Repository navigation
docs(pm-dispatch): an exhausted contract-review tier hands the review to triage, and triage tracks stale records - #26771
Conversation
… to triage, and triage tracks stale records The dispatching seat still runs its own contract review at the contract-review tier. Only a quota-refused call hands the review over: one PR comment carrying a `Contract-review-handoff:` line beside the existing label, which the triage seat reads each round and runs in an isolated subagent at the same tier. Triage also compares every record it rendered against the PR's current head and re-reviews or notes a moved head. `record-recognisers.mjs` gains the one reader of that line, with self-test pins; no gate reads it. Claude-Session: https://claude.ai/code/session_01ADHkmSUY4HbWjTHDfPyAYU Co-authored-by: Claude <noreply@anthropic.com>
…e rulebook A structural read of a governed file from a script is a census the gate derivation classifies, so the self-test keeps to rows and strings. Claude-Session: https://claude.ai/code/session_01ADHkmSUY4HbWjTHDfPyAYU Co-authored-by: Claude <noreply@anthropic.com>
… with rules only the dev file carries The (c)-metadata boundary and the routing rule stay in the triage duties; three lines that only pointed at filing-gate.md and dispatch-runbook.md pay for them instead. Claude-Session: https://claude.ai/code/session_01ADHkmSUY4HbWjTHDfPyAYU Co-authored-by: Claude <noreply@anthropic.com>
席位核对ACCEPT ·
|
Contract reviewServed-tier: Director seat (summon #52, ledger objectstack#12708), summoned by the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS Generated by Claude Code |
Requested by Steve · project thread
Fixes #26667
Clause-②: no
Metadata-protocol: none
维护者速读
CONTRACT_REVIEW_TIER调用被配额拒时,不降档审,而是在 PR 落一行固定格式的Contract-review-handoff:交接,交分诊席跑;分诊每轮认交接行、自己的记录与现 head 比对,过期的重审或记一条。references/contract-review.md(交接臂与行形状)、references/triage-duties.md(分诊轮步骤)、scripts/pm/record-recognisers.mjs(contractReviewHandoff与自检)。pnpm check:pm-record-recognisers——预期✓ … 232 cases pass,含交接行电池 13 例;pnpm check:pm-skill-ratchet预期两文件行数不变(55 / 103)。What changes
Maintainer rule, verbatim (2026-10-27): 「关于契约复审,开发自己有fable时都可以自己审核,只有开发的fable用完了,才需要分诊,但是此时分诊要能看出来,区别出来。」 and, after the triage seat reported a stale FAIL on a moved head: 「改进 skills」.
.claude/skills/pm-dispatch/references/contract-review.md〈复核归属与资格〉 — two lines after 「谁跑 = 派发席」: the hand-off arm (a quota-refusedCONTRACT_REVIEW_TIERcall never reviews at a lower tier; the seat posts the hand-off line, keepsneeds:contract-review, and triage runs the review) and the line's exact shape,Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (STATUS-OR-ERROR, UTC-TIME) · head SHA(the placeholders are spelled in words here; the file carries the card's exact angle-bracket shape). In 〈等复核标记〉 the readers line becomes the relation rule: a label without the line is still the seat's own review and triage does not touch it; a head that moves after the hand-off needs a fresh line or the seat's own review..claude/skills/pm-dispatch/references/triage-duties.md— six round-step lines: list open PRs whose newest hand-off line names the current head and run the review in an isolatedCONTRACT_REVIEW_TIERsubagent with the same-shape record signed by the triage seat; on triage's own quota refusal write once on the PR, keep the label, never review lower; each round compare every triage-rendered record'sHead-shawith the current head (regen-only / prose-only moves excepted, judged on the committed tree); a stale FAIL is re-reviewed in the same round (every earlier must-fix, the delta commits as changes in their own right); a stale PASS gets one note that it no longer governs and a delta review is owed; the round record lists each triage-reviewed PR asrecord head → current head → state.scripts/pm/record-recognisers.mjs— ONE recogniser:readContractReviewHandoff(text)reads the line (targettriage, the tier by its constant NAME through the same token readerServed-tier:uses, reason and UTC time in the parentheses, a 7–40 hex head; anything short of that is started-and-unreadable), andcontractReviewHandoff(rows, headSha)answers whose review it is off the newest such line:absent(the seat's own),triage(names the current head, prefix-matched like a record's span),stale(head moved),unreadable. Newest governs throughlatestMarkedComment, the locator's own resolution. ⛔ No gate reads it;locateReviewOfRecordand the queue guard are untouched, and a pin drives the guard's reading past a hand-off line beside a record. A new self-test battery of 13 cases;SELF_TEST_BATTERY_FLOOR12 → 13.Line budget (the ratchet, lines only down; 120-byte cap, no re-wraps):
references/contract-review.md--brief-template's built-in text, which the surviving line 37 points at and the self-test pins); the readers line (54) rewritten into the label↔line relation (its filter query lives indispatch-runbook.md〈跨账户复审〉)references/triage-duties.mddispatch-runbook.md〈紧急卡直接分诊〉), the report-only-instrument close rule (→instrument-discipline.mdlines 8 and 12), lane seats do not triage (→lanes/skills.mdL22,lanes/ui.mdL8,cross-repo-coordination.mdL32), the three-exit first-touch +Batch-of:line (→filing-gate.mdL25–28), the three-state grading pointer (→filing-gate.mdL46–48), the 域分批 / 积压告警 pointer (→dispatch-runbook.mdL23/L27). The (c)-metadata lines and the routing line stay (seat review, head5956f4ba).The hand-off line in
contract-review.mdis 122 bytes as ONE code span — the card's exact shape, kept verbatim; the ratchet'sunbreakableclass (a single code span has no legal wrap) passes it, measured withwrapLine. Every other new line is ≤ 120 bytes.No forced test edits. No changeset:
.claude/**andscripts/pm/**publish nothing (skip-changeset).Tests
node scripts/pm/record-recognisers.mjs --self-test—✓ record-recognisers self-test: 232 cases pass(219 before + 13 new), exit 0. The battery pins rows and strings only: a first cut also read the rulebook file to pin that it spells the line, andcheck:pm-dispatch-gatesrefused it (a structural read of a governed file from a script is a census that gate classifies), so that pin was dropped rather than the census widened.Acceptance notes
landing-operations.mdline 13 still says a review subagent that cannot start leaves the PR draft outside the queue with the maintainer's own review as the only bypass; the hand-off arm narrows the quota case out of that. Not edited (outside the card's file surface); noted for the seat.Head-shaandReviewed-bysession.locateReviewOfRecord(...).shaalready answers the head on the current head andabsenton a moved one; theReviewed-byVALUE is readable through the exportedREVIEWED_BY_LINEregex's capture group — no second reader was added, per the claim's ONE-recogniser surface.Verification
Head
c59cd9c6.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths) derived 40 families; every one was run on this head with its exit code captured before any pipe, and--ranreconciled:✓ dispatch-gates --ran: 40 derived famil(ies) accounted for — 40 run, 0 NOT-MEASURED, exit 0. All 40 exit 0.The acceptance families, verdict lines
pnpm check:pm-record-recognisers—✓ record-recognisers self-test: 232 cases passpnpm check:pm-skill-ratchet—✓ check-skill-line-ratchet: declared cross-file moves: 3, total ceilings down 487 lines.(contract-review.md 55/60, triage-duties.md 103/103, both unchanged in count)pnpm check:pm-skill-id-lint—✓ check-skill-id-lint: 104 file(s) cleanpnpm check:pm-governed-prose—✓ check-governed-prose: 2 instruction surface(s) name all 13 registered governed surfacespnpm check:pm-dispatch-gates—✓ dispatch-gates self-test (fast tier): 1935 cases pass; 7 slow section(s) deferred.pnpm check:skill-frame-sync—✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherentpnpm check:nul-bytes—✓ check-nul-bytes --self-test: 75 assertionsNot run locally:
pnpm lint(repo-wide, CI's run),test:repo(CI'sTest Core). No package is touched, so no ① closure and no ② package tests. Dogfood battery: n/a — no!in the title and no narrowing arm.Human Minimum
packages/specholds no runtime logic. (n/a — no schema)pnpm lintis CI's run (repo-wide), not re-run locally.main, one pull request.packages/spectouched: no.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code