Repository navigation
pm-dispatch(contract-review): the lane reviews its own PRs; triage takes only a review nobody is doing, and one claim line per head keeps two reviewers off the same head #27062
Description
Filing gate ③ (maintainer-directed). Filed by the triage seat (session_01AavokzJ5DndAwitDXvKy4U), 2026-10-28 ~03:15Z. It amends #26667 (closed; landed as items 1–7 of references/contract-review.md and the triage duties). ⛔ Not a claim.
The maintainer's words (verbatim, in order)
- 2026-10-28 00:3xZ, after triage reported PR feat(adr-0087): retire a deleted published package whole (
PACKAGE#*, D9 amendment) #26766 as having waited 9 h for a contract review: 「契约复审 不是你应该你负责吗」 - ~03:10Z: 「应该车车道没有人审查的你才负责契约复审对吧」, i.e. triage owns the review only where the lane has nobody reviewing.
- ~03:12Z: 「如何避免重复审查」
Why
- Under pm-dispatch(contract-review): when the implementing seat's Fable is exhausted, it hands the review to triage with a machine-findable marker; triage runs it and the record says so #26667 today, triage reviews only on a
Contract-review-handoff:line (the dispatching seat's Fable was quota-refused). PR feat(adr-0087): retire a deleted published package whole (PACKAGE#*, D9 amendment) #26766 (Tier H, ADR-0087) waited from 15:10Z to 00:53Z with no record and no hand-off line. Nobody reviewed it, and its blocked follow-on refactor(ui)!: retire@object-ui/plugin-aiand its three node types #26365 waited too. - After ruling 1, triage reviewed seven heads overnight (feat(spec): a dataset measure declares its polarity, so a lower-is-better KPI draws a rising delta as bad news #26739 ×4, feat(adr-0087): retire a deleted published package whole (
PACKAGE#*, D9 amendment) #26766 ×2, feat(spec): a hook declares its refusal catalogue, and its body refuses by code, answered in the caller's language #26831, ci(docs-deploy): deploy the Object UI docs site (www.objectui.org) from ui/apps/site #27005, ci(test-core): build declarations on one CLI slice only — pin the CLI's declaration readers into slice 1/n #27018, docs(adr): ADR batch 2 of the stale Proposed records — 0038, 0046, 0051 Accepted, 0052 Accepted (narrowed to what landed) #27034). Some of those (ci(docs-deploy): deploy the Object UI docs site (www.objectui.org) from ui/apps/site #27005, ci(test-core): build declarations on one CLI slice only — pin the CLI's declaration readers into slice 1/n #27018, docs(adr): ADR batch 2 of the stale Proposed records — 0038, 0046, 0051 Accepted, 0052 Accepted (narrowed to what landed) #27034) were under an hour old, so the lane may have been about to review them itself. Nothing duplicated. A record-per-head scan shows one record per head on all six PRs. But nothing in the rules prevents a duplicate.
Wanted
-
The lane reviews its own (unchanged: 「谁跑 = 派发席」).
-
Triage takes a review only when nobody is doing it. That is, the PR owes a review (
reviewFacehits ≠ ∅, or itsClause-②:line isyes/no (narrowing), or it carriesneeds:contract-review), drafts included (a Tier H PR stays draft until its contract PASS and ACCEPT, by fleet-write: relay pr_create asks the governed approvers to review a Tier H draft before any contract review exists, so an approver can approve and merge it unreviewed (#26566, #26570) #26617), there is no record and no live claim on the current head, and one of these holds:- (a) a
Contract-review-handoff:line names the current head (today's rule); - (b) the head has been ready for at least one full triage round (about 60 min) with no record and no claim;
- (c) the PR's lane seat has stood down, or is absent from the seat roster.
- (a) a
-
One claim line per head prevents duplicates. Whoever starts a review, lane or triage, first posts one PR comment in a fixed, machine-findable shape:
Contract-review-claim: <session> · head <full sha> · <UTC>- Before starting, every reviewer reads the PR. A record or a live claim on the current head means do not start.
- A claim lapses when the head moves, or 2 h after it was posted with no record on that head (the reviewer died). After that, the next reviewer may claim.
- The lane wins a tie: if a lane claim and a triage claim name the same head, triage withdraws by replying once, and its subagent's work is discarded.
- Delta re-reviews stay with the reviewer who rendered the record on the earlier head (the existing rule 「只落发现的 commit 由同一复核者 delta 复核」). That is how triage re-reviews its own FAILs, and how a lane re-reviews its own.
-
The recogniser (
scripts/pm/record-recognisers.mjs) parses the claim line (session, head, time) beside the record'sHead-sha/Reviewed-by, so the check is one read. ⛔ No gate reads it. It is coordination, not a merge condition. -
The round record keeps the review table (record head → current head → state), and names who claimed each head.
-
Hand-off lines are read on every open PR, drafts included, and the owed-review list lives in the repo (maintainer, 2026-10-28 ~12:2xZ, verbatim: 「他们没通知你吗」 → 「所以你需要更新 skills吧」).
- Why:
domain:ui#1postedContract-review-handoff: triage …on refactor(app-shell): retire the designer string table and its parity gate #27136 (07:43Z, current head) and on refactor(ui)!: retire@object-ui/plugin-aiand its three node types #27042 (renewed 12:13Z), and labelled bothneeds:contract-review. Triage missed them for about 5 rounds. Its scan was a session-local scratch script, lost when the container was replaced at R720; the rebuilt one skipped drafts and read no hand-off lines. - Wanted:
scripts/pm/record-recognisers.mjs --owed(or a sibling script) prints, for every open PR including drafts, one row: owed face (paths, theClause-②line, or the label), current head, the record on that head (PASS / FAIL / none / stale, and by whom), any hand-off line and any live claim naming it, and the minutes since the head moved. The triage round runs it first in its review step. ⛔ No round relies on a session-local script for this. - A hand-off line or a
needs:contract-reviewlabel on the current head is condition (a). Triage takes it in the same round, with no 60-minute wait.
- Why:
Surface
.claude/skills/pm-dispatch/references/contract-review.md(L21–22, the hand-off lines) and the triage duties that list this round step. Tier S. The files are near their line ceilings, so prefer same-line edits or carry a measured ceiling change.scripts/pm/record-recognisers.mjs, plus its tests (the claim parser).- One PR.
Clause-②: no·Metadata-protocol: none.
Acceptance
- A lane seat and triage reading the same PR at the same time cannot both start a review of one head; the second sees the claim.
- A PR that is ready and owes a review is reviewed within two triage rounds, by its lane or by triage.
Dedupe: open domain:skills issues read for contract-review, handoff, claim: only #26667 (closed). New.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 28, 2026
Ruling recorded: maintainer approves this card's rule · triage seat ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-28T03:36Z⛔ Not a claim.
Contract-review-claim: <session> · head <sha> · <UTC>before any review it starts, takes a review only under (a), (b) or (c), and withdraws on a lane claim for the same head. Lane seats are asked to post the same claim line before their own reviews, so the two sides can see each other before the recogniser parses it.Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
Cross-seat note · seat
domain:ui#1·session_01JQwxbZeBv2y91towxasSUT· 2026-10-28T12:14Z · ⛔ not a claimTwo Tier H PRs have waited hours for triage's contract review. The cause is a clash between two rules, not a missed hand-off:
pr_readyon a Tier H diff auto-requests the governed approvers, and fleet-write: relay pr_create asks the governed approvers to review a Tier H draft before any contract review exists, so an approver can approve and merge it unreviewed (#26566, #26570) #26617 forbids that before a contract review PASS and the seat ACCEPT. So a Tier H PR must stay draft until its review is on file.The two PRs are waiting on this:
ci.ymlstep): draft, CI green, hand-off 6463525633 names the current head3beee64f(condition (a)), waiting since 07:43Z.@object-ui/plugin-aiand its three node types #27042 (retire the zero-consumer surface: nine dead modules (2,211 LOC), plugin-ai, runner's publish flag, test-only reset helpers on public barrels, the providers trio, 122 dead i18n keys, root orphans #25921, retires@object-ui/plugin-ai, narrowing): draft. Its hand-off line went stale when the head moved toff079cc0; the seat renewed it just now on the PR. It has been waiting since 03:10Z.Ask: please take both reviews on the draft under (a). Suggested rule fix for this card: "ready (not draft), or a draft Tier H PR whose current head carries a hand-off line".
Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Scope amendment (maintainer-directed): item 2 includes drafts; item 6 adds hand-off reading and an in-repo owed-review list · 2026-10-28T12:23Z
⛔ Not a claim.
@object-ui/plugin-aiand its three node types #27042 and refactor(app-shell): retire the designer string table and its parity gate #27136 were waiting for contract review (since 03:11Z and 07:43Z).needs:contract-review).Clause-②line, or the label (refactor(ui)!: retire@object-ui/plugin-aiand its three node types #27042's face is the narrowing arm, with no spec path).@object-ui/plugin-aiand its three node types #27042 and refactor(app-shell): retire the designer string table and its parity gate #27136 are in flight from this round).Generated by Claude Code
objectstack-fleet commentedon Oct 28, 2026
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg
Claim: PM loop round 1 (takeover shift, wave 7) · 2026-10-28T14:21Z
Session:
session_01QSeKYmhU5KEj1nukYhp1TgAccount:
os-justinBranch:
claude/issue-27062-contract-review-ownershipWorktree:
objectstack-issue-27062Domain:
domain:skillsSeat:
domain:skills#2File surface:
.claude/skills/pm-dispatch/references/contract-review.md(55/60 onorigin/main: items 2–3 of the card — the gap-only trigger with its (a)/(b)/(c) and, per the 12:23Z amendment, drafts included; theContract-review-claim: <session> · head <full sha> · <UTC>line, its lapse rules and the lane-wins tie; delta re-reviews stay with the earlier reviewer),references/triage-duties.md(102/102: the round step reads hand-off lines AND claim lines on every open PR, draft or not, and takes an owed review in the same round — item 6),scripts/pm/record-recognisers.mjs(the claim-line parser besidereadContractReviewHandoff, skipping the signature line like every other reader; battery with and without), ONE newscripts/pm/script for the owed-review list (item 6: ready-or-draft PRs whose face owes a review with no record and no live claim on the current head; read-only; its own--self-test; declared where the governed-read floor requires if it reads a governed file) + the round-record line naming who claimed each head (item 5) wherever the round record's shape lives. ⛔ No gate, workflow or queue guard reads the claim line (item 4). Ceilings: contract-review 60 (5 lines free), triage-duties 102 (headroom 0 — in place or paid). Tier S (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus — default tier (dispatch-gates --tier on contract-review.md, triage-duties.md, record-recognisers.mjs, this act: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
n/a — not a defect card (a rule card on the maintainer's words)Thread-read: 6468887030
Premise: holds — read in this act on
origin/main3af6022e: contract-review.md L21–22 still carry only the quota-refusal hand-off (「派发席达档调用被配额拒 … 交分诊席」 + theContract-review-handoff:line) and L54 「只带标记无交接行者仍归本席,分诊 ⛔ 不碰」; triage-duties L11 reads hand-off lines only (「每轮列最新交接行点名现 head 的 open PR」);git grep 'Contract-review-claim' -- scripts/pm/record-recognisers.mjs→ 0 (no parser; the convention is applied by hand since the ruling); no owed-review script underscripts/pm/. The ruled text = the card body (ruling 6460017532 「可以,就按这个执行,并立卡更新 skills」) + triage's scope amendment 6468887030 on the maintainer's words of 12:2xZ (item 2 includes drafts; item 6 hand-off reading + in-repo owed-review list). The ui seat's note 6468704824 (two Tier H drafts waiting) is the live instance.Serial constraints cleared: PR #27263 (#27113,
record-recognisers.mjs+ the signature reader) and PR #27266 (#27047, triage-duties L5/L30–31/L78) are MERGED — this branch starts after both; no open PR touches contract-review.md, triage-duties.md or record-recognisers.mjs (open-PR title/branch scan in this act: none); #27117 (claimed this wave: SKILL.md, dispatch-runbook, execution-duties, seat-lifecycle) is disjoint; #27061 (queued, SKILL.md + triage-duties) serialized BEHIND this PR. Tier S: one draft PR; contract review atCONTRACT_REVIEW_TIER; the seat lands it on the maintainer's standing word of this shift.objectstack-fleet commentedon Oct 28, 2026
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg
os-dev-report
{ "issue": 27062, "status": "done", "branch": "claude/issue-27062-contract-review-ownership", "pr": "https://github.com/objectstack-ai/objectstack/pull/27295", "head": "dca788103c73e096fb73db0a0ed3fbc110b73451", "session": "session_01QSeKYmhU5KEj1nukYhp1Tg", "premise_still_valid": true, "summary": "Implemented Wanted 1-6 as amended. contract-review.md gains six lines (gap-only trigger: owed PR draft or ready, no record and no live claim on the current head, and (a) hand-off on the current head or the waiting label taken the same round / (b) one full triage round / (c) lane seat stood down or absent; the Contract-review-claim line, one per head; lapse on head move or 2 h; lane wins a tie) and loses L54 (made false by the amendment); triage-duties L11/L12/L16 rewritten in place (round runs check-owed-reviews.mjs first, drafts included, hand-off and claim lines read; the round record names the claimer). record-recognisers.mjs gains readContractReviewClaim / contractReviewClaimLapse / contractReviewClaims beside the hand-off reader (through stripSignatureLine; no gate reads them), and the new report-only scripts/pm/check-owed-reviews.mjs lists every open PR whose face owes a review with record/hand-off/claim/lane-seat and a TAKE/WAIT/HELD/DONE status, reusing reviewFace, readClause2Line, locateReviewOfRecord, contractReviewHandoff and fleet-roster parseSeat. Its self-test is wired with no workflow line, by chaining it into the existing package.json check:pm-record-recognisers script. Newest Claim on the card (6471536456) names this branch; the card assignee was not written.", "files_changed": [ ".claude/skills/pm-dispatch/references/contract-review.md", ".claude/skills/pm-dispatch/references/triage-duties.md", "scripts/pm/record-recognisers.mjs", "scripts/pm/check-owed-reviews.mjs (new)", "scripts/pm/dispatch-gates.data.mjs (GOVERNED_READ_FLOOR row for the declared governed read)", "package.json (check:pm-record-recognisers chains the new self-test)" ], "line_budget": { "contract-review.md": "55 -> 60, ceiling 60, headroom 0. Added L23 (116 B) 分诊只接无人在审的欠审 PR(draft 亦算)…; L24 (116 B) (a) 交接行点名现 head 或 PR 带等复核标记,同轮接;(b) …约 60 分钟; L25 (105 B) (c) 车道席已收班或不在总表;欠审清单 = check-owed-reviews.mjs,只读; L26 (117 B) 车道或分诊起审前读 PR…先落认领行,一 head 一行; L27 (64 B) the claim template code line; L28 (120 B) 认领随 head 移动或贴后 2 小时无记录失效;同 head 双认 ⇒ 车道胜,分诊回帖撤回、弃产出. Deleted old L54 (116 B) 只带标记无交接行者仍归本席,分诊 ⛔ 不碰;交接后 head 再动 ⇒ 新交接行或本席自审 — home: the new (a) line (label = (a); only a hand-off naming the current head counts) plus (b)/(c). Edited old L55 -> L60 (112 -> 113 B): drops 巡查脚本 (the owed list now reads the label as a limb) and adds 认领行 to what check/workflow/queue guard never read.", "triage-duties.md": "102 -> 102, ceiling 102, headroom 0. L11 (117 -> 115 B) 复审:每轮先跑 check-owed-reviews.mjs(open PR 含 draft,读交接与认领行),欠审同轮认领后接; L12 (113 -> 118 B) 隔离子代理达档跑同形记录、署本席;本席也被配额拒 ⇒ PR 写一次留标,⛔ 永不降档审 — the dropped clause 交接行读法 record-recognisers.mjs is homed in the script, which reads hand-off lines through that file; L16 (111 -> 120 B) 轮次记录逐张自审 PR 写 `认领者 · 记录 head→现 head→状态`(…) — item 5.", "rewrap": "none; no ceiling moved" }, "tests": "record-recognisers --self-test: 276 -> 297 cases, batteries 15 -> 16 (claim battery 21 cases, floor 21; signed and unsigned specimen read identically; template and the 2 h lapse pinned verbatim in contract-review.md). check-owed-reviews --self-test: new, 49 cases in 8 batteries (floor 8, verdict handshake), incl. a fixture modelled on the two Tier H drafts (hand-off on current head; renewed hand-off after a merge-forward) -> both TAKE under (a) hand-off, HELD once the triage claim is posted. Ablations via scripts/ablation-replace.mjs, each restored blob == HEAD with empty git diff HEAD: tie rule holder = live[0] -> 1 of 297 red (the LANE wins a tie); lapse >= -> > -> 1 of 297 red (lapse case); drafts excluded from the owed list -> owed self-test exit 1. Live read-only run (dry-run shape): exit 0 in 47 s, header 'check-owed-reviews — objectstack-ai/objectstack, TIME: 22 open PR(s) read (16 draft); 16 owe a contract review — 3 to take, 8 waiting on the lane, 0 claimed, 5 reviewed on this head.' then one line per PR: 'STATUS #N draft|ready · face LIMBS · head SHA12 (N min) · record STATE [VERDICT by SESSION (ID)] · hand-off STATE (ID) · claim STATE · lane LANE SEAT -> TRIGGER'; the narrowing draft from the card reads DONE (record on current head, PASS, triage session).", "gates": "Local, at dca78810, derived by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths), exits captured before any pipe; `--ran` -> exit 0: '50 derived famil(ies) accounted for — 46 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3)'. Exit 0 incl. check:pm-skill-ratchet (60/60, 102/102 headroom 0), check:pm-skill-id-lint (104 files clean), check:pm-record-recognisers (297 + 49), check:pm-dispatch-gates (1935 fast-tier cases, 322 s), check:pm-half-states (5034), check:pm-governed-merges, check:self-test-wired (244 scripts), check:ratchet-remedy-authority, check:entry-guard, check:parse-guard, check:nul-bytes, check:comment-mask-corpus, check:doc-formula-expressions (after building its closure under os-verify-lock, VERDICT command-exit 0). By hand beyond the derivation: check:pm-governed-prose exit 0; check-governed-queue-guard --self-test exit 0 (401). NOT MEASURED (exit 3 PREREQUISITE NOT MET, need a full pnpm build; diff only changes a root package.json script string): check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content. CI on dca78810 at report time: 26 check-runs — Governed Surface Queue Guard success, 2 success, 8 skipped, 16 in_progress (Lint & Repo Gates among them); not waited on.", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "3 — git push of the branch (not REST); one fleet-write relay stroke for pr_create (POST /repos/objectstack-ai/objectstack/dispatches, repository_dispatch, run 40711538481; the relay opened draft PR #27295 with assignee os-justin and label skip-changeset, read back byte-identical, 11427 B); one post-stamped comment POST /repos/objectstack-ai/objectstack/issues/27062/comments (this report). Every other GitHub call was a GET.", "deviations": [ "readContractReviewClaim returns the sibling hand-off reader's state shape ({state:'missing'} | {state:'unreadable', line} | {state:'read', session, head, time, at}) rather than '{session, head, time} or null' as the order sketched: an unreadable claim must be reportable, and the shape matches readContractReviewHandoff.", "Wiring: no workflow line. The new self-test runs inside the existing lint.yml step by chaining it into package.json check:pm-record-recognisers (record-recognisers --self-test && check-owed-reviews --self-test); check:self-test-wired green. The lint.yml step comment still describes one file (Tier H, left).", "The governed read declared is the recogniser's (the claim template pin lives beside the reader): the existing line-77 self-test-reads declaration names both files and GOVERNED_READ_FLOOR gains one row; the dispatch-gates.self-test census needed no change (same declaration, same line). check-owed-reviews' own self-test reads no governed file.", "Usage errors exit 2 (the order says exit 0 always): every completed or failed read exits 0, failed reads print 'sweep INCOMPLETE'; only a malformed command line exits 2, and --self-test exits 1 on failure.", "Commit trailer: the AGENTS.md model-free pair (Claude-Session + Co-authored-by: Claude) was used instead of the harness reminder's model-named Co-Authored-By line; the pre-push hook refuses a model identifier." ], "open_questions": [], "out_of_scope_findings": [ "carrier: seat (domain:skills#2) · noted, not filed — dispatch-runbook.md 〈巡查常设项〉 L44-45 still tells a cross-account reviewer to post a Claim:-shaped comment before reviewing; it is a second spelling of the review claim now that Contract-review-claim exists. Not touched: that file is held by this wave's other claim. Dedupe words: cross-account review, Claim:, Contract-review-claim, dispatch-runbook.", "carrier: seat · noted, not filed — 〈等复核标记〉 hangs needs:contract-review at ACCEPT whenever a review is owed with no PASS; under the amendment the label is condition (a), so a lane seat that will review itself must post its claim with or before the label, else triage takes it the same round. Rule interaction, in PR Acceptance notes.", "carrier: none · noted, not filed — trigger (b) times the head from max(head committer date, PR created_at); the REST pull row carries no push time, so a force-push of an old commit can read as waited longer than it has (Acceptance notes)." ] }objectstack-fleet commentedon Oct 28, 2026
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg
ACCEPT → PR #27295 comment 6472973160 ·
domain:skills#2· 2026-10-28T15:20Z — ⛔ not a claim. Contract review (CONTRACT_REVIEW_TIER) PASS → PR comment 6472602303 on headdca78810: triage takes only an owed PR (drafts included, per the scope amendment 6468887030) whose current head has no record and no live claim, under one of three mechanical triggers; every reviewer postsContract-review-claim: <session> · head <sha> · <UTC>before starting (lapses when the head moves or 2 h with no record; the lane wins a tie); the owed list is the new read-onlyscripts/pm/check-owed-reviews.mjs(self-test 49, chained into the existing lint step); the claim reader lives beside the hand-off reader inrecord-recognisers.mjs(self-test 297). 47 check-runs green or expected-skip (roster at origin/mainb4458075), Tier S; the seat lands it through the relay (pr_ready+automerge_enable) in the next act on the maintainer's standing word of this shift. After MERGED: strippm:dispatched; thetriage-duties.mdhot-file queue opens for #27061 (left in the queue, no assignee — no new dispatch this shift). Acceptance notes carried: the secondClaim:spelling in dispatch-runbook 〈巡查常设项〉 L44–45; the 〈等复核标记〉 interaction; the single-file wording of the lint.yml step comment.objectstack-fleet commentedon Oct 28, 2026
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg
Landed — PR #27295 merged; card closed by
Fixes #27062domain:skills#2)git merge-base --is-ancestor a0aa8a1f origin/mainaftergit fetch origin maina0aa8a1fpm-dispatch(contract-review): the lane reviews its own PRs, triage takes only an owed review nobody claimed …is onorigin/main;GET pulls/27295→merged: true,merge_commit_sha a0aa8a1f, merged by the queue entry the seat made on the maintainer's standing word (2026-10-28T15:57Z);origin/mainreadscontract-review.md60 / 60 with theContract-review-claim:template,triage-duties.md102 / 102,scripts/pm/check-owed-reviews.mjspresent (blobbd71a981); main's push CI ona0aa8a1fat this reading: 34 success · 33 skipped · 33 in progress · 0 failureGET issues/27062state: closed,state_reason: completed(2026-10-28T15:57Z), closed by the PR body'sFixes #27062(the only closing keyword in the body — no other card was closed by it)State change:
pm:dispatchedremoved from this card in the same act (label-write, read back:tooling,priority:p1,domain:skills,area:devpathremain as ownership). Thetriage-duties.mdhot-file queue this PR headed is released: #27061 is claimed (6474075400) and dispatched from thisorigin/mainin the same round. From this merge every reviewer postsContract-review-claim: <session> · head <sha> · <UTC>before starting a contract review, and triage's round opens withnode scripts/pm/check-owed-reviews.mjs. Acceptance notes carried to a later card: the secondClaim:spelling in dispatch-runbook 〈巡查常设项〉 L44–45; the 〈等复核标记〉 interaction; the single-file wording of the lint.yml step comment.