Skip to content

check-release-section-coverage --self-test reports a FALSE floor-mismatch when run from any cwd but the repo root — a could-not-read rendered as a verdict about another gate #13954

Description

@claude

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)

  1. 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.
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions