Contributor product-surface synchronization — 2026-08-12
Status: LOCAL_PASS / PUBLICATION_PENDING
Remote mutations performed: none
Finding
CONTRIBUTING.md had retained a historical list of three “official” beginner
entrypoints. It directed a new contributor toward the older own-bag shell
wrapper and the NTU VIRAL source quickstart, while the current product contract
defines four workflows around lidarslam-map: fixed demo, own-bag mapping,
retained sessions, and privacy-bounded support handoff.
All named historical scripts still exist, so link-existence tests could not detect this semantic drift. A contributor changing user-visible behavior could therefore follow a working but non-canonical interface and unintentionally expand the supported surface.
Repair
The contributor guide now names exactly the four current workflows and their canonical commands. It also explains that the no-argument interactive home is a smaller front door to existing workflows, not a fifth workflow. Historical wrappers, direct launches, dataset-specific quickstarts, benchmarks, and research scripts are explicitly advanced or compatibility interfaces unless the product contract promotes them.
The docs-entrypoint regression now checks that:
- all four current workflow command spellings appear in
CONTRIBUTING.md; - the focused
run_product_python_tests.shpath remains discoverable; - the no-argument home is described without changing workflow count; and
- the old three-entrypoint and old official own-bag wording do not return.
Verification then exposed a second, executable drift. The contributor runner
auto-sourced ROS only for graph_based_slam, but current
lidarslam/test/test_sensor_setup_wizard.py also builds rosbag2 fixtures with
rosbag2_py. Running the documented --suite lidarslam route from an
unsourced shell therefore produced 612 passed, 10 failed instead of an
actionable preflight or a passing suite.
run_product_python_tests.sh now treats both maintained suites as ROS-backed.
It auto-discovers Humble or Jazzy for either suite, checks rosbag2_py before
collection, and rejects an unsupported declared ROS distribution consistently.
Its fake-environment contract test was changed from asserting that lidarslam
did not need ROS to proving that a missing binding stops before pytest.
The first canonical --suite all run then exposed a third drift at the test
registration boundary. The graph suite's invariant test reported that the new
lidarslam/test/test_cli_interactive_home.py file was not registered with
CTest. The runner still continued to the second package as designed, producing
1,427 passed, 13 skipped, 1 failed for graph and 622 passed for lidarslam
before returning failure. Adding test_cli_interactive_home to
LIDARSLAM_ADDITIONAL_PYTESTS closes that gap, so the same public command now
checks the new beginner-facing surface and its CTest discoverability together.
Verification
| Check | Result |
|---|---|
| docs-entrypoint regression | 15 passed |
| contributor focused lidarslam command | 7 passed, 615 deselected |
| contributor runner contract regression | 10 passed |
| contributor focused graph command after repair | 11 passed, 1,430 deselected |
| unsourced-shell contributor lidarslam command after repair | 622 passed |
initial unsourced-shell --suite all discovery run |
graph: 1,427 passed, 13 skipped, 1 failed; lidarslam: 622 passed; overall FAIL |
| focused CTest-registration regression after repair | 1 passed, 6 deselected |
final unsourced-shell --suite all gate |
graph: 1,428 passed, 13 skipped, 11 warnings; lidarslam: 622 passed; PASS: all |
ament_flake8 graph_based_slam/test/test_docs_entrypoints.py |
PASS |
ament_flake8 graph_based_slam/test/test_product_python_tests_script.py |
PASS |
bash -n scripts/run_product_python_tests.sh |
PASS |
mkdocs build --strict |
PASS with existing Material/nav notices |
git diff --check |
PASS |
The full and focused commands used the same public contributor entrypoint
documented in CONTRIBUTING.md, rather than relying only on a
maintainer-specific pytest invocation. The final full run removed ROS
environment variables first, observed automatic Jazzy selection, and passed
2,050 product tests across the two package-scoped processes, with 13 graph
tests skipped. It also preserved the runner's fail-after-both-suites behavior
during the initial CTest-registration failure, giving contributors one
complete result instead of stopping after the first package.
Limits and next gate
This closes the local documentation, dependency-preflight, and CTest registration drift; it does not prove that an external contributor finishes in 30 minutes. That metric still requires an authorized, published starter issue, a publicly resolvable candidate revision, and a privacy-bounded prepared-environment timing record. No issue, label, pull request, repository setting, or public documentation was changed here.