Skip to content

pm-dispatch(triage): a round reads every main and queue red since the last record, answers pm:retriage on epics, and a lane holds a head with a Contract-review-hold: line that check-owed-reviews reads - #27468

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-27370-triage-reads-the-gap-and-hold-line
Oct 29, 2026

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #27370
Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:分诊每轮改读「上份轮次记录 fire 以来」全部 main push、schedule 与合并队列结论,窗内无锚的红当轮立锚卡、按首触定级(主干全量红与确定性队列红 p0,flake 判确定性才升;main 已转绿也照立并点名承修卡),断档逾 90 分钟在记录里写明;pm:epic 卡上的 pm:retriage 即答;车道可落一行 Contract-review-hold: 暂缓本 head 送审,check-owed-reviews.mjs 读它:活的 hold 只挡 (b)、新 head 即清、逾 24 小时列进分诊轮次记录;triage-duties.md 新 L3 写回分诊职责边界(本文加技能他处点名分诊之条即全部职责)。
  • 为什么改:10-28 分诊停了约 10 小时,回来第一轮只读最新一跑,两次 main 红没有锚卡;一张 epic 上问分诊的三个问题等了约 10 小时;车道用散文说「这个 head 先别审」,分诊按 (b) 认领后又撤回。现在主干红在断档里漏不掉,epic 的提问当轮有答,「先别审」是一行脚本读得懂的字,不再靠人重读散文。
  • 风险与回滚:只改两份技能文本(行数不变:60/60、102/102)与两个只报不拦的脚本;不新增门禁、check-run、workflow 步骤或半状态行。回滚 = revert 本 PR。hold 按 head 读:写错格式的行什么都不挡、也不使已有的有效 hold 失效,并以 ⚠️ 列出;全部 hold 行都读不懂时才读作 unreadable。
  • 先看:① scripts/pm/check-owed-reviews.mjs 的 owedReviewRow((b) 让位于活 hold 的两行与 listed);② scripts/pm/record-recognisers.mjs 的 readContractReviewHold / contractReviewHold(四段解析、按 head 读、24 小时只是读数);③ references/contract-review.md L29–31 与 references/triage-duties.md L3、L27–28、L61。
  • 两分钟验证:node scripts/pm/record-recognisers.mjs --self-test && node scripts/pm/check-owed-reviews.mjs --self-test,预期尾行 320 cases pass 与 63 cases pass in 9 batteries。
  • 需要你做的:无,席位落地(.claude/** 为 Tier S:分诊契约复核 PASS 6491338629 + delta PASS 6493363887 在案后入队)。另有一项待您裁(复核 should-fix 4,本 PR 未建):活 hold 只挡 (b),车道收班即触发 (c) 让分诊接手 —— A 在 contract-review.md L30 写明 (a)(c) 照触发,B 让未满 24 小时的 hold 也挡 (c)。

What changes

Three rules, one line each in the file that owns it, and one reader of an existing list. No new gate, check-run, workflow step or half-state row.

.claude/skills/pm-dispatch/references/triage-duties.md — 102 → 102 lines

  • L3 (new, rework 168cb1e8, triage should-fix 2): 「本文与技能他处点名分诊之条(复审、摘 pm:retriage、约定③ 等)即分诊座位的全部职责。」 — the scope bound restored in its true closed-world form; paid by folding old L99 「需裁事项攒批(≤5 项/批,每项一行带推荐),一句同意即全链执行。」, whose home is lanes/director.md 〈职责二〉 L48 / L56 under SKILL.md L276 (this file's L99 keeps 「方向性授权覆盖整条执行链」).
  • Item 1, L27–28 (new): each round reads every main push, schedule and merge-queue conclusion since the previous round record's fire time, ⛔ not only the newest run; an unanchored red in that window gets an anchor in the round, graded as first touch grades it (L30: main full red and deterministic queue red p0, a flake anchor raised only once deterministic — rework 168cb1e8, triage should-fix 1) — main green again still files it and names the card that carries the fix; a round with no record for over 90 minutes says so in its record.
  • Item 2, L61 (in place, beside 「父单永不派发」): a pm:epic card's pm:retriage is answered at once; parents are still never dispatched.
  • L10 (in place, bytes only): the review step names the hold line among what check-owed-reviews.mjs reads.

.claude/skills/pm-dispatch/references/contract-review.md — 60 → 60 lines

  • Item 3, L29–31 (new), beside the claim lines L26–28:
    • L29: a lane deferring review of this head posts Contract-review-hold: SESSION · head SHA · REASON · until CONDITION (the template, verbatim in a code span; placeholders spelled in angle brackets in the file).
    • L30: a new head clears it; while it names the current head, gap rule (b) does not fire; once the condition is met the holding lane hangs needs:contract-review or posts a hand-off line.
    • L31: a hold over 24 hours with its condition unmet is listed in the triage round record (check-owed-reviews.mjs marks it).
  • L60 (in place, bytes only): no check, workflow or queue guard reads the hold line either.

scripts/pm/record-recognisers.mjs — the recogniser, beside its siblings

  • CONTRACT_REVIEW_HOLD_KEY / CONTRACT_REVIEW_HOLD_TEMPLATE / CONTRACT_REVIEW_HOLD_LIST_HOURS = 24, built with the file's one keyLineRegex convention.
  • readContractReviewHold(text): four facts split on the doorbell's dot — the session (the claim reader's session regex, not a second spelling), head 7–40 hex, a non-empty reason, until plus a non-empty condition. A missing fact, a fifth part, a reason that is itself the until clause, or a session of another shape is started-and-unreadable; the template copied unedited is unreadable.
  • contractReviewHold(rows, headSha, { now }) (per head since rework 168cb1e8, triage should-fix 3): the newest READABLE hold naming the current head (prefix either way) is live whatever is posted after it; a newer readable hold naming an earlier head does not clear it (only a new head clears); stale only when readable holds exist and none names the current head; unreadable only when every hold line is unreadable; absent when none. Every reading carries unreadable[] (comment id, stamp, quoted line), so a malformed line voids nothing and is never silent. Age is timed from the comment's created_at; at 24 hours overdue: true, which is a reading — the hold stays live. No stamp gives overdue: null (unknown), never false.
  • Additive: new exports only, no signature change; the hand-off and claim readers are untouched (pinned below). The self-test-reads declaration keeps its line 77, which the dispatch-gates census pins.

scripts/pm/check-owed-reviews.mjs — the reader

  • Each row carries hold (state, id, session, reason, until, at, ageMinutes, overdue, holds, listed, gaps, unreadable); the row prints ⚠️ N unreadable hold line(s) (IDS) beside a live or stale hold.
  • Trigger (b) yields to a live hold; (a) and (c) still fire — the holding lane ends its hold with (a), and a lane seat that is gone is (c).
  • Status stays one of four. A held head is WAIT (the lane's own), and the row prints the hold and the (b) it holds.
  • listed = a live hold that is overdue or cannot be timed, on a WAIT row. The row ends ⏳ HOLD 24 h old — list it in the triage round record, and the report adds a block under the rows naming the PR, holder, post time, age and condition.

Tests

Self-test before (c5d46341) after (168cb1e8)
node scripts/pm/record-recognisers.mjs --self-test 297 cases, floor 16 batteries 320 cases (+23), floor 17 — new battery the Contract-review-hold: line … (23)
node scripts/pm/check-owed-reviews.mjs --self-test 49 cases in 8 batteries 63 cases in 9 batteries (+14) — new battery the hold: … (14)

Pinned:

  • The recogniser's shape (decoration, lowercasing, the 7-hex floor, every refusal), the template verbatim in contract-review.md beside 「24 小时」, per head (only a new head clears; a newer readable hold on an earlier head does not clear a hold on this head; an unreadable line voids nothing and is listed), and prefix matching.
  • The 24-hour age as a reading: 23 h 59 min reads live and not overdue; 24 h reads live and overdue.
  • No gate reads it: a record beside a hold still reads FOUND, and the claim and hand-off readings are unchanged.
  • In the reader: the same row is TAKE (b) without a hold and WAIT with one. A stale or unreadable hold holds nothing. (a) and (c) still fire under a hold. HELD and DONE are unchanged. Listing works at 24 h, an unknown age is listed rather than dropped, and nothing is listed on DONE or HELD rows. --json carries the hold through the live reader, and the status vocabulary is pinned at exactly four.

Acceptance notes

  • Rework 168cb1e8 (triage record 6491338629, should-fix 1–3, seat decision 6491385759): delta PASS 6493363887 by the same reviewer. Should-fix 4 (trigger (c) under a live hold) is not built; it is the maintainer's call, put in 维护者速读.
  • Out of scope, noted: lanes/triage.md L7 「每 fire 最旧优先」 vs triage-duties.md L24 「队列每轮清空时最新优先」 disagree when the queue clears every round; AGENTS.md 〈Multi-agent working discipline〉 still says the PR's assignee mirrors the card's at pr_create (Tier H, the maintainer's hand).
  • Tier: the card says 「Tier H (.claude/**)」. By AGENTS.md Prime Directive 14 and the register GOVERNED_SURFACES in scripts/pm/check-governed-merges.mjs (row claude-tree, GOVERNED_TIER_S), .claude/** is Tier S, and scripts/pm/** is off the register. The seat lands this after its own contract review.
  • Folded clauses (lines paid by deletion, each restated where named):
    • triage-duties.md old L3 「分诊席每次 fire 开局读本文;本文是分诊座位的全部职责。」 and its blank separator L4. Reader and scope are SKILL.md 〈阶段细则索引〉 L86 (「分诊席每次 fire 开局」 · 「分诊座位职责」). Rework 168cb1e8 restores the bound as new L3 in a true closed-world form (this file plus every clause of the skill that names triage), paid by folding old L99 (home: lanes/director.md L48 / L56 under SKILL.md L276). The original 「全部」 was not true of this file alone: triage duties also live in contract-review.md, state-machine.md L40 (answering pm:retriage, the duty item 2 is about) and landing-operations.md 约定③. Four other references (filing-gate.md, seat-lifecycle.md, cross-repo-coordination.md, execution-duties.md) already open without a header sentence.
    • triage-duties.md L60 「涉 cloud 整卡归 cloud 车道」, bytes only, paying item 2's clause. Restated by SKILL.md L165 (domain:cloud: 「涉 cloud 即整卡归 cloud PM」) and cross-repo-coordination.md L44 (same words), which triage reads before routing per SKILL.md L85. 「路由是分诊的技术判断」 → 「路由属分诊技术判断」 keeps the meaning.
    • contract-review.md old L30–31 → L33, dropping 「(申报面外三面加 ④)」. Restated by the same file's L39 (「④ 设计判断欠 schema、governed 规则文本、收窄三面」) and L41 (「余面同形无 ④」).
    • contract-review.md old L43, the isolated reviewer's scratch rule. record-recognisers.mjs --brief-template prints it in the brief's ⛔ READ-ONLY block, and that script's self-test pins it ("…and scopes scratch to the PR-named directory, reading nothing not written this round"). L44 makes that template the brief's starting point and forbids deleting its ⛔ lines.
    • contract-review.md old L48–49 → L49, dropping 「判据机读已提交树」. Restated by the same file's L17 (「面读 PR 已提交树的文件清单」) and triage-duties.md L11 (「纯重生成/只动散文面例外(判已提交树)」). The reader that decides it is record-recognisers.mjs, battery "a pure-regeneration head move KEEPS the record, decided on the COMMITTED trees".
  • Item 2's home: the sentence 「父单是协调节点」 does not exist on origin/main c5d46341 (zero hits under .claude/ and scripts/pm/). The nearest are triage-duties.md L60 「父单永不派发」 and filing-gate.md L16 「④ 协调节点」, so item 2 rides L60. L75's exception list governs the stale-premise re-check of in-flight cards (L73–75), not pm:retriage answers, which state-machine.md L40 governs.
  • Item 3's 24-hour clause lives in contract-review.md with the rest of the hold rule, not in triage-duties.md. Reason: the recogniser's self-test may read only the two governed files GOVERNED_READ_FLOOR already declares for it (project-forms.md, contract-review.md), and it pins the template and 「24 小时」 there.
  • WAIT, not a fifth HOLD status (measured): git grep check-owed-reviews finds no in-repo consumer of --json. In the file, a new status would touch STATUS_ORDER, the header counts, the row regex and the trigger condition, and HOLD sits one letter from HELD. A held head is the lane's own wait, so it stays WAIT, with the hold printed and listed.
  • The hold's age is a reading, never a lapse: whether a free-text condition is met is no reader's to judge. An overdue hold still holds (b) and is listed, so it cannot become a silent skip.

Verification

Every reading below is from head 167b0027; the rework head 168cb1e8 re-ran the union with the same result (40 derived, 40 run, 0 NOT-MEASURED; check:doc-formula-expressions again exit 3 → prerequisite build → 0; check:pm-dispatch-gates 1935 cases), reported in the second os-dev-report on #27370.

  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths): 4 paths against merge base c5d46341, 40 commands. --ran: exit 0 — 「40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN」. All 40 exited 0.
  • Edited-script consumers outside the derived set: post-stamped.mjs --self-test (735 cases), check-governed-queue-guard.mjs --self-test (401, loads record-recognisers.mjs through its real lazy import) and mailbox-open.mjs --self-test (45) all exit 0.
  • Live, read-only: node scripts/pm/check-owed-reviews.mjs at 2026-10-29T06:37Z read 22 open PRs (17 draft) and listed 13 owing rows. Each prints hold absent, since no hold line exists yet. Exit 0, no sweep INCOMPLETE.
  • Line ratchet: triage-duties.md 102/102 and contract-review.md 60/60, headroom 0, every changed line ≤120 B (below).
  • Two readings from the earlier head 0c9c1c53, both resolved before the final run:
    • check:pm-dispatch-gates failed 1 of 1935 cases. The declaration census pins scripts/pm/record-recognisers.mjs:77 self-test-reads, and my new header roster line had moved that declaration to :78. 167b0027 folds the roster entry into the existing hand-off/claim roster line, and the gate is green at 1935 cases.
    • pnpm --filter @objectstack/lint run check:doc-formula-expressions exited 3, a prerequisite refusal (@objectstack/lint and @objectstack/formula not built). I built them under the verify lock (os-verify-lock: VERDICT command-exit 0, turbo cache hits), and it exits 0 on the final run.
  • Not run locally, CI-owned: the repo-wide scans (pnpm lint, Test Core). check:dev-prereqs and check:skill-frame-freshness are not owed: the diff touches neither packages/spec nor the four-axis frame.
The 40 derived commands and their exit codes (the run record fed to --ran)
  • node scripts/check-closing-keyword-parity.mjs — exit 0
  • node scripts/check-closing-keyword-parity.mjs --self-test — exit 0
  • node scripts/check-comment-mask-corpus.mjs — exit 0
  • node scripts/check-declaration-mirrors.mjs — exit 0
  • node scripts/check-declaration-mirrors.mjs --self-test — exit 0
  • node scripts/check-self-test-wired.mjs — exit 0
  • node scripts/check-self-test-wired.mjs --self-test — exit 0
  • node scripts/check-self-test-workflow-commands.mjs — exit 0
  • node scripts/check-self-test-workflow-commands.mjs --self-test — exit 0
  • node scripts/check-whole-set-label-write.mjs — exit 0
  • node scripts/check-whole-set-label-write.mjs --self-test — exit 0
  • node scripts/ci/plan-test-core-shards.mjs --self-test — exit 0
  • node scripts/pm/bare-root-worklist.mjs --self-test — exit 0
  • node scripts/pm/check-harness-current.mjs --self-test — exit 0
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions — exit 0
  • pnpm check:agent-test-spelling — exit 0
  • pnpm check:bash32-floor — exit 0
  • pnpm check:ci-filter-parity — exit 0
  • pnpm check:cli-command-ids — exit 0
  • pnpm check:cross-package-test-inputs — exit 0
  • pnpm check:doc-authoring — exit 0
  • pnpm check:driver-memory-census — exit 0
  • pnpm check:entry-guard — exit 0
  • pnpm check:gitlink-declared — exit 0
  • pnpm check:nul-bytes — exit 0
  • pnpm check:parse-guard — exit 0
  • pnpm check:pm-dispatch-gates — exit 0
  • pnpm check:pm-governed-merges — exit 0
  • pnpm check:pm-half-states — exit 0
  • pnpm check:pm-label-write — exit 0
  • pnpm check:pm-record-recognisers — exit 0
  • pnpm check:pm-skill-id-lint — exit 0
  • pnpm check:pm-skill-ratchet — exit 0
  • pnpm check:pnpm-filter-targets — exit 0
  • pnpm check:pnpm-flag-spellings — exit 0
  • pnpm check:ratchet-remedy-authority — exit 0
  • pnpm check:refd-timer-probe — exit 0
  • pnpm check:scripts-symbol-anchors — exit 0
  • pnpm check:skill-frame-sync — exit 0
  • pnpm check:watch-hint-literal — exit 0
Every changed governed line, with its bytes as counted in the file (the hold template spelled with placeholders here)

.claude/skills/pm-dispatch/references/contract-review.md

+ 113 B  - 车道暂缓本 head 送审落 `Contract-review-hold: SESSION · head SHA · REASON · until CONDITION`
+ 111 B  - 新 head 即清;点名现 head 时 (b) 不起;条件满足由持有车道挂等复核标记或落交接行。
+  96 B  - 逾 24 小时条件未满的 hold 列入分诊轮次记录(`check-owed-reviews.mjs` 标出)。
- 111 B  - 同形 = `## Contract review` 题头、head sha 独占码段、①②③ 逐项(申报面外三面加 ④)、
-  29 B    独立性对、PASS/FAIL。
+ 111 B  - 同形 = `## Contract review` 题头、head sha 独占码段、①②③ 逐项、独立性对、PASS/FAIL。
- 118 B  - 隔离复核子代理暂存全写按所审 PR 命名的 `SCRATCHPAD/pr-N/`,⛔ 不读非本轮自写的暂存。
- 104 B  - 例外:纯重生成或只动上列散文面的 head 后移原记录继续管;判据机读已提交树;
-  35 B    PR 落 `Regen-provenance:` 行。
+ 112 B  - 例外:纯重生成或只动上列散文面的 head 后移原记录继续管;PR 落 `Regen-provenance:` 行。
- 113 B  - ⛔ 无 check、workflow 或队列守卫读标记与认领行;入队只认同形记录,标记有无不改判。
+ 119 B  - ⛔ 无 check、workflow 或队列守卫读标记与认领/hold 行;入队只认同形记录,标记有无不改判。

.claude/skills/pm-dispatch/references/triage-duties.md

-  76 B  分诊席每次 fire 开局读本文;本文是分诊座位的全部职责。
-   0 B  
- 115 B  - 复审:每轮先跑 `check-owed-reviews.mjs`(open PR 含 draft,读交接与认领行),欠审同轮认领后接。
+ 119 B  - 复审:每轮先跑 `check-owed-reviews.mjs`(open PR 含 draft,读交接/认领/hold 行),欠审同轮认领后接。
+ 113 B  - 每轮读上份轮次记录 fire 以来全部 main push、schedule 与队列结论,⛔ 不只读最新一跑。
+ 119 B  - 窗内无锚红当轮立锚卡、照首触定级,转绿照立并点名承修卡;逾 90 分钟无记录记明断档。
+ 118 B  - 本文与技能他处点名分诊之条(复审、摘 `pm:retriage`、约定③ 等)即分诊座位的全部职责。
-  87 B  - 需裁事项攒批(≤5 项/批,每项一行带推荐),一句同意即全链执行。
- 119 B  - 路由是分诊的技术判断,⛔ 不升级哪个仓的问题;涉 cloud 整卡归 cloud 车道;父单永不派发。
+ 118 B  - 路由属分诊技术判断,⛔ 不升级哪个仓的问题;父单永不派发,`pm:epic` 卡 `pm:retriage` 即答。

Generated by Claude Code

… answer pm:retriage on pm:epic cards, and a lane holds a head with a Contract-review-hold line

triage-duties.md: each round reads every main push, schedule and merge-queue
conclusion since the previous round record's fire time; an unanchored red in
that window gets a p0 anchor in the round (main green again still files it,
naming the carrying card); a gap over 90 minutes is noted in the record.
L60: a pm:epic card's pm:retriage is answered at once (parents are still
never dispatched). Paid by dropping the header line (SKILL.md's index row
states its reader and scope) and L60's cloud clause (SKILL.md domain:cloud
row and cross-repo-coordination.md state it verbatim).

contract-review.md: the Contract-review-hold line beside the claim line:
per head, (b) does not fire while it names the current head, the holding
lane hangs the waiting marker or posts a hand-off once its condition is met,
and a hold over 24 hours is listed in the triage round record. Paid by three
folds whose clauses are stated elsewhere (named in the PR body).

Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg
Co-authored-by: Claude <noreply@anthropic.com>
…d line; check-owed-reviews lets a live hold hold trigger (b) and lists a hold at 24 hours

record-recognisers.mjs: readContractReviewHold reads the line (session,
head 7-40 hex by prefix, reason, until CONDITION; a missing fact or a fifth
part is unreadable and holds nothing); contractReviewHold reads the thread,
newest governs: live on the current head, stale once the head moved, its age
from the comment's created_at a reading (overdue at 24 hours), never a lapse.
Self-test: a hold-line battery of 19 cases, the template and its 24-hour
listing pinned verbatim in contract-review.md; floor 16 -> 17.

check-owed-reviews.mjs: the row carries a hold field; trigger (b) yields to a
live hold while (a) and (c) still fire; status stays one of four (WAIT for a
held head); a live hold 24 hours or older on a WAIT row is listed, in the row
and under the report, for the triage round record. Self-test: a hold battery
of 13 cases; floor 8 -> 9.

Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg
Co-authored-by: Claude <noreply@anthropic.com>
…tion on line 77

The hold reader's entry in the header roster rides the existing hand-off and
claim roster line instead of a new line, so the declaration stays on the line
the dispatch-gates declaration census pins (scripts/pm/record-recognisers.mjs:77).

Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 29, 2026
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation labels Oct 29, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429 rate_limit: the account's ceiling-tier quota is exhausted, 2026-10-29T07:38Z) · head 167b002

The dispatching seat holds no claim and no record on this head and will not review it below tier (contract-review.md 〈复核归属与资格〉: 「派发席达档调用被配额拒(HTTP 429)⇒ ⛔ 不降档审;PR 落交接行、留等复核标记,交分诊席」). The maintainer's words this session: 「没有fable了,用 opus 完成开发,然后等分诊契约复审」. needs:contract-review hangs on this PR in the same stroke.

For the reviewer (inputs, not conclusions): the card is #27370 (filed by triage under gate ③ on the maintainer's 「立卡」); paths .claude/** ×2 (Tier S — the card's 「Tier H」 is corrected in the seat's claim 6489397583) + scripts/pm/** ×2 off the register; the order asked for no new gate, one reader of an existing list (check-owed-reviews.mjs learns the hold line, recogniser beside its siblings in record-recognisers.mjs), and the two governed files at their line ceilings (102 / 60) paid by folding. The dev report is on the card (os-dev-report, head 167b002); it names its folds and their homes, and that it ran no ablation (os-dev.md forbids ablating a script; the suppression pin carries its own control leg). Note for this review: this PR writes the very hand-off/hold rules triage applies here — the reviewer reads them as text under review, not as rules in force. After a PASS the seat writes its ## 席位核对 ACCEPT and lands it (Tier S: pr_ready + automerge_enable).

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head 167b0027935bc412f825dbb9bd4859e93eb934ef · 2026-10-29T07:53Z

Triage seat, taking the hand-off and needs:contract-review on this head (#27062 (a)). ⚠️ This PR changes triage's own rules (#27370, which triage filed), so the review is done by a reviewer that did not draft the card, and the seat's ACCEPT and the maintainer's approval stay the gate. The review runs at CONTRACT_REVIEW_TIER. If the lane claims or posts a record on this head first, triage withdraws.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 167b0027935bc412f825dbb9bd4859e93eb934ef
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/contract-review.md, .claude/skills/pm-dispatch/references/triage-duties.md + scripts/pm/check-owed-reviews.mjs, scripts/pm/record-recognisers.mjs, scripts/pm/check-half-states.mjs (latestMarkedComment), scripts/pm/check-governed-merges.mjs (GOVERNED_SURFACES), scripts/pm/check-skill-line-ratchet.mjs (ceilings 60 / 102), .claude/skills/pm-dispatch/SKILL.md (L29, L85–86, L113, L164–165), references/state-machine.md (L40), references/cross-repo-coordination.md (L44), references/filing-gate.md (L16), references/landing-operations.md (L76–84), .github/workflows/lint.yml (L1038, L1274), package.json (check:pm-record-recognisers, check:pm-skill-ratchet)

Inputs read: card #27370 body and its three comments (claim 6489397583, amendment 6489441362, os-dev-report 6490831569); PR #27468 body, file list (4 paths), net diff vs main; the two PR comments (hand-off 6490872952, triage claim 6491144568); 51 check-runs on the head, all completed, none pending: 27 success (Test Core and its shards, every Lint job including Lint · PM dispatch-gates which runs check:pm-skill-ratchet and check:pm-record-recognisers, every Type Check job, Governed Surface Queue Guard, PR-body guards, Check Changeset, Check PR Size), 24 skipped by path filter, 0 failures. Rulings #27062 and #27047 fetched by gh api GET. Files read with git show prr-27468: and origin/main:; nothing built, run or checked out. Note taken from the hand-off: this PR writes the hold and hand-off rules triage applies here; they were read as text under review, not as rules in force.

① Derived judgments

  • Accept set / public surface: no packages/** path is touched; nothing published changes. Right — Clause-②: no, Metadata-protocol: none match the diff.
  • scripts/pm/record-recognisers.mjs: additive exports only (CONTRACT_REVIEW_HOLD_KEY, CONTRACT_REVIEW_HOLD_TEMPLATE, CONTRACT_REVIEW_HOLD_LIST_HOURS, readContractReviewHold, contractReviewHold); contractReviewHandoff / contractReviewClaims bodies untouched; the self-test-reads declaration stays on L77 and only its rationale text changes. Right — internal PM tooling, off the governed register (GOVERNED_SURFACES rows: .claude/** is claude-tree Tier S in objectstack; no scripts/pm row), as the claim's correction of the card's 「Tier H」 says.
  • scripts/pm/check-owed-reviews.mjs: --json rows gain a hold object (additive); the status vocabulary stays TAKE,WAIT,HELD,DONE (pinned); trigger (b) alone yields to a live hold; a live overdue or untimed hold on a WAIT row is listed. git grep on the head finds no in-repo consumer of --json and exactly one consumer of the three sibling readers (this file, L242–244). Right.
  • Gate surface: the live reader is not wired into any workflow (.github/workflows names only the self-test via check:pm-record-recognisers); report-only, exit 0. No new check-run, workflow step or half-state row. Right — the card's 「新增门禁默认否」 holds, and contract-review.md L60 (「无 check、workflow 或队列守卫读…hold 行」) is true of the tree.
  • Governed text, line for line — triage-duties.md: L9 adds 「hold 行」 to what the review step reads (right, the reader does read it); L26 reads every main push, schedule and queue conclusion since the previous round record (right, card item 1); L27 anchors unanchored window reds p0, green-again included, and records a gap over 90 minutes (right against the card's words; see ④ should-fix 1 for its breadth); L60 answers pm:retriage on pm:epic cards at once, parents still never dispatched (right, card item 2). contract-review.md: L29 template, L30 per-head clearing / (b) does not fire / lane ends it with label or hand-off, L31 24-hour listing (right, card item 3 verbatim); L33, L49 fold restatements (right, see ③); L60 adds 「/hold」 (right).
  • Folds, each checked at its claimed home on origin/main: old triage-duties L3 → SKILL.md L86 row (reader and timing present; the 「全部职责」 bound has no home — ④ should-fix 2); 「涉 cloud 整卡归 cloud 车道」 → SKILL.md L165 and cross-repo-coordination.md L44, both 「涉 cloud 即整卡归 cloud PM」 (present); 「(申报面外三面加 ④)」 → contract-review.md L39 and L41 (present); the isolated reviewer's scratch rule → --brief-template ⛔ block (confirmed in this review's own brief: 「Scratch space is … alone; nothing there you did not write this round is read」) pinned by self-test L2529, kept by L44 (present); 「判据机读已提交树」 → contract-review.md L17 and triage-duties.md L11 (present).
  • 「父单是协调节点」: zero hits under .claude/skills/pm-dispatch on origin/main; nearest are triage-duties L60 「父单永不派发」 and filing-gate L16 「④ 协调节点」. Item 2 riding L60 is right.

② Semver level

No package touched; skip-changeset label present; Check Changeset success. Clause-②: no on the PR body and the claim; no changeset is owed and none is written. Matches. The declared face is none; the tier here comes from the two governed paths (rules face), not from the Clause-② line.

③ Boundary flags

open_questions: none. Dev deviations, each answered:

  1. Ablation not run (os-dev.md forbids ablating a script) — accepted: the pin case 「⭐ a live hold on the current head holds (b)…」 carries its control leg in-case (same row reads TAKE with no hold, WAIT with one); removing the hold.state !== 'live' guard reds it.
  2. Stale role definition at the shared checkout — no bearing on the committed tree.
  3. AGENTS.md 「assignee mirrors the card's」 vs os-dev.md L37/L60 — outside this PR's surface; drift between two governed texts, carrier named in the report. Escalated to the seat as a note, not a finding here. PR has no assignees, as os-dev.md and the order say.
  4. 「One line each」 taken as two lines (item 1) and three (item 3) — accepted: the card's acceptance is 「each states its rule once」, which holds; both files sit at their ceilings (60/60, 102/102 measured; changed lines 96–119 B; the one 122 B line, contract-review L22, is pre-existing on main).
  5. Item 2 on L60 not L75 — confirmed (see ①); L75 governs the stale-premise re-check, state-machine.md L40 governs pm:retriage answering.
  6. 24-hour clause in contract-review.md — right: the card places all of item 3 there, and the recogniser's self-test-reads declaration (dispatch-gates census) may read only project-forms.md and contract-review.md.
  7. Recogniser consumers — confirmed by git grep on the head: one consumer, check-owed-reviews.mjs.
  8. No package build/test owed — right.
  9. Hypothesis 3 — informational.
    Author: PR user.login is objectstack-fleet[bot]; no relay note owed. Conflict of interest: the card was filed by the triage seat and this PR changes triage's rules; the review was rendered by an isolated subagent that did not draft the card, fed the card, PR and check-runs only.

④ Design judgment

.claude/skills/pm-dispatch/references/triage-duties.md — held against card #27370 items 1–2, ruling #27047 items 5–6, landing-operations.md 约定①–③ and SKILL.md L86.

  • Item 1 (L26–27) holds against the scenario on the card: a 10-hour stop followed by a round that reads only the newest run now reads the whole window, files the anchor even when main is green again, and writes the gap. No gate reads these lines; none is claimed.
  • Should-fix 1 — L27 is broader than the rule beside it. 「窗内无锚红当轮立 p0 锚卡」 anchors any unanchored red in the window p0, queue reds included, while L29 (「flake 锚卡判确定性才升」) and pm-dispatch(p0): a lane's p0 card is dispatched at once — no batch, depth-wait or concurrency cap holds it, and lower-priority dev work pauses to make room; main or merge-queue red is graded p0 at first touch #27047 item 5 (a queue-flake-anchor becomes p0 only when triage reads the red as deterministic) grade a flaky queue red lower at first touch. The card's own words (「Any red in that window that has no anchor gets a p0 anchor now」) license L27, and the measured misses were main push reds, so this is not a must-fix; but the two lines now disagree inside one file and L27 is the one that hands triage the wider grading power. Bound L27 to 「主干红与确定性队列红」 or to 「照 L29 定级」 in the same bytes.
  • Should-fix 2 — the deleted scope sentence has no home. Old L3 「本文是分诊座位的全部职责」 was the file's only bound on what triage does; SKILL.md L86 restates who reads the file and when, not that the list is exhaustive. The dev's reason (duties also live in contract-review.md, state-machine.md L40, landing-operations 约定③) is true of main, but the cure for an over-claim is a narrower bound, not none: a seat whose remit the maintainer limited (「你只处理分诊」, amended once by pm-dispatch(p0): a lane's p0 card is dispatched at once — no batch, depth-wait or concurrency cap holds it, and lower-priority dev work pauses to make room; main or merge-queue red is graded p0 at first touch #27047 item 6) loses the one line that said so. Fold a pointer into L1 or L15, or into SKILL.md L86's row.
  • Item 2 (L60) holds: pm:epic cards carrying pm:retriage are answered 「即答」, parents still never dispatched; the dropped cloud clause is restated where triage reads before routing (SKILL.md L85 → cross-repo-coordination.md L44). L61–62 still define 「涉 cloud」 for that rule, which now lives one file over — acceptable, noted.

.claude/skills/pm-dispatch/references/contract-review.md — held against card item 3, ruling #27062 items 2–4, and the reader that implements it (contractReviewHold, owedReviewRow).

  • The template on L29 is the card's shape, and the reader pins it verbatim in this file with the 24-hour constant (self-test, readFileSync of this path). Four facts split on the doorbell separator; the session uses the claim reader's one regex; the head is 7–40 hex matched by prefix either way; the template copied unedited is unreadable; newest governs through latestMarkedComment as the hand-off line does; age from created_at, 24 h reads overdue: true and still live; no stamp reads overdue: null and is listed, never dropped. The reader does what L30–31 say.
  • Against the card's scenario (feat(spec): currencyMode: 'record' + currencyField — a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1) #27268: a lane says in prose 「head will move」, triage claims under (b), withdraws): a lane now posts one line; check-owed-reviews prints hold live … holds (b) waited N min and keeps the row WAIT; (b) cannot fire. Holds.
  • Should-fix 3 — an unreadable newest line voids a readable live hold, and the failure runs in triage's favour. contractReviewHold resolves by latestMarkedComment; if the newest comment matching the key is unreadable, the whole reading is unreadable and 「holds nothing」, so (b) fires even when an older comment carries a readable hold on the current head. keyLineRegex matches a backticked or bulleted key at line start, so a later seat note, round record or review that quotes the template line (as records of this very rule will) is exactly such a comment. contractReviewClaims takes the opposite convention (skips unreadable rows, honours every readable claim), and the hand-off reader's same convention fails conservatively (an unreadable newest hand-off means triage does not take). Here the same convention fails toward triage taking. Read the newest readable hold on the current head, or let an unreadable newest line keep (b) suppressed and print the gap; the rule text L30 is consistent with either.
  • Should-fix 4 — trigger (c) overrides a live hold, and the rule text does not say so. The card and L30 name (b) only; the script header and its pins assert 「(a) and (c) still fire」. (c) is 「lane seat stood down or absent」, which every lane meets nightly at 收班. A hold posted 「until the last sibling merges」 before the lane's shift ends is taken by triage at the next round — the churn the card filed to end, now without the lane's objection on record. Either L30 states that (a) and (c) still fire (so a lane knows its hold does not outlive its seat), or the reader lets a live hold suppress (c) as well while its age is under 24 h. Not a must-fix: the card's text names (b) alone and the implementation follows it; the maintainer's call.
  • L33, L49, L60 (in-place and fold edits) hold against their restatements (①). No must-fix.

Both files stay at their ceilings; check:pm-skill-ratchet and check:pm-record-recognisers ran green on the head inside Lint · PM dispatch-gates; no line exceeds 120 B that did not already on main.

Implemented-by: claude/issue-27370-triage-reads-the-gap-and-hold-line
Reviewed-by: session_01AavokzJ5DndAwitDXvKy4U

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg

Seat decision on triage's record 6491338629 (PASS on 167b0027, four should-fix) · 2026-10-29T08:06Z

  • Should-fix 1 (L27 bound to L29's grading), 2 (a home for the dropped scope bound), 3 (an unreadable newest hold line must not void a readable live hold on the current head): ride this PR in one rework commit. They are in this PR's files and are small, and the filing gate does not let the seat file a pm-rule card on its own (filing-gate.md L13), so a follow-up card is not the alternative. Rework dev on opus (the ceiling tier is still exhausted); the new head returns to triage for a delta review by the same reviewer (contract-review.md: 「只落发现的 commit 由同一复核者 delta 复核」).
  • Should-fix 4 (whether trigger (c) also yields to a live hold): not built here. The card names (b) alone and the implementation follows it; the reviewer calls it the maintainer's call. The seat puts it to the maintainer in its ACCEPT's 「需要你做的」 line with the two options the record names (state in L30 that (a) and (c) still fire, or let a live hold under 24 h suppress (c) too).
  • No ACCEPT and no landing on 167b0027; the seat's ACCEPT follows the delta PASS on the rework head.

…ng, restore triage's scope bound, and read a hold per head so an unreadable line voids nothing

triage-duties.md: the window line files an anchor for every unanchored red
and grades it as first touch does (main full red and a deterministic queue
red p0, a flake anchor raised only once read as deterministic), so it no
longer grades wider than the line two below. A first line restores a true
scope bound: this file plus the clauses elsewhere in the skill that name
triage (review, answering pm:retriage, convention 3) are the seat's whole
remit. Paid by folding the decision-batching line, whose home is the
director charter's ruling duty (batches of at most five, one reply per
batch) under SKILL.md's one presenting seat.

record-recognisers.mjs: contractReviewHold reads per head. The newest
readable hold naming the current head is live whatever is posted after it;
a newer hold naming an earlier head or a line that cannot be read voids
nothing; every unreadable hold line is returned by comment id on every
reading; only unreadable lines read unreadable and hold nothing.
Self-test: hold battery 19 -> 23 cases.

check-owed-reviews.mjs: the row carries the unreadable hold lines and
prints them beside a live or stale hold. Self-test: hold battery 13 -> 14.

Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429 rate_limit: the account's ceiling-tier quota is still exhausted, 2026-10-29T08:51Z) · head 168cb1e

Delta review owed on the rework commit 168cb1e8 (one commit on 167b0027: triage-duties.md +2/−2, check-owed-reviews.mjs +29/−11, record-recognisers.mjs +67/−30), by the same reviewer as record 6491338629 (contract-review.md: 「只落发现的 commit 由同一复核者 delta 复核」). Scope = should-fix 1, 2, 3 of that record, as the seat's decision 6491385759 ruled; should-fix 4 is not built (the maintainer's call). The dev report is 6492235178 on #27370. Check-runs on the new head: 41 complete, 25 success, 16 skipped, 0 failed. needs:contract-review re-hangs in the same stroke. After a delta PASS the seat writes its ACCEPT and lands it (Tier S).

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

Contract-review-claim: session_01AavokzJ5DndAwitDXvKy4U · head 168cb1e8f651edbb16204f9945c0b53c9603151d · 2026-10-29T09:39Z

Triage seat. This is a delta re-review from triage's PASS on 167b0027, against its four should-fixes. The PR changes triage's own rules, so the reviewer again gives triage no latitude. The review runs at CONTRACT_REVIEW_TIER. If the lane claims or posts a record on this head first, triage withdraws.


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 168cb1e8f651edbb16204f9945c0b53c9603151d
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/contract-review.md, .claude/skills/pm-dispatch/references/triage-duties.md + scripts/pm/check-owed-reviews.mjs, scripts/pm/record-recognisers.mjs, scripts/pm/check-half-states.mjs (latestMarkedComment, markerMatches), scripts/pm/check-governed-merges.mjs (GOVERNED_SURFACES), scripts/pm/check-skill-line-ratchet.mjs (ceilings 60 / 102), .claude/skills/pm-dispatch/SKILL.md (L69, L85–86, L164–165, L276), references/lanes/director.md (L21, L28, L48, L56), references/lanes/triage.md (L1–8), references/state-machine.md (L40), references/cross-repo-coordination.md (L44), references/filing-gate.md (L16, L28), references/landing-operations.md (L76–84), references/dispatch-runbook.md (L8), .github/workflows/lint.yml (L1038, L1274), package.json (check:pm-record-recognisers, check:pm-skill-ratchet)

Delta re-review by the reviewer of record 6491338629 (PASS on 167b0027, four should-fix), per 「只落发现的 commit 由同一复核者 delta 复核」. One commit on top of 167b0027: 168cb1e8 (triage-duties.md +2/−2, check-owed-reviews.mjs +29/−11, record-recognisers.mjs +67/−30; contract-review.md untouched). The new net diff is the old one plus exactly this commit (git diff --stat 167b0027 168cb1e8 matches; the four paths are unchanged). Inputs read: the seat's decision 6491385759 (should-fix 1–3 ride this PR; 4 goes to the maintainer), the dev's second os-dev-report 6492235178 on the card, the hand-off 6492252146 and claim 6493235088 on this head; 46 check-runs on 168cb1e8, all completed, none pending: 25 success (Test Core and both shards, every Lint job — the ratchet and the two self-tests run inside them — every Type Check job, Governed Surface Queue Guard, PR-body guards, Check PR Size), 21 skipped by path filter (Check Changeset among them on this head; the skip-changeset label is unchanged and it read success on 167b0027), 0 failures. Files read with git show prr-27468: and origin/main:; nothing built, run or checked out. The hold and hand-off rules this PR writes were read as text under review, not as rules in force.

① Derived judgments

  • Accept set / public surface: unchanged by the delta — no packages/** path; nothing published. Right.
  • scripts/pm/record-recognisers.mjs: contractReviewHold is rewritten per head; its signature and every export are unchanged; readContractReviewHold is untouched; the hold battery grows 19 → 23 with the floor at 17; the self-test-reads declaration stays on L77. Right — still off the governed register; one consumer (check-owed-reviews.mjs).
  • scripts/pm/check-owed-reviews.mjs: the row's hold gains unreadable (array of comment id, stamp, quoted line); holdText prints ⚠️ N unreadable hold line(s) (ids) beside a live or stale reading; listed, the trigger logic and the four-status vocabulary are unchanged; CONTRACT_REVIEW_HOLD_TEMPLATE is imported for the self-test fixture only. Right — additive, --json has no in-repo consumer.
  • Gate surface: unchanged — the live reader is in no workflow; both self-tests run under the existing check:pm-record-recognisers. Right.
  • Governed text (triage-duties.md, 102/102, no line over 120 B): new L3 bounds the seat to 「本文与技能他处点名分诊之条…即分诊座位的全部职责」 (right, see ④); L28 (was L27) 「窗内无锚红当轮立锚卡、照首触定级,转绿照立并点名承修卡;逾 90 分钟无记录记明断档」 (right: every unanchored window red still gets its anchor, the grade is L30's, the green-again and 90-minute clauses survive); old L99 「需裁事项攒批(≤5 项/批,每项一行带推荐),一句同意即全链执行」 deleted (right, homed — see ③/④). Every other line of both files is as reviewed on 167b0027; contract-review.md is byte-identical to that head.
  • Fold home of old L99, checked on origin/main: SKILL.md L276 (「总监席是唯一呈裁席:决策箱只经本席呈维护者人工裁」) makes presenting the director's; director.md L48 carries the ≤5-per-batch cap and 「每张皆呈」, L56 one batch per reply (「一字即可」), L21 the recommendation; this file's L99 keeps 「方向性授权覆盖整条执行链一并做完」; SKILL.md L69 defines the batch unit. Present. Triage's own list stays a report section (L97 「轮次报告设呈裁清单专节(卡、推荐、所引权威)」), so a presenting cap leaving the triage file grants triage nothing.

② Semver level

Unchanged: no package touched, skip-changeset present, Clause-②: no, Metadata-protocol: none. Check Changeset is skipped on this head by path filter, not failed. Matches.

③ Boundary flags

open_questions: none. The seven deviations of report 6492235178, each answered:

  1. Should-fix 1 spelling — neither of my two spellings verbatim: 「主干红与确定性队列红」 measured over 120 B, and 「照 L29 定级」 would be positional and wrong after the new L3 moved L29 to L30. 「照首触定级」 names L30 by content. Accepted; better than either of mine.
  2. Should-fix 2 premise — the enumerated 「this file + three homes」 form is false on main (dispatch-runbook.md L8, cross-repo-coordination.md, filing-gate.md L28, lanes/triage.md and others also assign triage duties; 分诊 appears in 24 files of the skill). The bound is written closed-world instead. Accepted; measured true.
  3. Fold choice — old L99 was the one candidate whose whole content has a named home. Confirmed (see ①).
  4. No ablation for should-fix 3 — os-dev.md forbids ablating a script; the control leg is in-case (same thread without the quoted template reads the same hold) and the dev's read-only base-vs-branch probe (a git archive into its scratchpad) shows the base reading unreadable on fixture (i). Accepted.
  5. Commit trailer: model-free Co-authored-by: Claude + Claude-Session per AGENTS.md L443 instead of the harness's model-named line. Informational.
  6. post-stamped.mjs echoes the proxy variable's value to stderr — the tool's own behaviour, outside this surface. Noted.
  7. check:doc-formula-expressions needed a prerequisite build, then exit 0; recorded in --ran. Accepted.
    pr_body_stale_sentences (12 listed by the dev, PR body not re-PATCHed): the 维护者速读 still says 「窗内无锚的红当轮立 p0 锚卡」 and 「hold 写错格式读作 unreadable、什么都不挡」, the line numbers, test counts and the Tests/Verification sections describe 167b0027, and the new L3 and the old-L99 fold are absent. Should-fix (non-governed): the seat or dev refreshes the body before landing; the tree, not the body, was judged here.
    out_of_scope_findings: lanes/triage.md L7 「每 fire 最旧优先」 vs triage-duties.md L24 「队列每轮清空时最新优先」 — a conflict between two triage texts, now both inside the remit L3 defines. Outside this diff; for the seat's ACCEPT notes.
    Author: objectstack-fleet[bot]; no relay note owed. Conflict of interest unchanged: the card is triage's, the rules are triage's; the record is an isolated subagent's.

④ Design judgment

Should-fix 1 — resolved exactly. L28 no longer grades wider than L30: a main full red or deterministic queue red is p0 at first touch, a flake anchor is filed in the round and raised only once read as deterministic, as #27047 item 5 ruled. The card's measured misses (two main push reds) still land p0 through L30. 「main 已转绿」 → 「转绿」 and 「则」 dropped to fit 119 B; the subject is the window red, unambiguous.

Should-fix 2 — resolved exactly. L3 restores a true bound: the seat's whole remit is this file plus every clause of the skill that names triage — so the charter's own ⛔ (lanes/triage.md L4: 「只写标签与审计评论,⛔ 无 PR、无认领」) and #27047's one-case amendment are inside it, and nothing unwritten is. Tighter than no bound, truer than the deleted 「本文是…全部职责」. The payment (old L99) is a presenting rule for a seat that does not present; L102's 「攒批」 now reads the director's batch, which is where the cap lives.

Should-fix 3 — resolved exactly, on my first option. contractReviewHold now classifies every row (read / unread), takes onHead = readable holds whose head meets the current head by prefix, and reads live off the newest of them whatever is posted after; stale only when readable holds exist and none names the current head; unreadable only when every hold line is unreadable; absent when none. Every reading carries unreadable[] and the row prints it. Tried to break it: (i) readable hold then a later comment quoting the template at a line start (a round record, a seat note, this very record) → live, WAIT, (b) held, the quote named by id — pinned with an in-case control; (ii) a later readable hold naming an earlier head no longer clears a hold on the current head — pinned both orders; (iii) only unreadable lines → unreadable, (b) fires, every line named — unchanged from 167b0027, and the dev's reason for keeping it (the other option lets any template quote suppress (b) on a PR no lane holds, failing toward nobody reviewing, and adds a second convention beside contractReviewClaims) holds; (iv) newestOf's fallback to the last entry only applies when latestMarkedComment finds no marker, and markerMatches already retries with CR stripped, so the fallback cannot change liveness, only which same-head hold's reason and age are printed; (v) no stamp → overdue: null, listed, unchanged. Nothing in the delta fails toward triage taking a review: every behavioural change moves a reading from (b)-fires to (b)-held or leaves it as it was.

Should-fix 4 — not built, by the seat's ruling; not counted. One line for the maintainer: the governed text still names (b) alone (contract-review.md L30 「点名现 head 时 (b) 不起」) and does not say that (a) and (c) still fire under a live hold; that sentence exists only in the script header and the self-test names, so the seat's ACCEPT must quote it when it puts the two options to the maintainer.

No must-fix. Both files stay at their ceilings; the ratchet and both self-tests ran green on this head inside the Lint jobs.

Implemented-by: claude/issue-27370-triage-reads-the-gap-and-hold-line
Reviewed-by: session_01AavokzJ5DndAwitDXvKy4U

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg

维护者速读

  • 改了什么:分诊每轮改读「上份轮次记录 fire 以来」全部 main push、schedule 与合并队列结论,窗内无锚的红当轮立锚卡、按首触定级(主干全量红与确定性队列红 p0,flake 判确定性才升),断档逾 90 分钟写明;pm:epic 卡上的 pm:retriage 即答;triage-duties.md 新 L3 写回分诊的职责边界;车道可落一行 Contract-review-hold: 暂缓本 head 送审,check-owed-reviews.mjs 按 head 读它:活 hold 只挡 (b)、新 head 即清、读不懂的行不挡也不废有效 hold 并以 ⚠️ 列出、逾 24 小时列进分诊轮次记录。
  • 为什么改:10-28 分诊停了约 10 小时,回来第一轮只读最新一跑,两次 main 红没有锚卡;一张 epic 上问分诊的三个问题等了约 10 小时;车道用散文说「这个 head 先别审」,分诊照 (b) 认领后又撤回 —— 您的「立卡」(pm-dispatch(triage): each round reads every main and queue red since the last round record, answers pm:retriage on pm:epic cards too, and a lane can hold a head with a Contract-review-hold: line #27370)。
  • 风险与回滚:只改两份技能文本(行数不变:60/60、102/102)与两个只报不拦的脚本;无新门禁、check-run、workflow 步骤或半状态行。回滚 = revert 本 PR。
  • 先看:scripts/pm/record-recognisers.mjs 的 contractReviewHold(按 head 读);references/triage-duties.md L3、L27–28、L61;references/contract-review.md L29–31。
  • 两分钟验证:node scripts/pm/record-recognisers.mjs --self-test && node scripts/pm/check-owed-reviews.mjs --self-test → 320 cases pass 与 63 cases pass in 9 batteries。
  • 需要你做的:落地无需你动手(Tier S)。一项待裁(复核 should-fix 4,本 PR 未建):今天的规则文本只写「点名现 head 时 (b) 不起」,而脚本让 (a) 与 (c) 照常触发 —— (c) 是车道席已收班,每个车道每晚都会收班,所以车道挂的 hold 活不过它的班次。A:在 contract-review.md L30 写明 (a)(c) 照触发(车道知道 hold 不过夜);B:让未满 24 小时的活 hold 也挡 (c)。回一个字母即可;席位推荐 A(不扩散、与当前实现一致,只补一句文本)。
  • 席位意见:ACCEPT。分诊复核 PASS(6491338629,167b0027)提 4 条 should-fix,1–3 随本 PR 返工,同一复核者 delta PASS(6493363887,168cb1e8),无 must-fix。

席位核对

  1. 形态:4 个文件 +327/−23(350 ≤ 3000);commit 0c9c1c53、167b0027、返工 168cb1e8;draft,作者 objectstack-fleet[bot](经中继),assignees []、requested_reviewers [];正文已由席位经中继 issue_patch 刷新到 168cb1e8(回读一致,20185 B)。
  2. 前提实测:卡上三处漏项属实(10-28 两次 main 红、connectors: auto-shelf readiness — declarative include and a loud Swagger 2.0 refusal for connector-openapi; tools/list pagination, fatal 401 and a tool-snapshot hash for connector-mcp; an offline spec-normalization tool #26709 的 pm:retriage 等约 10 小时、feat(spec): currencyMode: 'record' + currencyField — a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1) #27268 的散文暂缓);「父单是协调节点」在 main 上 0 命中,item 2 落 L61(「父单永不派发」旁);contractReviewHandoff / contractReviewClaims 唯一外部消费者是 check-owed-reviews.mjs。
  3. 门禁 check-runs(head 168cb1e):53 个全部完成,26 success、27 skipped、0 失败(PR-body guards 因正文刷新重跑后亦绿);check-expected-skips.mjs --pr 27468(roster 取自 origin/main)→ exit 0,每个 skip 皆在名册。
  4. 接受的偏差:item 1 占两行、item 3 占三行(每条规则只写一次,行数天花板不动);未做消融(os-dev.md 禁止消融脚本,复审钉案自带对照腿,dev 另以只读探针对比 base 与 branch);should-fix 1 的写法是「照首触定级」(复核两种写法一个超 120 B、一个按行号会在新 L3 后错位);should-fix 2 的边界写成闭世界形式(枚举「本文 + 三处」实测为假)。
  5. 范围外去向 + Skills-docs::lanes/triage.md L7「每 fire 最旧优先」与 triage-duties.md L24「队列每轮清空时最新优先」在队列每轮清空时相冲 —— pm 规则文本间漂移,不属立卡三类、席位不自立(filing-gate.md L13),记于此处与 PR 正文 Acceptance notes;AGENTS.md 〈Multi-agent working discipline〉「PR assignee mirrors the card」与 os-dev.md L37 相反 —— Tier H,您的手。Skills-docs: none(Metadata-protocol: none)。
  6. 落地条款:Tier S(check-governed-merges --pr 27468:.claude/** ×2 全在 Tier S 面,scripts/pm/** ×2 不在登记册);同形达档复核在案:6491338629(全量)+ 6493363887(delta PASS,钉现 head);Clause-②: no、Metadata-protocol: none 行首在 PR 正文;skip-changeset 正确。落地笔 = pr_ready + automerge_enable,授权原话「你应该按照 pm-dispatch 技能审核并落地pr」;分诊认领里「维护者批准仍为闸门」一句与 Tier S 规则不符,按 SKILL.md 〈路径分叉〉 Tier S 由席位落地。

ACCEPT · head 168cb1e8f651edbb16204f9945c0b53c9603151d · 2026-10-29T09:48Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant