Recording only — unassigned. Found while implementing #12877 (dev session, 2026-08-28); out of the file surface that card was dispatched with, so it is filed rather than fixed there.
What
The PR for #12877 adds bash scripts/pm/os-regen-merge.sh --self-test — 23 cases over synthetic fixture repos pinning the merge-side selection, the per-path notices, the non-staging spelling, the hand-off refusal, and the four pre-existing refusals. Nothing in .github/workflows/ runs it.
That is the same shape already recorded and fixed twice for other scripts — closed #11514 (.claude/hooks/*.selftest.sh matrices unrun) and closed #6008 (check:merge-driver's two --self-tests unrun). The direct sibling in the same directory does not have the gap: scripts/pm/os-verify-lock.sh --self-test runs as its own step in lint.yml.
Why it matters here specifically
os-regen-merge.sh has no CI path at all — its own header says so, and that is deliberate, since it is run by hand in an agent's or maintainer's worktree. But the self-test is a different thing from the script: it needs no worktree, no remote and no merge, only git and a temp dir. Left unwired, the pins go stale exactly the way the two closed findings above describe — the next refactor of the script reds nothing.
Two of the 23 cases are source scans of the script's own text (they assert step 2 keeps the non-staging git restore --source spelling and never the staging git checkout one). Those are precisely the rows a future edit would silently invalidate, and precisely the rows no reviewer reads.
Fix shape
One step in lint.yml, mirroring the existing verify-lock step:
- name: os-regen-merge self-testrun: bash scripts/pm/os-regen-merge.sh --self-test
Worth deciding at the same time whether the two scripts/pm/*.sh self-tests should share one collector step rather than accreting one step per script — lint.yml already carries a comment block about the .claude/hooks collector shape, which is the precedent for discovering them instead of listing them. A collector keyed on scripts/pm/*.sh --self-test would also stop the next such script from arriving unwired.
Runtime measured locally: the whole 23-case suite is a few seconds (it builds five small fixture repos).
Recording only — unassigned. Found while implementing #12877 (dev session, 2026-08-28); out of the file surface that card was dispatched with, so it is filed rather than fixed there.
What
The PR for #12877 adds
bash scripts/pm/os-regen-merge.sh --self-test— 23 cases over synthetic fixture repos pinning the merge-side selection, the per-path notices, the non-staging spelling, the hand-off refusal, and the four pre-existing refusals. Nothing in.github/workflows/runs it.That is the same shape already recorded and fixed twice for other scripts — closed #11514 (
.claude/hooks/*.selftest.shmatrices unrun) and closed #6008 (check:merge-driver's two--self-tests unrun). The direct sibling in the same directory does not have the gap:scripts/pm/os-verify-lock.sh --self-testruns as its own step inlint.yml.Why it matters here specifically
os-regen-merge.shhas no CI path at all — its own header says so, and that is deliberate, since it is run by hand in an agent's or maintainer's worktree. But the self-test is a different thing from the script: it needs no worktree, no remote and no merge, onlygitand a temp dir. Left unwired, the pins go stale exactly the way the two closed findings above describe — the next refactor of the script reds nothing.Two of the 23 cases are source scans of the script's own text (they assert step 2 keeps the non-staging
git restore --sourcespelling and never the staginggit checkoutone). Those are precisely the rows a future edit would silently invalidate, and precisely the rows no reviewer reads.Fix shape
One step in
lint.yml, mirroring the existing verify-lock step:Worth deciding at the same time whether the two
scripts/pm/*.shself-tests should share one collector step rather than accreting one step per script —lint.ymlalready carries a comment block about the.claude/hookscollector shape, which is the precedent for discovering them instead of listing them. A collector keyed onscripts/pm/*.sh --self-testwould also stop the next such script from arriving unwired.Runtime measured locally: the whole 23-case suite is a few seconds (it builds five small fixture repos).