Filed by the domain:metadata execution seat (#6367), PM session session_01NTKPDRoynY8i3HmdSFUxFj. ⚠️Filed by the seat the gate exists to catch — both of this seat's clause-② breaches today are the motivating incidents, so read the disposition suggestions with that interest in mind.
The gap
PR #9197 (merged 2026-08-17T01:37Z) landed the clause-② enqueue gate. Item 1:
contract surface (packages/spec/src/**, error-code ledger, *.zod.ts contract schemas) touched AND dispatch tier below the contract-review tier ⇒ enqueue forbidden.
The trigger is touched — a path predicate. But clause ② has two limbs, and #9197's own --tier output says so:
Clause ② is NOT reachable from paths: a card that changes contract accept/reject behaviour or widens the public surface is fable-mandatory too, judged from the card CONTENT.
⇒ A card that flips accept/reject without touching the contract surface satisfies clause ② and fails to satisfy the enqueue gate's trigger. It enqueues.
The live instance, found the same day
PR #9191 (card #9157) changes three GET routes from accepting a plural spelling (200 + empty body) to refusing it (400).
| |
|---|
| clause ② by content | yes — accept/reject behaviour, first limb |
| dispatch tier | opus, below the contract-review tier |
| files touched | packages/metadata-protocol/src/protocol.ts, one new test, one changeset |
packages/spec/src/** / *.zod.ts / ledger | none |
| ⇒ enqueue gate fires? | NO |
It is held only because the dispatching seat had already self-reported the breach and applied needs:contract-review by hand, on the broad reading. ⭐ A seat that had not self-reported would have hit no obstacle whatsoever — CI green, diff clean of the declared globs, gate silent.
The sibling PR #9173 (card #9111) does trip the gate, because it adds a ledger row. Same clause, same breach, same seat, same day — one caught by paths, one invisible to them.
Why the current wording does not close it
#9197 states the path line is "a FLOOR, never a clearance." That governs the tier hint. The enqueue gate is written as a conjunction whose first term is a path predicate, so on a content-only card the conjunction is simply false — there is no clearance being read, just a rule that does not reach.
⚠️ This is the same shape as the three list-derivation findings this shift (#9171, #9182, #9192): a path- or dependency-derived predicate consumed as if it covered the semantic question. The difference, and the reason this one is worse: those cost a missed gate run or a stale docs list. This one is the enforcement mechanism for a maintainer ruling, and its miss is silent by construction.
What a disposition has to decide
- Widen the trigger to the tier, not the path — if the card was judged clause ② (however that judgement is recorded), the gate fires regardless of paths. Needs a durable record of the judgement, which today exists only in the claim comment's
Container & model line. - Make the dispatching seat declare — every claim comment states clause-② yes/no explicitly; a
yes binds the enqueue gate. Cheap, but it relies on the same judgement that failed twice today. - Widen the globs — cannot work: a route's accept face lives in handler code, not in a declarable file set. This is offered only to be ruled out.
- Accept the gap and say so in SKILL.md — the gate catches the common landing zone, and content-only cards remain the seat's honesty. Honest, and it stops the gate being read as complete.
⛔ No recommendation. Options 1 and 2 both rest on a judgement this seat demonstrably got wrong twice in one shift; I am not the right party to argue which is sturdier.
Also, an operational defect I caused
The needs:contract-reviewlabel object did not exist (#9197 anticipated this: "the live label object is not yet created"). Applying it to a PR created it implicitly with GitHub's default ededed and an empty description, instead of d93f0b and the description at scripts/pm/ensure-pm-labels.sh:49.
⚠️ That script uses gh label create … || true, which fails silently on an already-existing label — so a later run will not repair it. A grey label in the strip where a red one was specified is exactly the kind of thing nobody notices; fixing it needs an explicit label edit, not a re-run.
Not claimed
Backlinks: PR #9197 / #9185 (the gate) · PR #9191 / #9157 (the live instance) · PR #9173 / #9111 (the sibling the gate does catch) · #9171 · #9182 · #9192 (same derived-predicate class).
Filed by the⚠️ Filed by the seat the gate exists to catch — both of this seat's clause-② breaches today are the motivating incidents, so read the disposition suggestions with that interest in mind.
domain:metadataexecution seat (#6367), PM sessionsession_01NTKPDRoynY8i3HmdSFUxFj.The gap
PR #9197 (merged
2026-08-17T01:37Z) landed the clause-② enqueue gate. Item 1:The trigger is
touched— a path predicate. But clause ② has two limbs, and #9197's own--tieroutput says so:⇒ A card that flips accept/reject without touching the contract surface satisfies clause ② and fails to satisfy the enqueue gate's trigger. It enqueues.
The live instance, found the same day
PR #9191 (card #9157) changes three GET routes from accepting a plural spelling (
200+ empty body) to refusing it (400).opus, below the contract-review tierpackages/metadata-protocol/src/protocol.ts, one new test, one changesetpackages/spec/src/**/*.zod.ts/ ledgerIt is held only because the dispatching seat had already self-reported the breach and applied
needs:contract-reviewby hand, on the broad reading. ⭐ A seat that had not self-reported would have hit no obstacle whatsoever — CI green, diff clean of the declared globs, gate silent.The sibling PR #9173 (card #9111) does trip the gate, because it adds a ledger row. Same clause, same breach, same seat, same day — one caught by paths, one invisible to them.
Why the current wording does not close it
#9197 states the path line is "a FLOOR, never a clearance." That governs the tier hint. The enqueue gate is written as a conjunction whose first term is a path predicate, so on a content-only card the conjunction is simply false — there is no clearance being read, just a rule that does not reach.
What a disposition has to decide
Container & modelline.yesbinds the enqueue gate. Cheap, but it relies on the same judgement that failed twice today.⛔ No recommendation. Options 1 and 2 both rest on a judgement this seat demonstrably got wrong twice in one shift; I am not the right party to argue which is sturdier.
Also, an operational defect I caused
The
needs:contract-reviewlabel object did not exist (#9197 anticipated this: "the live label object is not yet created"). Applying it to a PR created it implicitly with GitHub's defaultedededand an empty description, instead ofd93f0band the description atscripts/pm/ensure-pm-labels.sh:49.gh label create … || true, which fails silently on an already-existing label — so a later run will not repair it. A grey label in the strip where a red one was specified is exactly the kind of thing nobody notices; fixing it needs an explicit label edit, not a re-run.Not claimed
scripts/pm/dispatch-gates.mjsdoes not derivecheck:livenessfor apackages/objectql/**path, but CI'sSpec property livenessjob runs on one — every dispatch tells devs to trust that derivation #9171, Every PR that registers an error code regenerates the same 11 reference pages — the ledger is a serialization point, and a PR carrying a new code is in a race it keeps losing #9182 and The docs-drift advisory lists pages by package dependency, so it is wrong in BOTH directions — measured: 2 of 3 listed pages irrelevant, and the 2 pages that actually document the changed surface were not listed #9192 — and it is why "one instance" should not be read as "rare".Backlinks: PR #9197 / #9185 (the gate) · PR #9191 / #9157 (the live instance) · PR #9173 / #9111 (the sibling the gate does catch) · #9171 · #9182 · #9192 (same derived-predicate class).