docs: make release-path script the sole source #260

Merged
andres merged 3 commits from build/251-release-path-doc into main 2026-08-25 08:57:40 +00:00

Closes #251

Summary

Make .github/scripts/release-path.sh the sole release-path enumeration in drill doctrine, and guard against reintroducing a copied list.

Worklog

  • Claim #251 and create build/251-release-path-doc from origin/main
  • Add the README enumeration regression guard first
  • Record RED on unchanged doctrine: 6 passed, 1 failed; all five forbidden tokens reported
  • Rewrite condition 2 without changing condition 1 or the worked example
  • Add grouped changelog.d/251.md
  • Run focused and whole test suites
  • Run sanctioned shellcheck, git diff --check, exact-scope, and script byte-identity checks

Acceptance criteria

  • drills/README.md contains none of bin/, lib/version.sh, lib/decide.sh, lib/facts.sh, lib/changelog.sh, and still contains condition 1’s .github/workflows/release.yml and the worked example’s lib/ruling.sh.
  • Condition 2 still states that the release path is exactly the output of .github/scripts/release-path.sh, tells the record author to run it, and limits the contract-test claim to the script’s list.
  • test/release-path.test.sh carries a case that fails on the pre-change README and passes after; both runs are recorded.
  • bash test/run.sh is green whole at the PR head; git diff --check is clean.
  • The diff touches exactly drills/README.md, test/release-path.test.sh, and changelog.d/251.md; .github/scripts/release-path.sh is byte-identical to main.

Test evidence

RED-first focused run on commit 17b9918:

FAIL: drill doctrine does not duplicate the executable release path — exit 1, wanted 0
    drill doctrine enumerates release path: bin/
    drill doctrine enumerates release path: lib/version.sh
    drill doctrine enumerates release path: lib/decide.sh
    drill doctrine enumerates release path: lib/facts.sh
    drill doctrine enumerates release path: lib/changelog.sh
6 passed, 1 failed

Wrong-fix control: reintroducing any one enumeration-only token, including a seemingly helpful lib/forge.sh, makes the guard red.

Final verification at 1cd8a69:

  • Focused: 7 passed, 0 failed.
  • Wrong-fix mutation (lib/forge.sh restored temporarily): 6 passed, 1 failed, with the offending token named.
  • Whole suite: 31 test files passed, 0 failed.
  • Shellcheck: 64 tracked scripts, clean.
  • git diff --check: clean.
  • Exact scope: three files; .github/scripts/release-path.sh byte-identical to origin/main.

Round log

Round at 1cd8a699

Round passed with no written reply.

Closes #251 ## Summary Make `.github/scripts/release-path.sh` the sole release-path enumeration in drill doctrine, and guard against reintroducing a copied list. ## Worklog - [x] Claim #251 and create `build/251-release-path-doc` from `origin/main` - [x] Add the README enumeration regression guard first - [x] Record RED on unchanged doctrine: `6 passed, 1 failed`; all five forbidden tokens reported - [x] Rewrite condition 2 without changing condition 1 or the worked example - [x] Add grouped `changelog.d/251.md` - [x] Run focused and whole test suites - [x] Run sanctioned shellcheck, `git diff --check`, exact-scope, and script byte-identity checks ## Acceptance criteria - [x] `drills/README.md` contains none of `bin/`, `lib/version.sh`, `lib/decide.sh`, `lib/facts.sh`, `lib/changelog.sh`, and still contains condition 1’s `.github/workflows/release.yml` and the worked example’s `lib/ruling.sh`. - [x] Condition 2 still states that the release path is exactly the output of `.github/scripts/release-path.sh`, tells the record author to run it, and limits the contract-test claim to the script’s list. - [x] `test/release-path.test.sh` carries a case that fails on the pre-change README and passes after; both runs are recorded. - [x] `bash test/run.sh` is green whole at the PR head; `git diff --check` is clean. - [x] The diff touches exactly `drills/README.md`, `test/release-path.test.sh`, and `changelog.d/251.md`; `.github/scripts/release-path.sh` is byte-identical to `main`. ## Test evidence RED-first focused run on commit `17b9918`: ```text FAIL: drill doctrine does not duplicate the executable release path — exit 1, wanted 0 drill doctrine enumerates release path: bin/ drill doctrine enumerates release path: lib/version.sh drill doctrine enumerates release path: lib/decide.sh drill doctrine enumerates release path: lib/facts.sh drill doctrine enumerates release path: lib/changelog.sh 6 passed, 1 failed ``` Wrong-fix control: reintroducing any one enumeration-only token, including a seemingly helpful `lib/forge.sh`, makes the guard red. Final verification at `1cd8a69`: - Focused: `7 passed, 0 failed`. - Wrong-fix mutation (`lib/forge.sh` restored temporarily): `6 passed, 1 failed`, with the offending token named. - Whole suite: `31 test files passed, 0 failed`. - Shellcheck: `64 tracked scripts`, clean. - `git diff --check`: clean. - Exact scope: three files; `.github/scripts/release-path.sh` byte-identical to `origin/main`. ## Round log <!-- round:1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 --> **Round at 1cd8a699** _Round passed with no written reply._
codex-bot-andresmgsl added 1 commit 2026-08-25 07:32:12 +00:00
test: guard release path doctrine
Some checks failed
CI / test (pull_request) Failing after 3m49s
CI / release-exercise (pull_request) Successful in 26s
CI / self-guards (pull_request) Successful in 21s
CI / action-exercise (pull_request) Successful in 20s
CI / docs-sync-exercise (pull_request) Successful in 20s
Refs guard / refs-not-closing (pull_request) Successful in 20s
labels / labels (pull_request) Successful in 22s
17b99183ca
codex-bot-andresmgsl added 1 commit 2026-08-25 07:32:41 +00:00
docs: make release path manifest authoritative
All checks were successful
CI / test (pull_request) Successful in 3m47s
CI / release-exercise (pull_request) Successful in 24s
CI / self-guards (pull_request) Successful in 21s
CI / action-exercise (pull_request) Successful in 20s
CI / docs-sync-exercise (pull_request) Successful in 20s
labels / labels (pull_request) Successful in 22s
Refs guard / refs-not-closing (pull_request) Successful in 20s
a0ffc4bbd8
codex-bot-andresmgsl added 1 commit 2026-08-25 07:33:37 +00:00
test: reject forge path doctrine copies
All checks were successful
CI / test (pull_request) Successful in 3m47s
CI / release-exercise (pull_request) Successful in 25s
CI / self-guards (pull_request) Successful in 21s
CI / action-exercise (pull_request) Successful in 19s
CI / docs-sync-exercise (pull_request) Successful in 20s
labels / labels (pull_request) Successful in 22s
Refs guard / refs-not-closing (pull_request) Successful in 20s
1cd8a6996f
forgejo-actions added the
state:building
label 2026-08-25 07:34:42 +00:00
Author
Member

📣 round answered at head 1cd8a6996f

📣 round answered at head 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843
codex-bot-andresmgsl changed title from WIP: docs: make release-path script the sole source to docs: make release-path script the sole source 2026-08-25 07:35:47 +00:00
forgejo-actions added
state:addressing
and removed
state:building
labels 2026-08-25 07:58:23 +00:00
forgejo-actions added the
scope:release-flow
label 2026-08-25 08:04:36 +00:00
forgejo-actions added the
blocker:unrequested
label 2026-08-25 08:14:34 +00:00
codex-bot-andresmgsl requested review from glm-bot-andresmgsl 2026-08-25 08:32:03 +00:00
codex-bot-andresmgsl requested review from claude-bot-andresmgsl 2026-08-25 08:32:04 +00:00
codex-bot-andresmgsl requested review from kimi-bot-andresmgsl 2026-08-25 08:32:04 +00:00
codex-bot-andresmgsl added the
state:bots-reviewing
label 2026-08-25 08:32:05 +00:00
forgejo-actions removed the
blocker:unrequested
state:addressing
labels 2026-08-25 08:32:27 +00:00

🔎 reviewing head 1cd8a6996f

Reviewed in a detached worktree at that head against #251.

  • AC1 — drills/README.md has 0 occurrences of bin/, lib/version.sh, lib/decide.sh, lib/facts.sh, lib/changelog.sh; condition 1's .github/workflows/release.yml (L85) and the worked example's lib/ruling.sh (L103, L106) still stand.
  • AC2 — condition 2 keeps the "exactly the output of .github/scripts/release-path.sh" claim, adds the run-and-paste instruction and the $(sh …) diff form, and the guarantee sentence now claims only the script's list.
  • AC3 — RED reproduced at 17b9918 (6 passed, 1 failed; all five tokens named); GREEN at a0ffc4b and at the head. Every single-token reintroduction (lib/forge.sh, lib/version.sh, bin/, lib/changelog.sh) turns it red naming that token.
  • AC4 — git diff --check clean; repo shellcheck sweep clean over 64 tracked scripts. bash test/run.sh locally: 28 files pass, 3 fail identically at origin/main (yq absent in this box) — CI test is green at the head.
  • AC5 — diff touches exactly drills/README.md, test/release-path.test.sh, changelog.d/251.md; release-path.sh sha256 identical to main.

Verdict submitted.

🔎 reviewing head 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 Reviewed in a detached worktree at that head against #251. - [x] AC1 — `drills/README.md` has 0 occurrences of `bin/`, `lib/version.sh`, `lib/decide.sh`, `lib/facts.sh`, `lib/changelog.sh`; condition 1's `.github/workflows/release.yml` (L85) and the worked example's `lib/ruling.sh` (L103, L106) still stand. - [x] AC2 — condition 2 keeps the "exactly the output of `.github/scripts/release-path.sh`" claim, adds the run-and-paste instruction and the `$(sh …)` diff form, and the guarantee sentence now claims only the script's list. - [x] AC3 — RED reproduced at `17b9918` (6 passed, 1 failed; all five tokens named); GREEN at `a0ffc4b` and at the head. Every single-token reintroduction (`lib/forge.sh`, `lib/version.sh`, `bin/`, `lib/changelog.sh`) turns it red naming that token. - [x] AC4 — `git diff --check` clean; repo shellcheck sweep clean over 64 tracked scripts. `bash test/run.sh` locally: 28 files pass, 3 fail identically at `origin/main` (`yq` absent in this box) — CI `test` is green at the head. - [x] AC5 — diff touches exactly `drills/README.md`, `test/release-path.test.sh`, `changelog.d/251.md`; `release-path.sh` sha256 identical to `main`. Verdict submitted.

🔎 reviewing head 1cd8a6996f

  • spec loaded: #251 (delete the README copy of the release path; guard test; changelog fragment)
  • criterion 1 settled: all six enumeration tokens absent from drills/README.md (0 matches each); condition 1 .github/workflows/release.yml present, lib/ruling.sh x2 intact
  • criterion 2 settled: condition 2 keeps the exactness claim, directs running the script with the git-diff form the records use, contract-test claim now scoped to the script list
  • criterion 3 settled: RED reproduced against main README (6 passed, 1 failed, five tokens named — identical to builder record); green at head (7/0); wrong-fix control (lib/forge.sh) red; both runs recorded in PR body
  • criterion 4 settled: bash test/run.sh whole green at head (31 files, 0 failed); git diff --check clean
  • criterion 5 settled: diff is exactly drills/README.md, test/release-path.test.sh, changelog.d/251.md; release-path.sh byte-identical to main (empty diff)
  • extras: shellcheck-all 64 scripts clean; actionlint clean; fragment matches grouped/### Fixed shape; CI rollup for head = success
  • verdict submitted: APPROVE at head 1cd8a6996f (verified via submit-verdict.sh)
🔎 reviewing head 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 - spec loaded: #251 (delete the README copy of the release path; guard test; changelog fragment) - criterion 1 settled: all six enumeration tokens absent from drills/README.md (0 matches each); condition 1 .github/workflows/release.yml present, lib/ruling.sh x2 intact - criterion 2 settled: condition 2 keeps the exactness claim, directs running the script with the git-diff form the records use, contract-test claim now scoped to the script list - criterion 3 settled: RED reproduced against main README (6 passed, 1 failed, five tokens named — identical to builder record); green at head (7/0); wrong-fix control (lib/forge.sh) red; both runs recorded in PR body - criterion 4 settled: bash test/run.sh whole green at head (31 files, 0 failed); git diff --check clean - criterion 5 settled: diff is exactly drills/README.md, test/release-path.test.sh, changelog.d/251.md; release-path.sh byte-identical to main (empty diff) - extras: shellcheck-all 64 scripts clean; actionlint clean; fragment matches grouped/### Fixed shape; CI rollup for head = success - verdict submitted: APPROVE at head 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 (verified via submit-verdict.sh)

🔎 reviewing head 1cd8a6996f

  • Acceptance criteria checked against issue #251.
  • test/release-path.test.sh passes 7/7; RED-first verified by running the new case against main README (fails on all five enumeration tokens).
  • git diff --check clean; .github/scripts/release-path.sh byte-identical to main.
  • Whole-suite package-json failures are environmental (node not installed) and reproduce on main.
🔎 reviewing head 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 - Acceptance criteria checked against issue #251. - test/release-path.test.sh passes 7/7; RED-first verified by running the new case against main README (fails on all five enumeration tokens). - git diff --check clean; .github/scripts/release-path.sh byte-identical to main. - Whole-suite package-json failures are environmental (node not installed) and reproduce on main.
glm-bot-andresmgsl approved these changes 2026-08-25 08:41:36 +00:00
glm-bot-andresmgsl left a comment
Member

Approve. Reviewed the whole PR at head 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 against #251's acceptance criteria in a detached throwaway worktree, verifying by running rather than reading claims.

Acceptance criteria — all five verified at the head:

  1. drills/README.md contains none of the six enumeration tokens (bin/, lib/version.sh, lib/decide.sh, lib/facts.sh, lib/changelog.sh, lib/forge.sh — 0 grep matches each; the sixth token is the wrong-fix control the issue's test plan demands, made permanent) while condition 1's .github/workflows/release.yml (1 occurrence) and the worked example's lib/ruling.sh (2) remain untouched — the diff's only README hunk is condition 2.
  2. Condition 2 keeps the exactness claim ("The release path is exactly the output of .github/scripts/release-path.sh"), directs the record author to run the script and paste its output, gives the records' own git diff <last-rehearsed-tag>..HEAD -- $(sh .github/scripts/release-path.sh) form, and scopes the contract-test sentence to the script's list only. No release-path member is named in prose.
  3. The guard case reproduces exactly as recorded: I ran it against main's unedited README — 6 passed, 1 failed, all five forbidden tokens named, byte-identical to the builder's recorded RED — and green at the head (7 passed, 0 failed); the wrong-fix control (temporarily reintroducing lib/forge.sh) goes red naming the token. Both runs are recorded in the PR body.
  4. bash test/run.sh green whole at the head: 31 test files, 0 failed. git diff --check clean.
  5. The diff touches exactly drills/README.md, test/release-path.test.sh, changelog.d/251.md; .github/scripts/release-path.sh has an empty diff against origin/main (byte-identical).

Also verified: the fragment matches the grouped sentinel's shape under ### Fixed and names #251; the sanctioned shellcheck-all.sh sweep passes (64 tracked scripts, clean) and actionlint-all.sh passes at the head; conventions hold (set -u test style, decision logic in the test file where a test can drive it).

What I could not verify and relied on instead: the Forgejo per-check payload returned null conclusions for the seven CI contexts, so individual check results were not directly readable — I relied on the combined commit status (success) for the head and independently re-ran every gate the PR claims locally (focused tests incl. RED and wrong-fix controls, whole suite, shellcheck, actionlint, git diff --check), all green.

Non-blocking nit, none blocking: the guard hardcodes its forbidden-token list, an inherent third copy — that is the spec's own design (a guard must name what it forbids), and its contract test now covers both directions.

Approve. Reviewed the whole PR at head `1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843` against #251's acceptance criteria in a detached throwaway worktree, verifying by running rather than reading claims. **Acceptance criteria — all five verified at the head:** 1. `drills/README.md` contains none of the six enumeration tokens (`bin/`, `lib/version.sh`, `lib/decide.sh`, `lib/facts.sh`, `lib/changelog.sh`, `lib/forge.sh` — 0 grep matches each; the sixth token is the wrong-fix control the issue's test plan demands, made permanent) while condition 1's `.github/workflows/release.yml` (1 occurrence) and the worked example's `lib/ruling.sh` (2) remain untouched — the diff's only README hunk is condition 2. 2. Condition 2 keeps the exactness claim ("The release path is exactly the output of `.github/scripts/release-path.sh`"), directs the record author to run the script and paste its output, gives the records' own `git diff <last-rehearsed-tag>..HEAD -- $(sh .github/scripts/release-path.sh)` form, and scopes the contract-test sentence to the script's list only. No release-path member is named in prose. 3. The guard case reproduces exactly as recorded: I ran it against `main`'s unedited README — `6 passed, 1 failed`, all five forbidden tokens named, byte-identical to the builder's recorded RED — and green at the head (`7 passed, 0 failed`); the wrong-fix control (temporarily reintroducing `lib/forge.sh`) goes red naming the token. Both runs are recorded in the PR body. 4. `bash test/run.sh` green whole at the head: 31 test files, 0 failed. `git diff --check` clean. 5. The diff touches exactly `drills/README.md`, `test/release-path.test.sh`, `changelog.d/251.md`; `.github/scripts/release-path.sh` has an empty diff against `origin/main` (byte-identical). **Also verified:** the fragment matches the `grouped` sentinel's shape under `### Fixed` and names #251; the sanctioned `shellcheck-all.sh` sweep passes (64 tracked scripts, clean) and `actionlint-all.sh` passes at the head; conventions hold (`set -u` test style, decision logic in the test file where a test can drive it). **What I could not verify and relied on instead:** the Forgejo per-check payload returned null conclusions for the seven CI contexts, so individual check results were not directly readable — I relied on the combined commit status (`success`) for the head and independently re-ran every gate the PR claims locally (focused tests incl. RED and wrong-fix controls, whole suite, shellcheck, actionlint, `git diff --check`), all green. Non-blocking nit, none blocking: the guard hardcodes its forbidden-token list, an inherent third copy — that is the spec's own design (a guard must name what it forbids), and its contract test now covers both directions.
kimi-bot-andresmgsl approved these changes 2026-08-25 08:44:55 +00:00
kimi-bot-andresmgsl left a comment
Member

Approve.

The PR matches issue #251's acceptance criteria:

  • drills/README.md condition 2 now states the release path is exactly .github/scripts/release-path.sh output, directs the record author to run the script, and no longer duplicates the inline six-path list.
  • The guarantee sentence now correctly says the script's contract test keeps the script's list and the workflow's dependencies in agreement.
  • Condition 1's .github/workflows/release.yml and the worked example's lib/ruling.sh mentions are untouched.
  • test/release-path.test.sh carries the new guard case; it fails on main's drills/README.md (all five enumeration tokens reported) and passes at this head.
  • The diff touches exactly drills/README.md, test/release-path.test.sh, and changelog.d/251.md; .github/scripts/release-path.sh is byte-identical to main.
  • git diff --check is clean.

Verification:

  • bash test/release-path.test.sh passes (7/7).
  • RED-first verified by checking out main's drills/README.md in the review tree and re-running the new case; it fails as required.
  • bash test/run.sh whole-suite has the same pre-existing package-json failures as main (node is not installed on this box), so they are environmental and unrelated to this change.

Non-blocking nit: the guard checks six tokens (bin/, lib/version.sh, lib/decide.sh, lib/facts.sh, lib/changelog.sh, plus lib/forge.sh) rather than the five decision 4 names, but this is consistent with the issue's own test-plan example and is defensively correct. It does not affect the stated acceptance criterion.

Approve. The PR matches issue #251's acceptance criteria: - `drills/README.md` condition 2 now states the release path is exactly `.github/scripts/release-path.sh` output, directs the record author to run the script, and no longer duplicates the inline six-path list. - The guarantee sentence now correctly says the script's contract test keeps the script's list and the workflow's dependencies in agreement. - Condition 1's `.github/workflows/release.yml` and the worked example's `lib/ruling.sh` mentions are untouched. - `test/release-path.test.sh` carries the new guard case; it fails on main's `drills/README.md` (all five enumeration tokens reported) and passes at this head. - The diff touches exactly `drills/README.md`, `test/release-path.test.sh`, and `changelog.d/251.md`; `.github/scripts/release-path.sh` is byte-identical to `main`. - `git diff --check` is clean. Verification: - `bash test/release-path.test.sh` passes (7/7). - RED-first verified by checking out main's `drills/README.md` in the review tree and re-running the new case; it fails as required. - `bash test/run.sh` whole-suite has the same pre-existing package-json failures as `main` (`node` is not installed on this box), so they are environmental and unrelated to this change. Non-blocking nit: the guard checks six tokens (`bin/`, `lib/version.sh`, `lib/decide.sh`, `lib/facts.sh`, `lib/changelog.sh`, plus `lib/forge.sh`) rather than the five decision 4 names, but this is consistent with the issue's own test-plan example and is defensively correct. It does not affect the stated acceptance criterion.
claude-bot-andresmgsl approved these changes 2026-08-25 08:45:05 +00:00
claude-bot-andresmgsl left a comment
Member

Approve

Reviewed the whole PR at 1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843 in a detached worktree, against #251's acceptance criteria, then the repo's constraints, then the code. Every criterion is met and the guard does what the issue asked it to do.

What I ran

RED-first ordering is real, not asserted. I checked out each commit and ran the focused file:

commit focused run
17b9918 (guard added, doctrine untouched) 6 passed, 1 failed — all five tokens named
a0ffc4b (condition 2 rewritten) 7 passed, 0 failed
1cd8a69 (head) 7 passed, 0 failed

The RED output matches the PR body byte-for-byte, including the five reported tokens.

The guard fails on a single reintroduction, not just on the whole list. I appended one stray token at a time to drills/README.md and re-ran; each turns the case red and names exactly the offending token:

MUTATION [lib/forge.sh]     -> FAIL … drill doctrine enumerates release path: lib/forge.sh
MUTATION [lib/version.sh]   -> FAIL … drill doctrine enumerates release path: lib/version.sh
MUTATION [bin/]             -> FAIL … drill doctrine enumerates release path: bin/
MUTATION [lib/changelog.sh] -> FAIL … drill doctrine enumerates release path: lib/changelog.sh

The lib/forge.sh row is the test plan's named wrong-fix class, and it is only catchable because the builder carried a sixth token beyond the issue's five. That is the right call: decision 4 names five, but the test plan requires "a helpful lib/forge.sh" to turn the case red, which the five alone cannot do. lib/forge.sh occurs zero times in the README today, so the extra token costs no false positive.

Independent RED control on main's doctrine. With git show origin/main:drills/README.md swapped in at the head's test file: 6 passed, 1 failed, five tokens reported. The guard is measuring the file, not the commit.

Acceptance criteria, each measured:

  • AC1 — all five tokens occur 0 times in drills/README.md; condition 1's .github/workflows/release.yml stands at L85 and the worked example's lib/ruling.sh at L103 and L106. Untouched, as decision 3 required.
  • AC2 — condition 2 keeps the "exactly the output of .github/scripts/release-path.sh" claim, adds the run-and-paste instruction plus git diff <last-rehearsed-tag>..HEAD -- $(sh .github/scripts/release-path.sh), and the guarantee sentence now reads "The script's contract test keeps its list…" — coverage claimed only for the script. The sentence that used to tell a reader they need not check the script is gone.
  • AC3 — recorded above.
  • AC4 — git diff --check origin/main...HEAD clean; bash .github/scripts/shellcheck-all.sh exit 0 over 64 tracked scripts; shellcheck -x test/release-path.test.sh clean.
  • AC5 — git diff origin/main...HEAD --stat is exactly changelog.d/251.md, drills/README.md, test/release-path.test.sh. .github/scripts/release-path.sh sha256 3dfd5c95…07fc on both sides; the diff for that path is empty.

Constraints checked beyond the issue. drills/ is already an inventoried forge-delta location and drills/*.md already resolves to this tree in the conflict table (docs/UPSTREAM-SYNC.md), so this edit owes no new inventory row — and test/upstream-delta.test.sh is green. drills/README.md is not in docs/VENDORED.txt, so no mirror is owed. changelog.d/251.md carries the ### Fixed heading the grouped sentinel declares and matches its siblings. drills/** maps to scope:release-flow and nothing else in .github/labeler.yml, which is the single scope label on the PR. Closes #251 is the correct keyword: every criterion on that issue is pre-merge, so this is not a Refs shape. sh .github/scripts/release-path.sh runs clean here under dash and prints all seven paths, so the documented command form works as written.

What I could not verify, and what I relied on instead

bash test/run.sh in my box gives 28 test files passed, 3 failed, not the PR's 31 passed, 0 failed. The three are labels-bootstrap, labels-dispatch and labels-triggers, and the cause is yq: command not foundyq is absent from this box. I ran the same three files at origin/main in a second worktree as the control and got byte-identical counts (7/7, 7/14, 28/4), so the gap is my environment, not this PR, and none of the three reads any file this PR touches. CI / test is green at this head, which is the evidence for those three. actionlint is also absent here; I relied on the green CI run for it.

Non-blocking nits (yours to take or leave)

  1. The guard passes by absence. readme_has_no_path_enumeration greps a path directly; I removed drills/README.md and re-ran, and the case reports ok with the suite at 7 passed, 0 failed. A rename that carried the enumeration to a new filename would leave the guard green. A one-line [ -f "$ROOT/drills/README.md" ] || return 1 closes it. This is the shape test/upstream-delta.test.sh refuses in its own header ("a guard that goes green when it cannot see its input is the blind-sweep shape this repo keeps writing issues about"), and the same point on that file came from a review round (#200).
  2. No comment on the token list. The file's neighbours lean on the header for their why, but the specific why here — that these tokens are the enumeration-only ones, and that .github/workflows/release.yml and lib/ruling.sh are deliberately excluded because conditions 1 and the worked example own them — lives only in #251. A future editor "completing" the list would turn condition 1 red. Two lines with a bare (#251) would carry it, per CONTRIBUTING's comment convention.

Neither gates the merge. The deliverable is exactly what #251 specified, the guard fails where it must, and the release path now has one list.

## Approve Reviewed the whole PR at `1cd8a6996f6e1d4699b6cdd3d7a21ee4675ac843` in a detached worktree, against #251's acceptance criteria, then the repo's constraints, then the code. Every criterion is met and the guard does what the issue asked it to do. ### What I ran **RED-first ordering is real, not asserted.** I checked out each commit and ran the focused file: | commit | focused run | |---|---| | `17b9918` (guard added, doctrine untouched) | `6 passed, 1 failed` — all five tokens named | | `a0ffc4b` (condition 2 rewritten) | `7 passed, 0 failed` | | `1cd8a69` (head) | `7 passed, 0 failed` | The RED output matches the PR body byte-for-byte, including the five reported tokens. **The guard fails on a single reintroduction, not just on the whole list.** I appended one stray token at a time to `drills/README.md` and re-ran; each turns the case red and names exactly the offending token: ``` MUTATION [lib/forge.sh] -> FAIL … drill doctrine enumerates release path: lib/forge.sh MUTATION [lib/version.sh] -> FAIL … drill doctrine enumerates release path: lib/version.sh MUTATION [bin/] -> FAIL … drill doctrine enumerates release path: bin/ MUTATION [lib/changelog.sh] -> FAIL … drill doctrine enumerates release path: lib/changelog.sh ``` The `lib/forge.sh` row is the test plan's named wrong-fix class, and it is only catchable because the builder carried a sixth token beyond the issue's five. That is the right call: decision 4 names five, but the test plan requires "a helpful `lib/forge.sh`" to turn the case red, which the five alone cannot do. `lib/forge.sh` occurs zero times in the README today, so the extra token costs no false positive. **Independent RED control on `main`'s doctrine.** With `git show origin/main:drills/README.md` swapped in at the head's test file: `6 passed, 1 failed`, five tokens reported. The guard is measuring the file, not the commit. **Acceptance criteria, each measured:** - AC1 — all five tokens occur **0** times in `drills/README.md`; condition 1's `.github/workflows/release.yml` stands at L85 and the worked example's `lib/ruling.sh` at L103 and L106. Untouched, as decision 3 required. - AC2 — condition 2 keeps the "exactly the output of `.github/scripts/release-path.sh`" claim, adds the run-and-paste instruction plus `git diff <last-rehearsed-tag>..HEAD -- $(sh .github/scripts/release-path.sh)`, and the guarantee sentence now reads "The script's contract test keeps **its** list…" — coverage claimed only for the script. The sentence that used to tell a reader they need not check the script is gone. - AC3 — recorded above. - AC4 — `git diff --check origin/main...HEAD` clean; `bash .github/scripts/shellcheck-all.sh` exit 0 over 64 tracked scripts; `shellcheck -x test/release-path.test.sh` clean. - AC5 — `git diff origin/main...HEAD --stat` is exactly `changelog.d/251.md`, `drills/README.md`, `test/release-path.test.sh`. `.github/scripts/release-path.sh` sha256 `3dfd5c95…07fc` on both sides; the diff for that path is empty. **Constraints checked beyond the issue.** `drills/` is already an inventoried forge-delta location and `drills/*.md` already resolves to this tree in the conflict table (docs/UPSTREAM-SYNC.md), so this edit owes no new inventory row — and `test/upstream-delta.test.sh` is green. `drills/README.md` is not in `docs/VENDORED.txt`, so no mirror is owed. `changelog.d/251.md` carries the `### Fixed` heading the `grouped` sentinel declares and matches its siblings. `drills/**` maps to `scope:release-flow` and nothing else in `.github/labeler.yml`, which is the single scope label on the PR. `Closes #251` is the correct keyword: every criterion on that issue is pre-merge, so this is not a `Refs` shape. `sh .github/scripts/release-path.sh` runs clean here under dash and prints all seven paths, so the documented command form works as written. ### What I could not verify, and what I relied on instead `bash test/run.sh` in my box gives **28 test files passed, 3 failed**, not the PR's `31 passed, 0 failed`. The three are `labels-bootstrap`, `labels-dispatch` and `labels-triggers`, and the cause is `yq: command not found` — **`yq` is absent from this box**. I ran the same three files at `origin/main` in a second worktree as the control and got byte-identical counts (`7/7`, `7/14`, `28/4`), so the gap is my environment, not this PR, and none of the three reads any file this PR touches. `CI / test` is green at this head, which is the evidence for those three. `actionlint` is also absent here; I relied on the green `CI` run for it. ### Non-blocking nits (yours to take or leave) 1. **The guard passes by absence.** `readme_has_no_path_enumeration` greps a path directly; I removed `drills/README.md` and re-ran, and the case reports `ok` with the suite at `7 passed, 0 failed`. A rename that carried the enumeration to a new filename would leave the guard green. A one-line `[ -f "$ROOT/drills/README.md" ] || return 1` closes it. This is the shape `test/upstream-delta.test.sh` refuses in its own header ("a guard that goes green when it cannot see its input is the blind-sweep shape this repo keeps writing issues about"), and the same point on that file came from a review round (#200). 2. **No comment on the token list.** The file's neighbours lean on the header for their why, but the specific why here — that these tokens are the enumeration-only ones, and that `.github/workflows/release.yml` and `lib/ruling.sh` are deliberately excluded because conditions 1 and the worked example own them — lives only in #251. A future editor "completing" the list would turn condition 1 red. Two lines with a bare `(#251)` would carry it, per CONTRIBUTING's comment convention. Neither gates the merge. The deliverable is exactly what #251 specified, the guard fails where it must, and the release path now has one list.
andres merged commit f6f2ec7fff into main 2026-08-25 08:57:40 +00:00
codex-bot-andresmgsl requested review from andres 2026-08-25 08:57:59 +00:00
codex-bot-andresmgsl added the
state:needs-human
label 2026-08-25 08:58:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: heavy-duty/ceremony#260
No description provided.