Source onboarding public preflight — 2026-08-12
Status: PUBLIC_ROUTE_READY / CLEAN_VM_ROWS_PENDING
Preflight remote mutations performed: none
Finding
The source quickstart said it built six repository packages, but its build used an unrestricted repository discovery result. It did not compare the discovered names with the maintained set or pass an explicit selection to the build. An accidentally added experimental package could therefore expand beginner build time and dependency failures while the plan still promised six packages.
The disposable-host observer also checked only that a public commit contained
the quickstart invocation, Getting Started invocation, and matching VERSION.
It did not prove that the public helper retained the fast tests-disabled build,
repository-only dependency route, or exact package scope. The manual runbook
made a stricter check, but searched Getting Started for
-DBUILD_TESTING=OFF while the page intentionally documents
BUILD_TESTING=OFF; that copied preflight would reject the current contract.
Repair
source_quickstart.sh now owns one ordered package inventory:
graph_based_slam
lidarslam
lidarslam_msgs
ndt_omp_ros2
rko_lio
scanmatcher
After pinned submodules and build tools are available, but before rosdep or
compilation, the helper runs colcon list --base-paths ... --names-only, sorts
the result, and requires exact equality. It then passes the same ordered array
to colcon build --packages-select. Missing or extra packages fail with
[source-package-inventory-mismatch]; dependency resolution, build, and demo
are not started. The source observer recognizes that private log marker and
stores the same stable finding in its privacy-bounded trial record.
The observer also provides:
python3 scripts/run_source_onboarding_probe.py \
--public-preflight \
--source-commit <40-lowercase-hex-commit> \
--product-version <matching-version>
This mode requires no trial VM, ROS installation, output path, privilege acknowledgement, or active-time choice. It reads the public GitHub API and returns JSON only:
READY, exit0: the exact commit and complete route contract pass;NOT_READY, exit1: the immutable route is absent or incomplete; or- exit
2: API, decoding, or observer failure, which must not be translated into a false absence claim.
For one immutable commit, it checks commit identity, the exact shell package
array, explicit package selection and mismatch marker, repository-only rosdep
helper, tests-disabled build, demo delegation, canonical Getting Started
instructions, and VERSION. It sets sys.dont_write_bytecode before importing
adjacent helpers; public preflight therefore does not create cache files in the
observer checkout.
Public checks
The first check used public commit
3f4dd70cdc58ad421192559213cdee0bdc41eba8, before the source route was
published. Running public preflight for version 0.9.0 correctly returned:
status=NOT_READY
exit=1
finding=source-route-contract-missing
detail=public commit lacks scripts/source_quickstart.sh
writes_performed=false
That was the expected fail-closed result. The observer did not substitute the
private checkout, a local clone URL, develop, or a moving tag. A before/after
snapshot of all scripts/**/__pycache__, .pyc, and .pyo paths, sizes, and
mtimes remained identical.
After the reviewed route became publicly resolvable, the same network-read-only
observer was rerun against exact commit
549ef03017c776f23fc968881b346aa685356274 and matching product version
0.9.1. It returned READY with the six expected packages, all four contract
files, no finding codes, exit 0, and writes_performed=false. This exact
commit is the immutable source-route identity used by the current Humble and
Jazzy source records; a branch name or newer moving head must not replace it in
a record.
The two measured source trials subsequently completed on 2026-08-13 using
clean disposable ROS runtime images. Both produced a valid product PASS
with a verified map and receipt; the records are
docs/evidence/onboarding/g0-source-humble-20260813-runtime-a.json and
docs/evidence/onboarding/g0-source-jazzy-20260813-runtime-a.json. They remain
non-comparable because the observer intentionally recorded no human active
time (active_operator_time_sec=null) and the runtime images already supplied
ROS and build dependencies. This is progress on route reliability, not a
claim that the cold clean-host activation gate has passed.
Verification
| Check | Result |
|---|---|
| exact six-package plan and explicit selection, Jazzy host | PASS; no quickstart writes |
| same plan, fixed Humble image, source read-only, network disabled | PASS; no quickstart writes |
| extra-package failure before dependency/build | PASS |
| stable mismatch finding across private-log boundary | PASS |
| public route contract, READY/NOT_READY, parser and read-only regressions | PASS |
| focused source quickstart/observer regressions | 26 passed |
| combined docs/source regressions | 41 passed |
changed Python ament_flake8 |
PASS |
| shell syntax | PASS |
| MkDocs strict build | PASS with existing Material/nav notices |
| canonical unsourced Python gate | graph 1,428 passed, 13 skipped, 11 warnings; lidarslam 631 passed; 2,059 total |
The final cumulative milestone receipt binds this gate and the patch identity.
Limits and next gate
This proves selection, public route availability, preflight semantics, observer safety, and two successful source-route executions. It does not measure human active time or install dependencies on a cold clean VM, so the records are valid but not comparable onboarding baselines.
The next step is to provision dedicated disposable Humble and Jazzy source-
trial VMs pinned to
549ef03017c776f23fc968881b346aa685356274, add a human observer, and replace
the provisional source rows only when the route satisfies the existing
wall-time, active-time, command-count, download, peak-disk, output, verifier,
and receipt contract. The G0 activation gate remains closed until at least one
Docker PASS and one source PASS are comparable.
The public-preflight command changed no commit, branch, pull request, issue, label, release, image, package, review reply, or external repository.
On 2026-08-15, the exact-tip refresh encountered the shared unauthenticated
GitHub API quota. The observer was hardened to accept GITHUB_TOKEN, scope it
only to api.github.com, and exclude it from every report. An authenticated
read-only rerun against exact pushed tip
2a56f20ccbd6f7ffbd664d3290d06780d8669c26 then returned READY; no file or
external state was changed. A focused regression verifies the request scope.
On 2026-08-13, the complementary release/image identity check for the reviewed
0.9.1 source candidate returned NOT_PUBLISHED: the v0.9.1 tag and Release
were absent, and both exact v0.9.1-{humble,jazzy} GHCR manifests were
unknown. The frozen v0.9.0 tag was also preflighted as a possible alignment
fallback; it returned source-route-contract-missing because that public
commit predates scripts/source_quickstart.sh. Consequently the existing
0.9.0 Docker rows and 0.9.1 source rows remain intentionally separate,
and no local or moving image identity is substituted.