Filed by the dev seat on #8442 (PR #8533), where this cost a red CI lap. Unassigned and unlabeled for triage. Surface: PM dispatch tooling / gate derivation.
⚠️No gate is asked to be weakened, and no gate is wrong.check-type-check-coverage.mjs behaved correctly — it caught four real new type errors. This is about the name the derivation hands a dev seat, and the fact that running that name cannot reproduce the failure.
The mismatch
scripts/pm/dispatch-gates.mjs:396 emits, as a convention-triggered gate for any change that adds a test file:
- pnpm check:type-check-coverage — TEST_DEBT ratchets a package's test-layer
type errors, so a new test file that does not typecheck cleanly moves it
The rationale is the ratchet. The named command does not run the ratchet. From package.json:
check:type-check-coverage = check-type-check-coverage.mjs --self-test && check-type-check-coverage.mjs
check:type-check-debt = check-type-check-coverage.mjs --self-test && check-type-check-coverage.mjs --re-measure
Same script file, two invocations, two different questions. --re-measure is the half that re-runs tsc per ledgered package and fails when an entry drifts upward. Plain invocation checks coverage/wiring and never re-measures. lint.yml runs both — check:type-check-coverage at line 950 and check:type-check-debt at line 1357 — and it is the second that goes red on a new type error.
Why the usual defences did not catch it
This is the part worth carrying forward. The lane's standing rule is to derive gates from the workflow and re-derive with dispatch-gates.mjs, then run the union. That rule could not help here: both lists name the same script, and what differed was the flag. A union of two lists of script names is blind to an invocation split inside one script. On #8442 the union-green report therefore listed check:type-check-coverage in good faith while the ratchet had never been run locally at all; CI found four new errors (2 in metadata-protocol, 1 each in objectql and runtime).
The failure is also asymmetric in the expensive direction: --re-measure refuses to run at all without a fully built workspace closure (it throws rather than measure a different world, per #6376), so it is precisely the gate a dev seat is least likely to have run incidentally.
Suggested shape (not decided here)
Emit the package script CI actually runs for the ratchet rationale — check:type-check-debt — either replacing the current entry or listed beside it, since the two answer different questions and a change adding a test file genuinely moves both. If both are emitted, the ratchet line should carry the build-closure prerequisite, because a seat that runs it cold gets a throw rather than a verdict and may read that as "not applicable to me".
Worth considering as a general rule for the derivation: where one script has multiple CI invocations, the entry should name the invocation, not the script. A quick check for other instances of that shape in CHANGE_KIND_GATES would tell whether this is a one-off or a class.
Related
#8442 / PR #8533 (where it surfaced) · #5278 (the ratchet's shrink-only rule) · #6376 (why --re-measure demands a built closure). #8538 is a different finding about the same script family — it concerns whether a ledger-expanding remedy carries an authority marker, not which invocation gets derived; it is not addressed here and remains open.
Generated by Claude Code
Filed by the dev seat on #8442 (PR #8533), where this cost a red CI lap. Unassigned and unlabeled for triage. Surface: PM dispatch tooling / gate derivation.
check-type-check-coverage.mjsbehaved correctly — it caught four real new type errors. This is about the name the derivation hands a dev seat, and the fact that running that name cannot reproduce the failure.The mismatch
scripts/pm/dispatch-gates.mjs:396emits, as a convention-triggered gate for any change that adds a test file:The rationale is the ratchet. The named command does not run the ratchet. From
package.json:Same script file, two invocations, two different questions.
--re-measureis the half that re-runstscper ledgered package and fails when an entry drifts upward. Plain invocation checks coverage/wiring and never re-measures.lint.ymlruns both —check:type-check-coverageat line 950 andcheck:type-check-debtat line 1357 — and it is the second that goes red on a new type error.Why the usual defences did not catch it
This is the part worth carrying forward. The lane's standing rule is to derive gates from the workflow and re-derive with
dispatch-gates.mjs, then run the union. That rule could not help here: both lists name the same script, and what differed was the flag. A union of two lists of script names is blind to an invocation split inside one script. On #8442 the union-green report therefore listedcheck:type-check-coveragein good faith while the ratchet had never been run locally at all; CI found four new errors (2 in metadata-protocol, 1 each in objectql and runtime).The failure is also asymmetric in the expensive direction:
--re-measurerefuses to run at all without a fully built workspace closure (it throws rather than measure a different world, per #6376), so it is precisely the gate a dev seat is least likely to have run incidentally.Suggested shape (not decided here)
Emit the package script CI actually runs for the ratchet rationale —
check:type-check-debt— either replacing the current entry or listed beside it, since the two answer different questions and a change adding a test file genuinely moves both. If both are emitted, the ratchet line should carry the build-closure prerequisite, because a seat that runs it cold gets a throw rather than a verdict and may read that as "not applicable to me".Worth considering as a general rule for the derivation: where one script has multiple CI invocations, the entry should name the invocation, not the script. A quick check for other instances of that shape in
CHANGE_KIND_GATESwould tell whether this is a one-off or a class.Related
#8442 / PR #8533 (where it surfaced) · #5278 (the ratchet's shrink-only rule) · #6376 (why
--re-measuredemands a built closure). #8538 is a different finding about the same script family — it concerns whether a ledger-expanding remedy carries an authority marker, not which invocation gets derived; it is not addressed here and remains open.Generated by Claude Code