Skip to content

docs(pm): express the dispatch-gates self-test size as a floor, not a frozen reading - #13962

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-13536-selftest-count-docblock
Aug 31, 2026
Merged

docs(pm): express the dispatch-gates self-test size as a floor, not a frozen reading#13962
os-project-manager merged 1 commit into
mainfrom
claude/issue-13536-selftest-count-docblock

Conversation

@claude

@claude claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes #13536

The defect

The invokedDirectly docblock in scripts/pm/dispatch-gates.mjs sized this file's own self-test with a frozen literal:

That is the same defect PR #9897 fixed in check-governed-merges.mjs at 77 assertions; this file carries it at 334.

334 was a reading of cases.length — a number the self-test computes and prints at runtime. It had drifted to 1073, a factor of 3.2. The figure is load-bearing prose: it is the severity term in the argument for why a self-test must be a MODE of the file being run and never a side effect of importing it. Writing today's number would re-freeze the same defect one value later, which is exactly how the card describes the original mistake.

Zone 2 A — the history measurement that chose the shape

Question: has this file's self-test case count ever DECREASED across a commit?

Answer: no — not once, over the file's entire life.

Method. The runtime count is cases.length, accumulated by const t = (name, cond) => cases.push([name, cond]). Running the self-test at every historical commit is not affordable (a single run is 2–6 minutes on this shared box), so I used a static proxy — the count of t( call sites — and validated the proxy against the live run before trusting it:

reading value
static t( call sites at 9c4c431fd 1047
file-local loop expansions (below) +26
predicted runtime 1073
actual --self-test output 1073 cases pass

The +26 is fully accounted for, and every multiplier is a literal array in this file — no loop draws its population from the repo tree, so the printed count is a function of this file plus a few existsSync branches:

  • rootFileDeclarations (8 entries, 2 assertions each) +14
  • ['check:entry-guard', 'check:parse-guard'] (3 assertions each) +3
  • the 4-element fabricated list +3
  • ['check:docs', 'check:skill-refs'] +2
  • ['check:i18n', 'check:i18n-coverage'] +2
  • misparsedFamilySources, packageLedgerFamilySources (2 entries each) +1 each

Result over all 83 commits that have touched the file (2026-08-10 through 2026-08-31, git log --follow):

transitions count
increases 72
flat 10
decreases 0

The count went 14 to 1047 monotonically — it has never gone down.

Which shape that chose. The measurement clears option 2a (a bound). A lower bound stays true under a count that only ever grows, and it keeps the severity term the argument needs, which dropping the figure entirely would blunt. So: a floor, phrased as a multiple of the 77 already in the sentence — "more than ten times that many". Live ratio is 1073/77 = 13.9, so the floor carries ~39% headroom, and by the history measurement that headroom only widens.

Two smaller findings pushed the same way. The printed number is not even a pure function of this file — eight assertions sit behind if (existsSync(...)) branches, so the same commit can print different totals in different checkouts. And the count moves on 88% of commits here (72 of 82 transitions). Both make an exact figure doubly unfreezable.

Zone 2 B — occurrence count

334 appears exactly once in the file, re-derived on current origin/main (9c4c431fd) after PR #13930 landed. PM reading confirmed; the replace-one was safe.

$ grep -c '\b334\b' scripts/pm/dispatch-gates.mjs
1

After the change: 0.

Zone 2 C — the neighbouring 77 is correctly frozen (and a finding next door)

Verified, PM reading holds. 77 is a historical fact anchored to PR #9897, not a live count, so it is correct to leave frozen — and the new text now says so explicitly ("which carried 77 assertions at that PR") rather than leaving it ambiguous:

assert( call sites in scripts/pm/check-governed-merges.mjs value
at PR #9897 (a065e46550b4) 70
at that PR's parent 70
at 9c4c431fd (today) 223

70 static + 7 loop expansion = the 77 the prose names, so 77 was true at #9897 and is now roughly a third of the truth. Frozen-and-anchored is the right call.

⚠️ Reported, not fixed (a different file — out of scope per the card): scripts/pm/check-governed-merges.mjs carries the same defect in its own docblock, and there it is not anchored:

an unguarded trigger ran THIS file's 77 assertions inside the importer's own --self-test

"THIS file's 77 assertions" is a present-tense claim about that file's current count, which is now 223+. That is the identical rot, one file over. Not touched here.

The new text

 * the importer's exit code. That is the same defect PR #9897 fixed in
 * `check-governed-merges.mjs`, which carried 77 assertions at that PR; this
 * file carries it at more than ten times that many. That multiple is a FLOOR,
 * and it is written as one on purpose. The live figure is whatever
 * `--self-test` prints from `cases.length`; it moves on most edits to this
 * file, and over this file's history it has never once gone down — so a floor
 * stays true where a reading rots. A reading stood here before and had drifted
 * by more than a factor of three before anyone repaired it, so do not
 * "helpfully" refresh this back into one. A self-test is a mode of the file
 * being RUN, never a side effect of importing it, and a shared module that
 * exits on import is a shared module nobody can share.

Per the card's Zone 3 note, the paragraph now separates what still holds (the property: this file's self-test is enormous next to the one #9897 fixed, so an import-triggered run is far worse here) from what was measured once (77, at #9897). And it states why the figure is a floor, so the next reader who reaches for the live number is told, in place, not to.

No gate was added to pin the docblock to the live count — the card rules that out, and I agree: it would tax every edit to a constantly-edited file and re-freeze the number by another route.

What would catch a wrong edit here

Plainly: nothing would. Stating that rather than implying coverage:

  • --self-test stays green (1073 cases) — but it was green with 334 too. It asserts nothing about this prose.
  • Every gate in the derived family that reads this file masks comments before judging (check:entry-guard reports "masked prose/payloads accepted"; check-self-test-wired counts --self-test "in code (comments masked)"). By construction they cannot see this paragraph.
  • Nothing caught the original 334 rot for the whole 334 to 1073 drift. A human reading the file filed the card.

So the defence this PR ships is not mechanical: it is that the claim is now a floor instead of a reading, which stays true without maintenance, plus a sentence telling the next editor why refreshing it would be wrong. If the count ever fell below 770 the sentence would go false and nothing would flag that either — the history measurement above is the whole basis for accepting that risk.

Changeset

None. Script-only, and comment-only within that: no package publishes anything from this diff, matching the repo's precedent for script-only commits. The diff is one file under scripts/pm/, which is inside the closed list the skip-changeset label exists for. I have applied skip-changeset up front rather than waiting for Check Changeset to go red.

Gates: derived vs run

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (14 families; provenance line confirms the answer is about this repo at 9c4c431fd). Reconciliation comm -23 of derived against run is empty — every derived family was invoked. Verdicts:

gate result
pnpm check:agent-test-spelling green
pnpm check:bash32-floor green — 153 self-test cases
pnpm check:cli-command-ids green — 39 self-test cases
pnpm check:cross-package-test-inputs green — 117 self-test cases
pnpm check:entry-guard green — 54 self-test cases, 194 files swept
pnpm check:parse-guard green
pnpm check:pnpm-filter-targets green — 54 + 40 assertions
pnpm check:watch-hint-literal green — 57 self-test cases
node scripts/check-ci-filter-parity.mjs green — 129 declared globs covered
node scripts/check-cross-package-test-inputs.mjs green — 24 packages
node scripts/check-self-test-wired.mjs green — 157 CI-run scripts
node scripts/check-shard-attestation.mjs green
node scripts/check-test-completeness.mjs NOT MEASURED — see below
pnpm check:pm-dispatch-gates green — exit 0; it drives the self-test to 1073 cases pass

Plus, outside the derivation:

  • pnpm check:ratchet-remedy-authoritygreen. Run explicitly because #13813 records that this gate builds its scan surface with readdirSync at runtime and spells no declarative glob, so path derivation cannot name it.
  • node scripts/pm/dispatch-gates.mjs --self-testgreen, 1073 cases pass.

check-test-completeness is NOT MEASURED, not red. It grades a saved turbo run test log and was invoked with no argument; the gate prints its own instruction for this case: "running the family locally, record this gate as NOT MEASURED... ⛔ It is not a red, and there is nothing here to fix." CI passes it a real log.

Two gates (check-ci-filter-parity, check-shard-attestation) first returned PREREQUISITE NOT MET — the dependency yaml is not installed, which is also not a red. I ran pnpm install --frozen-lockfile and re-ran both to green rather than reporting an unmeasured gate.

Every derived family is now green except the one NOT MEASURED row. Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC

All gate verdicts above are quoted from each gate's own printed verdict line, with exit codes captured by redirect before any pipe. Gate union run at 44fbc0a37, which is the head of this branch.

Generated by Claude Code


Generated by Claude Code

The entry-guard docblock carried "this file carries it at 334" — a frozen
reading of a number that moves on most edits to this file. It had drifted to
1073 by the time anyone looked: a factor of 3.2.

Writing today's number would re-freeze the same defect one value later, so the
figure is now a FLOOR ("more than ten times" #9897's 77), stated as a floor on
purpose and pointing at `--self-test`'s `cases.length` as the live reading.

Measured before choosing the shape: across all 83 commits that have touched
this file, the assertion count went up 72 times, held flat 10 times, and has
never once gone down (14 -> 1047 static call sites; 1073 at runtime after the
file-local loop expansions). A floor is safe precisely because of that.

The neighbouring 77 is left frozen deliberately — it is anchored to PR #9897
and was true there (70 static assertions at that commit), so it is a historical
fact rather than a live count. The sentence now says so explicitly.

No behaviour change: the `invokedDirectly` guard and the self-test are
untouched. `--self-test` still reports 1073 cases pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Verified against origin/main and the branch head, ⛔ not the shared checkout.

⭐⭐ The Zone 2 A measurement is the model for how to use a proxy

Running the self-test at 83 historical commits is unaffordable (2-6 min a run). So the dev used a static proxy — the count of t( call sites — and ⭐ validated the proxy against ground truth before trusting it:

1047 static call sites at 9c4c431fd + 26 file-local loop expansions = 1073 predicted; the actual run printed exactly dispatch-gates self-test: 1073 cases pass.

It also checked that every multiplier is a literal array in this file, so no loop draws its population from the repo tree — which is what makes the proxy stable across history rather than only at the calibration point.

Then the sweep, 83 commits touching the file (2026-08-10 → 08-31): 72 increases, 10 flat, 0 decreases.

⇒ ⭐ A proxy calibrated against the real reading, with the mechanism that could invalidate it checked separately, is a measurement. An uncalibrated proxy would have been a guess with numbers on it.

The shape the measurement chose

2a — a bound, expressed as a multiple of the 77 already in the sentence. Live ratio is 1073/77 = 13.9, so "more than ten times that many" carries ~39% headroom that the history says only widens.

The shipped text does four things I want on record:

  1. Anchors the 77"check-governed-merges.mjs, which carried 77 assertions at that PR" — turning an ambiguous number into a dated fact;
  2. Declares the floor as deliberate"That multiple is a FLOOR, and it is written as one on purpose";
  3. Points at the live reading"whatever --self-test prints from cases.length";
  4. Inoculates against the next helpful refresh, with the evidence: "A reading stood here before and had drifted by more than a factor of three before anyone repaired it, so do not 'helpfully' refresh this back into one."

334 occurrences after the change: 0. The argument's closing sentence is preserved verbatim.

⭐⭐ "What would catch a wrong edit?" — nothing, and it explained structurally why

⛔ Not "I ran it and it was green". The dev established that every gate in the derived family that reads this file masks comments before judging: check:entry-guard reports "masked prose/payloads accepted", check-self-test-wired counts occurrences "in code (comments masked)". ⇒ by construction neither can see this paragraph, and nothing caught the original rot across the whole 334→1073 drift — a human filed the card.

And it stated the residual risk plainly rather than burying it: "If the count ever fell below 770 the sentence would go false and nothing would flag that either — the Zone 2 A history measurement is the entire basis for accepting that risk."

⚠️ One of its own side findings sharpens that: 8 assertions sit behind existsSync branches, so the printed total is not a pure function of this file. ⇒ The monotonicity evidence is about the code, and the runtime figure can also move with the environment. That does not threaten a ten-times floor at 13.9×, but it is the honest boundary of the claim and it belongs on the record.

⛔ My own zero was wrong, and the counter-check is the only reason I know

Zone 2 C asked whether the neighbouring 77 is a historical fact (correct to freeze) or a live claim. The dev confirmed it is historical in this file — and reported that check-governed-merges.mjs carries the same number unanchored and present-tense in its own docblock, filing it as #13963.

I went to verify and my git grep "77 assertions" on that file returned nothing. ⇒ I nearly reported the finding as unsupported.

It is not. The phrase wraps across a line break: scripts/pm/check-governed-merges.mjs:3503 ends …an unguarded trigger ran THIS file's 77 with assertions on the next line. A single-string grep cannot see it.

⭐ That is instrument lesson on this lane's own list — cross-line text makes a single-string grep return zero — committed again by the seat that wrote it down this morning. I caught it only because the rule says to counter-check a zero against a control, and the control (-i assertion in the same file) returned five hits. ⇒ #13963's premise holds.

Gates

14 families derived (harvested with --commands, ⛔ not grepped), 14 run, comm -23 derived ran empty. 13 green, 1 NOT MEASURED (check-test-completeness exit 3, by its own printed instruction). check:ratchet-remedy-authority run explicitly per #13813 — green.

⭐ Two gates first exited 1 with "PREREQUISITE NOT MET — the dependency yaml is not installed" in a fresh worktree. The dev read them as not measured, ran pnpm install --frozen-lockfile, and re-ran both to green verdicts — ⛔ rather than reporting an unmeasured gate or, worse, a red. That is the distinction this lane keeps having to make and it made it unprompted.

⛔ No ablation, correctly: the change is comment-only, and — per the field above — there is no mechanical check here that could be proved failable.

Governed-surface check

Diff is scripts/pm/dispatch-gates.mjs only, +10/−4, comment-only. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

Follows once CI settles green on the head.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] dispatch-gates' import-side-effect docblock still sizes its own self-test at "334 assertions" — the live count is 979

2 participants