Skip to content

Commit 5e1f09b

Browse files
committed
fix(pm): dispatch-gates names the LANES that owe the clause-② review, not a seat
The clause-② note and the suspect tail printed by `--tier` (quoted into claim comments) said "spec seat; default-tier build" and "in the spec seat" — the 2026-09-10 seat key, never re-keyed by the 09-16 tier PR. They now say what the charter says: the review is owed in the spec and skills lanes, in-seat at tier or by the at-tier subagent, and a contract-surface hit outside those lanes is spec-lane work that moves there. The docblock above MANDATORY_TIER_GLOBS carries the same rule; four self-test pins hold both renderings to the lane key and refuse the two retired spellings. Claude-Session: https://claude.ai/code/session_01BTeBejoPUvRHN8WdAJC6oF Co-authored-by: Claude <noreply@anthropic.com>
1 parent c93bb8b commit 5e1f09b

1 file changed

Lines changed: 34 additions & 14 deletions

File tree

‎scripts/pm/dispatch-gates.mjs‎

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11879,11 +11879,12 @@ export function residueLines(
1187911879
/**
1188011880
* The single source of truth for the model tier the PM lane's governance
1188111881
* reads — clause ②'s CONTRACT-REVIEW tier: the tier the clause-② REVIEW runs
11882-
* at, both halves of it — the spec seat's review of a card that changes
11883-
* contract accept/reject behaviour or widens the public surface, and the
11884-
* `needs:contract-review` re-review sub-round (its opening self-check reads
11885-
* this). The BUILD of such a card is at the default judgment tier, so this
11886-
* constant is a review tier and never a dispatch mandate. Declared HERE
11882+
* at, both halves of it — the spec and skills lanes' review of every round
11883+
* they deliver (a card that changes contract accept/reject behaviour or
11884+
* widens the public surface is spec-lane work, whichever seat found it), and
11885+
* the `needs:contract-review` re-review sub-round (its opening self-check
11886+
* reads this). The BUILD of such a card is at the default judgment tier, so
11887+
* this constant is a review tier and never a dispatch mandate. Declared HERE
1188711888
* and only here, as a constant, so a model upgrade is a one-line change in one
1188811889
* file — the clause-① mandate rows below read it, the self-test compares
1188911890
* against it, and the PM skill's prose names it, so the model id is spelled as
@@ -11945,12 +11946,22 @@ export const CONTRACT_REVIEW_TIER = 'claude-fable-5-1';
1194511946
* a file-surface predicate, and exactly what this script takes as argv;
1194611947
* - clause ②, NOT encoded and deliberately not: a card that changes contract
1194711948
* accept/reject behaviour or widens the public surface is built at the
11948-
* default tier and REVIEWED at `CONTRACT_REVIEW_TIER` — in the spec seat
11949-
* only, since the 2026-09-10 ruling; every other lane's clause-② review is
11950-
* that lane's own default-tier review plus the gates, and neither the
11951-
* triage seat nor the maintainer-summoned director spawns a
11952-
* contract-review-tier subagent for anything. That is judged from the
11953-
* card's CONTENT — what the change
11949+
* default tier and REVIEWED at `CONTRACT_REVIEW_TIER`. WHO owes that
11950+
* review is keyed by LANE — the maintainer's lane rule, keyed by seat on
11951+
* 2026-09-10, re-keyed by served tier on 2026-09-16 and restated as the
11952+
* lane rule on 2026-09-17 (「曾经要求只有 spec 和 skills 需要 fable,其他
11953+
* opus 就够了,理论上其他车道不需要契约复审」): the spec and skills lanes
11954+
* owe it on every round they deliver — in-seat when the seat's served
11955+
* tier is that tier, otherwise by the at-tier review subagent the seat
11956+
* spawns (the fastest route, per the maintainer) — and every other lane
11957+
* owes NO contract review: its whole bar is the three landing pre-checks
11958+
* and the gates, ⛔ no default-tier "self-review" record is demanded of
11959+
* it and ⛔ no at-tier subagent is spawned from it (neither the triage
11960+
* seat nor the maintainer-summoned director spawns one for anything). A
11961+
* clause-② hit outside those two lanes is lane ROUTING, never a review
11962+
* demand on the lane that found it: the work is the spec lane's,
11963+
* whichever seat found it, and moves there. Clause ② itself is judged
11964+
* from the card's CONTENT — what the change
1195411965
* does to the contract — and a path cannot answer it. An ordinary-looking
1195511966
* surface (one package's source file) is the NORMAL shape of a clause-②
1195611967
* card. The closest a path can honestly get is SUSPICION:
@@ -12141,8 +12152,9 @@ export function tierLines(result) {
1214112152
}
1214212153
const clause2 =
1214312154
' Clause ② is NOT reachable from paths: a card that changes contract accept/reject behaviour or widens the public' +
12144-
' surface owes a contract-review-tier REVIEW too (spec seat; default-tier build), judged from the card CONTENT.' +
12145-
' This line is a FLOOR, never a clearance.';
12155+
' surface owes a contract-review-tier REVIEW too (owed in the spec and skills lanes, in-seat at tier or by the' +
12156+
' at-tier subagent; default-tier build; a hit outside those lanes is spec-lane work and moves there), judged from' +
12157+
' the card CONTENT. This line is a FLOOR, never a clearance.';
1214612158
// The suspicion tail prints only on a hit — unlike the clause-② note above,
1214712159
// which prints always: "no suspicion" and "no suspect table" must not share a
1214812160
// spelling, and the note is what keeps silence from reading as a clearance.
@@ -12151,7 +12163,7 @@ export function tierLines(result) {
1215112163
: [
1215212164
` Clause ② SUSPECT surface — a hint, not a verdict: judge the tier from the card CONTENT as best you can` +
1215312165
` (a card changing contract accept/reject behaviour or widening the public surface is reviewed at ${CONTRACT_REVIEW_TIER}` +
12154-
' in the spec seat, built at the default tier);' +
12166+
' in the spec lane — a contract-surface hit is spec-lane work whichever seat found it — built at the default tier);' +
1215512167
` whichever tier is dispatched, the PR's actual diff passes the clause-② enqueue gate before the card may enqueue.`,
1215612168
...suspects.map((s) => ` - ${s.path} ⇢ '${s.glob}' — ${s.why}`),
1215712169
];
@@ -24578,6 +24590,13 @@ function selfTest() {
2457824590
t('the no-mandate rendering claims no mandate', !plainLines.includes('MANDATORY'));
2457924591
t('the no-mandate rendering names the floor and the default, so the judgment call has its band', plainLines.includes(TIER_FLOOR) && plainLines.includes(TIER_DEFAULT));
2458024592
t('BOTH renderings state that clause ② is out of reach of paths — a no-mandate line is not a clearance', plainLines.includes('Clause ②') && mandLines.includes('Clause ②'));
24593+
// The lane key (#18536): the maintainer's lane rule restated — the review is
24594+
// owed in the spec and skills lanes, in-seat at tier or by the at-tier
24595+
// subagent, and in no other lane; the 2026-09-10 SEAT key and the
24596+
// 2026-09-16 TIER key are both retired spellings and must not come back.
24597+
t('BOTH renderings key the clause-② review by LANE — the spec and skills lanes, in-seat at tier or by the at-tier subagent', [plainLines, mandLines].every((l) => l.includes('spec and skills lanes') && l.includes('at-tier subagent')));
24598+
t('…and neither spells a retired key — no "spec seat" (2026-09-10) and no default-tier review or self-review (2026-09-16)', [plainLines, mandLines].every((l) => !l.includes('spec seat') && !l.includes('default-tier review') && !l.includes('self-review')));
24599+
t('…and both say a clause-② hit outside those lanes is spec-lane work that MOVES there — lane routing, never a review demand on the lane that found it', [plainLines, mandLines].every((l) => l.includes('spec-lane work and moves there')));
2458124600
t('the no-mandate rendering says how many globs it checked, so an empty table cannot read as a clearance', plainLines.includes(`${MANDATORY_TIER_GLOBS.length} declared glob`));
2458224601
// Refusals: a contradiction is not printed, and an ambiguity is not guessed.
2458324602
let tierRefused = false;
@@ -24645,6 +24664,7 @@ function selfTest() {
2464524664
t('the suspicion rendering sends the seat to the card CONTENT for the tier call', suspectRendered.includes('judge the tier from the card CONTENT'));
2464624665
t('the suspicion rendering routes EVERY dispatch through the enqueue gate on the ACTUAL diff', suspectRendered.includes('whichever tier is dispatched') && suspectRendered.includes('enqueue gate'));
2464724666
t('the suspicion rendering names the contract-review tier from its single-source constant', suspectRendered.includes(CONTRACT_REVIEW_TIER));
24667+
t('the suspicion rendering keys the review by LANE — "in the spec lane", the work being the spec lane\'s whichever seat found it — never by seat (#18536)', suspectRendered.includes('in the spec lane') && suspectRendered.includes('whichever seat found it') && !suspectRendered.includes('spec seat'));
2464824668
const noSuspicion = fableOf(['packages/runtime/src/kernel.ts']);
2464924669
t('an ordinary non-contract surface raises no suspicion', noSuspicion.suspects.length === 0);
2465024670
t('no suspicion ⇒ no suspect line — absence and clearance must not share a spelling with a hit', !tierLines(noSuspicion).join('\n').includes('SUSPECT'));

0 commit comments

Comments
 (0)