Found while working #13757 (PR #13952). Out of scope there — that card is a docblock relabel
and is fenced to not touching the gate's logic — so recording it here instead.
What happens
scripts/check-release-section-coverage.mjs --self-test reads its sibling gate to pin the two
scope floors together. The path is repo-root-relative:
const SIBLING_GATE = 'scripts/check-release-page-status.mjs';
and the read sits inside a try { ... } catch { /* reported by the expect below */ }. So when
the process cwd is not the repo root, the read fails, siblingFloor stays null, and the
self-test reports a content verdict about the other gate:
x self-test: scope — the floor is READ from scripts/check-release-page-status.mjs and equals
this gate's (sibling: UNREADABLE, here: 16). Two gates reading the same pages under different
floors is two answers to one question, so the inheritance is pinned rather than declared in a
comment
check-release-section-coverage --self-test: 1 failure(s).
Repro — same commit, same clean tree, two cwds
$ cd /path/to/objectstack && node scripts/check-release-section-coverage.mjs --self-test
OK self-test: 41 cases pass ... # EXIT=0
$ cd /path/to && node objectstack/scripts/check-release-section-coverage.mjs --self-test
x self-test: scope — ... (sibling: UNREADABLE, here: 16) ... # EXIT=1
Verified at 71018fe16 with git status --porcelain empty.
Why it is worth a card
The failure is not "I could not read a file" — it is a confidently wrong verdict about a
different gate, in the exact prose a real cross-gate floor drift would produce. A reader who
hits it goes looking for drift in check-release-page-status.mjs that is not there.
It is the family of #13885 (a gate signalling "nothing measured" with the exit code the repo
reserves for a real finding) and #13798 (self-tests that exit without reaching their verdict),
one step worse: this one reaches its verdict and the verdict is false. AGENTS.md already names
this class — a PREREQUISITE NOT MET / could-not-measure state must read as NOT MEASURED, never
as a finding. check-test-completeness.mjs is the in-repo model: it exits 3, distinct from
a finding's 1, and says in its own output that it is not a finding.
Cost paid: one ablation cycle on #13757 was scored against this false red before the cwd was
identified as the cause. The reading was void, not a measurement.
Possible remedies (not ruling between them)
- Resolve
SIBLING_GATE from import.meta.url rather than cwd, so the pin is cwd-independent.
Note AGENTS.md's cross-package-test-inputs spellings if that path would escape the package.
- Keep the relative path but drop the
catch, and let an unreadable sibling be a loud
prerequisite failure with its own exit code, in the check-test-completeness shape — so
"cannot read" never renders as "the floors disagree".
Option 1 removes the failure mode; option 2 keeps the verdict honest when it fires. They are
not exclusive.
Worth checking whether sibling gates in scripts/ share the shape — this was found by
accident, not by a sweep.
Generated by Claude Code
Generated by Claude Code
Found while working #13757 (PR #13952). Out of scope there — that card is a docblock relabel
and is fenced to not touching the gate's logic — so recording it here instead.
What happens
scripts/check-release-section-coverage.mjs --self-testreads its sibling gate to pin the twoscope floors together. The path is repo-root-relative:
and the read sits inside a
try { ... } catch { /* reported by the expect below */ }. So whenthe process cwd is not the repo root, the read fails,
siblingFloorstaysnull, and theself-test reports a content verdict about the other gate:
Repro — same commit, same clean tree, two cwds
Verified at
71018fe16withgit status --porcelainempty.Why it is worth a card
The failure is not "I could not read a file" — it is a confidently wrong verdict about a
different gate, in the exact prose a real cross-gate floor drift would produce. A reader who
hits it goes looking for drift in
check-release-page-status.mjsthat is not there.It is the family of #13885 (a gate signalling "nothing measured" with the exit code the repo
reserves for a real finding) and #13798 (self-tests that exit without reaching their verdict),
one step worse: this one reaches its verdict and the verdict is false. AGENTS.md already names
this class — a
PREREQUISITE NOT MET/ could-not-measure state must read as NOT MEASURED, neveras a finding.
check-test-completeness.mjsis the in-repo model: it exits 3, distinct froma finding's 1, and says in its own output that it is not a finding.
Cost paid: one ablation cycle on #13757 was scored against this false red before the cwd was
identified as the cause. The reading was void, not a measurement.
Possible remedies (not ruling between them)
SIBLING_GATEfromimport.meta.urlrather than cwd, so the pin is cwd-independent.Note AGENTS.md's cross-package-test-inputs spellings if that path would escape the package.
catch, and let an unreadable sibling be a loudprerequisite failure with its own exit code, in the
check-test-completenessshape — so"cannot read" never renders as "the floors disagree".
Option 1 removes the failure mode; option 2 keeps the verdict honest when it fires. They are
not exclusive.
Worth checking whether sibling gates in
scripts/share the shape — this was found byaccident, not by a sweep.
Generated by Claude Code
Generated by Claude Code