fix(tooling): re-derive the #5499 denominator over the whole tree, retire the present-tense freeze claims, and name the un-fireable-latch class - #13268
Conversation
…erted in the present tense, and name the un-fireable-latch class Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
|
The gate's own output diagnoses it completely:
⇒ This is the died-before-any-test-body-ran class, not a red I am asking for a nicer answer:
⛔ For the record, what I did not do: no empty commit, no close/reopen, no re-queue of a red test hoping for a different verdict.
I am adding one job to a deep backlog deliberately and once, because without it this PR has no path to green at all. Generated by Claude Code |
Fixes #13211
Not a fourth sweep. The deliverable is a stated population and the class-level repair of the
un-fireable-latch trap; the site edits are what that population then compels.
1. The population, decided first
The three cards in this family (#13089 -> #13168 -> #13194) measured completeness with
grep -rn 5499 packages --include=*.ts. That population cannot contain a.mjsgate script, a.ymlworkflow, a.jsonledger or a.mddoc — by construction, not by oversight. Re-running itwith more extensions is how a fifth card gets discovered, so the denominator is redefined instead:
Why this cannot produce a fifth card: the denominator is the whole tracked tree, so no extension can
hide a site; and the exclusions are rules with reasons, so re-deriving them returns the same answer
instead of a new discovery.
2. Re-derived on this tree (
74049254d4), because no recorded number is definitiveThe card measured 143 repo-wide on its tree and triage 162 on another. Different trees — not a
disagreement to settle by picking one. On mine:
--includepackages/**/*.ts— what all three cards measuredscripts/**.github/**docs/adr/**The buckets partition exactly (58+19+43+22+2+3 = 147). The uncontested direction holds: the shared
denominator saw under a third of the population, and 27 lines of live, hand-maintained text
(
scripts+.github+docs/adr) were outside every card's reach.3. The PM's four assumptions, measured
96d8b20ee4(2026-08-29 12:19:29Z) touches14 files, every one of them a
.tsfile underpackages/. It reaches no.mjs, no.yml, no.jsonledger, no doc. The reading was right; the card is not smaller than filed.the repairs are anchored on the sentence text, and every anchor matched exactly once.
state: open, labelstracking+domain:engine, 12 comments. The dissolution is comments 8 and 9 (5249019855mongodb,5252526378driver-memory, both 2026-08-11), the second saying outright that the freeze "isfully dissolved ... it no longer gates anything." The issue itself never reached a terminal
state and, being
tracking, is not meant to.Not "they are all past tense" — one is not.
packages/drivers/driver-mongodb/CHANGELOG.md:1145reads "
driver-memory's half of drivers(memory, mongodb): the$containsfamily still folds case — the last two backends left on the wrong side of #4706 Q2 = A #6682 stays open under the [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 freeze", present tense, insidea shipped release entry. It stays because of venue: a CHANGELOG entry records the state at
release time, and rewriting one rewrites history — the same discipline that keeps
content/docs/releases/out of code PRs. A frozen record making a present-tense claim is adrafting defect in a document nobody may amend, which is exactly the case A2.4 asked about.
4. What changed — 11 sentence sites in 6 files, plus the class
(a) A green gate printing a false sentence on every successful run.
scripts/check-driver-memory-census.mjsbuilt its own OK line ending"Nothing here invests in the driver (#5499 freeze)." It now ends "This gate polices the census,
never investment." — true, and true regardless of any freeze.
(b) The mirrored pair, both sides, identically.
check-driver-memory-census.mjs(header) and.github/workflows/lint.yml(the census step's comment) both said "which stays frozen under#5499." Both now carry the dated history instead. The mirror question was measured before either
edit — see section 5.
(c) The restart latch — the instance is not what the card thought, and the class is worse.
Measured: at
scripts/pm/check-half-states.mjstheRestart-when:closure string is a self-testfixture (inside
function selfTest(), reached only via--self-test), a captured specimen drivingH17's trigger-file extractor. It is not evaluated as a latch, and its truth changes no assertion.
The card it was sampled from, #9276, was completed on 2026-08-27, so nothing is parked behind that
specific string.
The class is real and lives one level up, in H9's contract:
Restart-when:line is present and notmanual. It never askswhether the line's target can be reached.
Restart-when: closed OWNER/REPO#N, i.e. a ruling encoded as an issue closing.trackinganchor stays open by design. A ruling recorded in one of its comments produces noclose event, so the hold is parked forever — and H9 stays green the whole time, because a line
is there.
So the repair is the class, not a new issue number: re-pointing the exit only moves the trap. H9's
section header now names the failure mode and the measured specimen; the finding sentence warns that
a closure form fires only if its target can reach a terminal state, and tells the seat to name the
ruling rather than the closure; and the fixture is labelled as a captured specimen so the next reader
is not the fourth to take it for live machinery.
Also in scope:
scripts/check-driver-conformance.mjsgave two opposite answers.:384and:408were present tense while:397/:490/:501correctly said "unfroze this package on2026-08-11". Repairing
:408truthfully exposed a second, harder staleness measured against thecode rather than the prose: the file's heading claimed "ONE DEBT row left" and "what remains is
driver-memory", whileconst LEDGER = [];— empty, under a note reading "the intended steadystate, reached on 2026-08-11". Both now say what the ledger says.
:384additionally corrected alive instruction: it told readers un-freezing would re-run the mongo cells; the unfreeze happened
18 days ago and nothing re-ran, because the other half (funding the binary provisioning) was never
done.
And the same sentence in a second venue.
docs/adr/0053carried the:384claim near-verbatimplus two conditions waiting on the unfreeze (
:867,:1016). Repairing only the script would haverecreated exactly the asymmetry item (b) is about, so all three moved with it.
scripts/driver-memory-census.ledger.jsonhad one more: "the #5499 freeze is untouched."5. The mirror question, answered by ablation rather than by reading
Prediction, written before the run: no mirror gate holds the census header and the lint.yml comment
equal —
MIRRORSincheck-published-list-mirrors.mjsholds exactly one pair(
AGENTS.mdfromcheck-cross-package-test-inputs.mjs), andcheck-declaration-mirrors.mjsnamesneither file — so a one-sided repair trips nothing.
Ran it: reverted only
.github/workflows/lint.ymlto the retired sentence while the script keptthe repaired one; mutation proven on disk by decomposed counts (retired sentence 0 to 1, repaired
1 to 0) and
git hash-object; restored under an absolute-pathtrapand proven byte-identical toHEAD.Prediction held. Both mirror gates' self-tests are green, so they can go red — they simply do not
cover this pair. Both sides were repaired anyway.
6. The card's central claim, measured rather than asserted
Prediction: restoring "Nothing here invests in the driver (#5499 freeze)." into the census gate's
own OK line leaves every gate green — because the gate is the thing saying it.
Mutation proven on disk (false sentence 0 to 1, repaired 1 to 0; blob
b90b2090efd1against HEAD's8872cf1f49e6), restored under an absolute-pathtrapand proven byte-identical toHEAD. Thesubject is a
.mjsscript node runs from source — no packageexportstodisthop — so there isno dist leg to rebuild on either the mutation or the restore.
...and the green run's own log contained, verbatim:
Nothing here invests in the driver (#5499 freeze).Prediction held. Nothing could have caught this.7. Clause 2: the behavioural half, and the line I stopped at
Prediction: the H9 edit changes no verdict —
hasFireableRestartWhenaccepts any non-manualvalue, so the ruling spelling this change starts advertising was already legal.
Differential run of
h9OnHoldNoRestartWhenatHEAD~1againstHEADover 20 fixture shapes,including the trap itself and the newly advertised spelling:
The latch fires on exactly the inputs it fired on before. Teaching H9 to REFUSE a closure exit
whose target cannot reach a terminal state would be the real mechanical fix — and it is precisely
"makes the latch fire on an input it previously ignored", so it is named and not made here. It
needs a ruling, and there is a second reason to hold it: it would want the same widening in
.claude/skills/pm-dispatch/references/state-machine.md, whose line ceiling inscripts/pm/check-skill-line-ratchet.mjssits at headroom 0 — raising it is a maintainer ruling,never a dev's.
8. Verification
Gate family derived, never recalled:
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackon the final commit, 6 paths against merge base
74049254d. All 40 matched entries (several shareone npm script, e.g.
check:required-contextscovers both derived lines) plus the twoconvention-triggered ones (
bare-root-worklist --self-test,check:pm-dispatch-gates, both fired by"edits a GATE SCRIPT") were run. Exit codes captured by redirect-then-
$?, never through a pipe.Every one EXIT=0, including
check:driver-conformance,check:driver-memory-census,check:pm-half-states,check:adr-anchors,check:doc-authoring,check:required-contexts,check:nul-bytesandcheck:doc-formula-expressions(green after building@objectstack/formulaand
@objectstack/lint).Three results that are NOT MEASURED, not reds:
check:type-check-debt— its--self-testand coverage legs printedcheck-type-check-coverage: OK — 66/78 workspace packages type-checked, then--re-measurerefused: "56 workspace dependencies ... have no built type entry point on disk". It needs the
full
./packages/*built closure, which CI builds. This diff contains zero TypeScript and zeropackage sources, so it cannot move that ledger. Declared narrowing, not a skipped gate.
check-test-completeness.mjsargument-less — EXIT=3, the documented refusal ([finding]check-test-completeness.mjsanswers a standalone run with exit 1 + a usage line, so the derived gate family reads one false red — three independent devs paid for it in one session #13110).check:doc-formula-expressionson the first pass —PREREQUISITE NOT MET, then EXIT=0 once thetwo packages were built.
No changeset: this PR releases nothing — gate-script comments, a workflow comment, one ledger string
and one ADR.
skip-changesetapplies.9. One residual, dispositioned rather than swept
The re-derivation found a site inside the three cards' own denominator that the group-A sweep
missed:
packages/services/service-analytics/src/read-scope-sql.ts:180still reads"
driver-memory/driver-mongodbstay pin-only under the #5499 freeze" — present tense — whileits own sibling
src/__tests__/read-scope-undefined-comparand.test.ts:51, repaired hours earlier,already carries the correct form ("were pin-only ... The thaw has arrived: the freeze dissolved
2026-08-11 ... that debt is now DUE rather than deferred"). A one-sided repair of a mirrored pair,
the same shape as item (b).
⛔ Not fixed here. The bounded-in-place exemption fails its fourth condition: editing a
.tsfile inservice-analyticsadds that package's test and typecheck surface to a PR that currently has none.It is handed to the PM to file: the repo-scoped REST channel answers 403 from this seat and the one
targeted MCP
search_issuesdedup call came backAPI rate limit already exceeded, so this seat cannot search for a duplicate, and filing without adedup read is not an option this contract allows.
10. Proposal, not a decision
Triage noted item (c) is
domain:skillsshaped and did not adjudicate. With the measurement in handthe split now looks unnecessary: the class repair landed entirely in
scripts/pm/, one file, inthe same edit as the denominator re-evaluation — and the piece that would justify a separate card is
the behaviour change in section 7, which is a maintainer ruling rather than a lane routing question.
⛔ No
domain:*label written, and no re-routing done.Generated by Claude Code