From dd12e49f2f8474c038546373fdb6953a00845aaa Mon Sep 17 00:00:00 2001 From: Yeachan-Heo Date: Tue, 26 May 2026 00:33:06 +0000 Subject: [PATCH] Protect ROADMAP helper missing-path behavior Add the missing explicit-path regression so operators keep the current fail-fast contract covered, and record the completed ROADMAP follow-up. Constraint: scope limited to ROADMAP helper regression coverage plus the DONE roadmap entry; tests/__init__.py is included so the requested python -m unittest tests.test_roadmap_helpers invocation resolves locally instead of an external tests package. Rejected: changing roadmap-next-id.sh behavior | dogfood showed the script already returns the desired nonzero empty-stdout error. Confidence: high Scope-risk: narrow Directive: Keep stdout reserved for the single next id on successful roadmap-next-id.sh runs. Tested: python -m unittest tests.test_roadmap_helpers -q; scripts/roadmap-check-ids.sh ROADMAP.md; scripts/roadmap-next-id.sh ROADMAP.md; git diff --check -- ROADMAP.md tests/test_roadmap_helpers.py tests/__init__.py --- ROADMAP.md | 2 ++ tests/__init__.py | 0 tests/test_roadmap_helpers.py | 11 +++++++++++ 3 files changed, 13 insertions(+) create mode 100644 tests/__init__.py diff --git a/ROADMAP.md b/ROADMAP.md index 89ff2be33f..426482da6f 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7617,3 +7617,5 @@ Original filing (2026-04-18): the session emitted `SessionStart hook (completed) 724. **DONE — ROADMAP duplicate-id validation guard for helper-era append collisions** — follow-up to #723 after dogfood showed `scripts/roadmap-next-id.sh` still printed 724 and exited 0 when a temp ROADMAP copy already contained a second `723. ...` line. This PR closes the gap for new optimistic-append collisions by adding `scripts/roadmap-check-ids.sh`, wiring it into docs CI and the local pre-push hook, documenting the pre-push command in CONTRIBUTING, and mentioning the guard from `roadmap-next-id.sh`. The guard defaults to ids >=723 so current historical roadmap content and old numbered lists do not block docs-only PRs; `--min-id 1` is available for a strict whole-file audit once legacy collisions are cleaned up. **Verification:** `scripts/roadmap-check-ids.sh` passes on current ROADMAP; a temp copy with an appended duplicate `723.` fails nonzero and lists duplicate id 723 with line numbers. Source: Jobdori dogfood follow-up on origin/main `922c2398`, 2026-05-25. [SCOPE: docs/scripts] 725. **DONE — roadmap-next-id helper now fails closed on helper-era duplicate ids before printing a next id** — follow-up to #724 after dogfood on origin/main 25ee5f3d showed `scripts/roadmap-next-id.sh` could print `1000` and exit 0 when a temp ROADMAP copy already contained two `999.` helper-era entries. This PR makes `roadmap-next-id.sh` resolve `roadmap-check-ids.sh` by its own script directory, run the checker with default helper-era min-id semantics before computing `highest+1`, keep stdout reserved for the single next id on success, and fail closed with a useful error if the checker is unavailable. Added focused pytest coverage for clean next-id output, duplicate fail-fast behavior, and missing-checker fail-closed behavior. **Verification:** `scripts/roadmap-next-id.sh ROADMAP.md` prints `725`; `scripts/roadmap-check-ids.sh ROADMAP.md` passes; a temp ROADMAP with duplicate `999.` exits nonzero and lists duplicate id 999 without printing a next id; `bash -n scripts/roadmap-next-id.sh scripts/roadmap-check-ids.sh` passes; `python -m pytest tests/test_roadmap_helpers.py -q` passes. Source: Jobdori dogfood follow-up on origin/main 25ee5f3d. [SCOPE: docs/scripts] + +726. **DONE — roadmap-next-id helper missing explicit ROADMAP path behavior is regression-tested** — follow-up to #725 after dogfood on origin/main 49d5b3fc showed the helper already failed correctly for `scripts/roadmap-next-id.sh /tmp/nonexistent-roadmap` but tests only covered clean next-id output, duplicate fail-fast behavior, and missing-checker fail-closed behavior. This PR adds focused unittest coverage proving a missing explicit ROADMAP path exits nonzero, keeps stdout empty, and reports both `ROADMAP not found` and the requested path on stderr. **Verification:** `python -m unittest tests.test_roadmap_helpers -q`; `scripts/roadmap-check-ids.sh ROADMAP.md`; `scripts/roadmap-next-id.sh ROADMAP.md`. Source: Jobdori dogfood follow-up on origin/main 49d5b3fc. [SCOPE: docs/scripts] diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/test_roadmap_helpers.py b/tests/test_roadmap_helpers.py index 0169f88cc5..b674836187 100644 --- a/tests/test_roadmap_helpers.py +++ b/tests/test_roadmap_helpers.py @@ -46,6 +46,17 @@ def test_roadmap_next_id_fails_fast_on_helper_era_duplicate(self) -> None: self.assertIn('999', result.stderr) self.assertNotIn('1000', result.stdout) + def test_roadmap_next_id_fails_when_explicit_roadmap_path_is_missing(self) -> None: + with tempfile.TemporaryDirectory() as temp_dir: + roadmap = Path(temp_dir) / 'missing-ROADMAP.md' + + result = run_next_id(roadmap) + + self.assertNotEqual(0, result.returncode) + self.assertEqual('', result.stdout) + self.assertIn('ROADMAP not found', result.stderr) + self.assertIn(str(roadmap), result.stderr) + def test_roadmap_next_id_fails_closed_when_checker_is_unavailable(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: script_dir = Path(temp_dir) / 'scripts'