Repository navigation
pm-dispatch(review): a PR reaches a human only after the seat's ACCEPT and a same-head contract PASS: no seat assignee at the draft open, the approver request is the seat's hand-off, a PR landed owing a review is re-reviewed with findings filed as cards - #27385
Conversation
…d PASS, and a PR landed owing one is re-reviewed SKILL.md 〈路径分叉〉 ③: the approver request is the seat's hand-off, made once its ACCEPT and a contract PASS on the current head are both on the thread; `pr_create`/`pr_ready` request and assign nobody; the 「需要你做的」 line names the PASS comment id and `Head-sha`, or says "contract review owed" and does not ask. contract-review.md: the same-head PASS gates the ask as it gates landing (L49), and a PR that landed still owing a review is re-reviewed on its landed head with every must-fix filed as a new card (two lines, paid by folding the `Local-runs:` and `--brief-template` pairs). landing-operations.md L12 points at ③ for Tier H and carries the post-landing pointer (paid by its restated L54). director.md L57 adds the same-head PASS to the pre-approval check. Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg Co-authored-by: Claude <noreply@anthropic.com>
…governed follow-up leaves pr_create os-dev.md L37/L60: a dev's `pr_create` carries no `assignees`; a human sees the PR at the seat's hand-off. execution-duties.md L63: the in-flight-PR reader is `head:claude/` plus the card the body names, no PR assignee. dispatch-runbook.md 〈卡线程〉: a project thread does not perform the harness's post-create assign/request-review step (paid by the coordinator.md restatement it carried). ops.mjs: `governedReview` leaves `pr_create` — the draft open summons nobody; `pr_ready` keeps the follow-up as the backstop and the seat's hand-off is `pr_request_reviewers` / `assign`. execute.mjs / validate.mjs self-tests pin the derived op list as `pr_ready` alone and that a create reads no file list and sends no request or assignee (execute 208 → 209 cases). Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg Co-authored-by: Claude <noreply@anthropic.com>
… ACCEPT and a same-head PASS on the thread check-half-states.mjs H43 reads the PR's own comment thread (H48's fetch class, cached for H48/H69) before judging "asked neither approver": a Tier H PR before the seat's `## 席位核对` ACCEPT and a `## Contract review` PASS naming its current head is NOT a half state and buys no review page; after both, with no approver request, it is. `h43HandoffReading` reuses seat-record.mjs and `latestContractReviewOnHead`, the latter widened with the verdict word (`contractReviewVerdictOf`, the one reader of it — a FAIL on the head owes a patch round, not a request). H69's prose stops saying the relay summons at `pr_create`. Summary clause and count keys carry the thread/due readings; self-test 5034 → 5066 cases, new battery `H43 hand-off timing`. Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg Co-authored-by: Claude <noreply@anthropic.com>
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg Contract-review-claim: session_01QSeKYmhU5KEj1nukYhp1Tg · head 50118ff · 2026-10-29T04:47Z |
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg Contract reviewServed-tier: Claim line 6488220465 on this head (2026-10-29T04:54Z); no earlier record on it. Read at 2026-10-29T04:54Z by the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: FAIL — one must-fix (SKILL.md L200 vs ops.mjs |
…is the hand-off's backstop The seat's contract review on 50118ff found the one governed sentence that contradicted the mechanism it describes: SKILL.md L200 said `pr_create`/`pr_ready` request and assign nobody, while ops.mjs keeps `governedReview: true` on `pr_ready` (`GOVERNED_REVIEW_OPS` derives to `['pr_ready']`) and execute.mjs pins that a Tier H `pr_ready` requests every uncovered approver and assigns an approver-author. Ruled text follows code: L200 now says `pr_create` requests and assigns nobody, `pr_ready` fills only what the seat's hand-off left uncovered (zero writes once the hand-off was made), a head that moves after the PASS goes back to waiting for review, and an off-relay PR has its requested reviewers and assignees read by the seat. One line rewritten in place (119 → 118 B), 319 lines kept, no clause moved; L198, L199 and L201 are byte-identical. No script changed. Claude-Session: https://claude.ai/code/session_01QSeKYmhU5KEj1nukYhp1Tg Co-authored-by: Claude <noreply@anthropic.com>
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg Contract-review-claim: session_01QSeKYmhU5KEj1nukYhp1Tg · head 3e2b20c · 2026-10-29T05:42Z |
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg Contract reviewServed-tier: Claim line 6489001909 on this head (2026-10-29T05:44Z); the earlier record 6488313163 stands for the other ten files. Read at 2026-10-29T05:44Z by the ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS — delta on 6488313163's must-fix; the full record for the other ten files is 6488313163. |
|
domain:skills#2 · os-justin · session_01QSeKYmhU5KEj1nukYhp1Tg 维护者速读
席位核对
ACCEPT · head |
Fixes #27345
Fixes #27363
Clause-②: no
Metadata-protocol: none
维护者速读
pr_request_reviewers;作者是审批人时assign),dev 开 draft PR 不再带assignees,中继pr_create不再在开 PR 那一刻请审;落地时仍欠复核的 PR 在落地 head 上复审,发现逐条立新卡;巡查 H43 只在交棒已到期而无人被请时才报。pr_create的governedReview)与一条只报不拦的巡查行;不新增门禁、不碰 workflow。回滚 = revert 本 PR 的三个 commit;中继pr_ready仍保留受管请审兜底(Tier H 的 ready 本就在批准之后),Tier H 的批准与合并仍是您的点击。scripts/pm/fleet-write/ops.mjs的pr_create行(governedReview: true移除)与头部「The governed-review follow-up」节;②.claude/skills/pm-dispatch/SKILL.mdL198–201(规则唯一一份);③scripts/pm/check-half-states.mjs的h43HandoffReading与h43GovernedReviewRequestGap(新的handoff门;unread 不判、before 不报、due 才报)。node scripts/pm/fleet-write/execute.mjs --self-test && node scripts/pm/check-half-states.mjs --self-test,预期尾行209 cases pass across 20 batteries与5066 cases pass … H43 hand-off timing 89/80;本 PR 自身就是首个样本:draft 开出时assignees与requested_reviewers皆空(见 Verification 的回读)。.claude/**+scripts/pm/**,Tier S:席位跑契约复审,PASS 后 ready → 入队)。What changes
The two cards are one rule at two points, so the rule is written once — SKILL.md 〈路径分叉〉 ③ — and the other files point at it: a PR reaches a human only when development is done AND the seat's ACCEPT (
## 席位核对) AND, where clause ② applies (every governed path is the review'srulesface, so on every governed PR), a## Contract reviewPASS on the CURRENT head are on the PR; then, and only for Tier H, the seat requests review fromGOVERNED_APPROVERS(os-zhuang,hotlong). The seat's own account is never assigned to or requested on a PR; a Tier S PR goes to no human; a head that moves after the PASS goes back to waiting.Card 27345 — the same-head PASS gates the ask, and a PR that landed owing a review is re-reviewed
.claude/skills/pm-dispatch/SKILL.md〈路径分叉〉 L198–201, rewritten in place (four lines, same count): ③ the request IS the seat's hand-off after ACCEPT + same-head PASS, throughpr_request_reviewers; the author-is-approver fallback stays (assignthe author, request the others; never the seat's own account; Tier S hands off to nobody);pr_create/pr_readyrequest and assign nobody, a head that moves after the PASS goes back to waiting, an off-relay PR has the seat read its reviewers and assignees itself; the 速读 「需要你做的」 line that asks for approval names the PASS comment id and itsHead-sha, and with no PASS says "contract review owed" and does not ask.references/contract-review.mdL47 (was L49): the two pre-landing checks now gate the request and the ask as well — ① a same-head, same-shape, at-tier PASS on the current head. New L52–53 (item 2): a PR that lands while still owing a review is re-reviewed on its landed head by the lane seat or by triage under the gap rule (a)(b)(c); a FAIL is not repaired on the closed PR — each must-fix is filed as a NEW card citing the record, graded on its own; a revert only for a main red (p0, main-red 约定①) or a security boundary. Paid by folding the two wrapped pairs L34–35 (Local-runs:) and L43–44 (--brief-template) into one line each — every clause kept; the script path is spelled in full on L33 already.references/landing-operations.mdL12: PASS ⇒ Tier S ready + auto-merge, Tier H hands off per SKILL.md ③; L13 points at the post-landing rule. Paid by deleting old L54, whose content (a contract-review-PASS PR arrives at the landing window already ready and armed) is L12's own statement.references/lanes/director.mdL57: five checks in order before a governed PR waits for a human — seat record, 速读, same-head PASS,pr_request_reviewers, green head.Card 27363 — no seat assignee at the draft open; the approver request is the seat's hand-off
.claude/agents/os-dev.mdL37/L60: a dev'spr_createcarries noassignees(labels only —skip-changesetstill rides the create); a human sees the PR at the seat's hand-off.references/execution-duties.mdL63: 「PR assignee = 卡的」 and the takeover swap are gone; the in-flight-PR reader ishead:claude/open PRs plus the card their body names (Fixes/Part of) — no PR assignee anywhere in it. The card's assignee and theClaim:Branch:still own the work.references/dispatch-runbook.md〈卡线程〉 L140 (item 4): a project thread does not perform the harness's post-create assign / request-review step; the request is the seat's hand-off — citing 「审核通过才会推送给我审核」. Paid by deleting old L136, whose three clauses (p1 first; the project-wide cap is the maintainer's; queue when full) arecoordinator.md三 L23–L25 verbatim, which the deleted line itself pointed at.scripts/pm/fleet-write/ops.mjs:governedReview: trueleaves thepr_createrow — the draft open summons nobody;GOVERNED_REVIEW_OPSderives to['pr_ready']. Theassigneesleg stays optional on the row for the author-is-approver fallback and other callers; a dev simply stops sending it. Hypothesis 1 measured: the relay already haspr_request_reviewers(ops.mjs L1050:pullrequired,reviewers/team_reviewerswithatLeastOne), so the hand-off is ONE seat stroke after ACCEPT + PASS;pr_readykeeps its follow-up as a backstop — a Tier H pull is readied only after an approver approved it, so there it costs zero writes when the hand-off was made and names the one approver still uncovered when it was not. Header sections rewritten accordingly (the maintainer's words quoted once).scripts/pm/fleet-write/execute.mjs/validate.mjs: headers and self-tests pin the derived op list aspr_readyalone and that apr_createon a Tier H diff reads no file list, re-reads no pull or reviews, sends no request and no assignee (an approver-authored pull included), and that a create answering no number owes no follow-up (the stroke no longer fails on its account). The governed battery's create-side runs becamepr_readyruns; three create NEGATIVE pins replace them (pin 29 → 30).scripts/pm/check-half-states.mjsH43 (item 5): before judging 「asked neither approver」 the row reads the PR's own issue-comment thread — H48's fetch class, cached so H48/H69 pay nothing — for the seat's ACCEPT (SEAT_RECORD_MARKER+seatRecordAccepts, seat-record.mjs) and a## Contract reviewnaming the current head whose verdict word is PASS (latestContractReviewOnHead, widened withverdict;contractReviewVerdictOfis the one reader of the word, three measured dialects). Three states: unread ⇒ UNJUDGED (quiet, disclosed), before ⇒ not a half state (quiet), due ⇒ the existing coverage judgment. Only DUE buys the submitted-review page. Summary clause and two count keys (governedHandoffRead,governedHandoffDue) disclose the reading; drafts still neither fire nor silence it. Bound stated in the header: the PR thread is the one thread read — a PASS on the card alone reads as BEFORE (under-report only); the ACCEPT's freshness against the head stays H69's question. H69's header and sentence stopped saying 「the relay summons atpr_create」 (made false by this PR; its self-test pin moved with it).check-handover.mjs(a) reads CARD assignees and puts pull requests out of its population (its self-test pins it);check-half-states.mjsreads a PR'sassigneesonly as H43's approver-coverage fallback, kept on purpose (the fallback assigns an approver, never a seat).project-forms.mdL31–32: the ledger is labels + the card's assignee +Claim:+head:claude/PRs — already assignee-free on the PR side, no edit.locateReviewOfRecorditself is not called: it requires BOTH threads (PR and card) or answersunreadable, and reads no verdict word; H43 reuses its building blocks (latestContractReviewOnHead, the one head-sha recogniserrecord-recognisers.mjsimports) and adds the verdict word beside them.Regen-provenancepair (contract-review L50–51) does not compress under 120 B; theLocal-runs:and--brief-templatepairs do, so they paid; landing-operations L7–8 kept, old L54 paid instead.Line budget — every
.claudefile at its ceiling (headroom 0, prose ≤120 B).claude/skills/pm-dispatch/SKILL.md — 319 → 319 lines
- ③ 中继 ˋpr_createˋ/ˋpr_readyˋ 命中 Tier H 即向 ˋGOVERNED_APPROVERSˋ 中未请/派/审者请审。- 作者是审批人 ⇒ 指派它、请其余(请它必 422),否则请全员;速读只点非作者审批人去批。- 脱中继开的 PR 无 run 行:交速读前席位恒自读 ˋrequested_reviewersˋ/ˋassigneesˋ,⛔ 不只看 run 行。- 缺口经中继 ˋpr_request_reviewersˋ/ˋassignˋ 补,⛔ 不碰 draft 位;ACCEPT 与轮报点名脱中继作者。- ③ 请审 = 席位交棒:ACCEPT 与现 head 同形 PASS 俱在案后,中继 ˋpr_request_reviewersˋ 请审批人。- 作者是审批人 ⇒ ˋassignˋ 它、请其余(请它必 422);⛔ 永不派/请席位自身账号;Tier S 不交人。- ˋpr_createˋ/ˋpr_readyˋ 不请审不指派;PASS 后 head 移 ⇒ 回等复核;脱中继 PR 自读请审人与指派。- 速读「需要你做的」求批点名 PASS 评论 id+ˋHead-shaˋ;无 PASS ⇒ 写 contract review owed 不求批。.claude/agents/os-dev.md — 402 → 402 lines
- 恒不写卡的 assignee(空也开工,报 ˋsummaryˋ);PR assignee = 卡的:ˋpr_createˋ 带 ˋassignees: [LOGIN]ˋ。- 恒不写卡的 assignee(空也开工,报 ˋsummaryˋ);PR ⛔ 不带 ˋassigneesˋ,人经席位交棒才见 PR。- 写预算三笔:ˋgit pushˋ、ˋpr_createˋ(draft,含 assignee 与 labels)、ˋos-dev-reportˋ 评论。- 写预算三笔:ˋgit pushˋ、ˋpr_createˋ(draft,含 labels、⛔ 无 assignees)、ˋos-dev-reportˋ 评论。.claude/skills/pm-dispatch/references/execution-duties.md — 188 → 188 lines
- 卡 assignee 归 PM,dev 恒不写;PR assignee = 卡的,接管 ② 同笔换;读者 ˋis:pr is:open assignee:LOGINˋ。- 卡 assignee 归 PM,dev 恒不写;PR ⛔ 不派席位账号;在飞 PR 读 ˋhead:claude/ˋ 开 PR 正文点名的卡。.claude/skills/pm-dispatch/references/contract-review.md — 60 → 60 lines
- 同形另带 ˋLocal-runs:ˋ 行:ˋnoneˋ,或 ˋprobe — REASONˋ 具名唯一本地探针;有行必校,缺行旧记录不改判。- 同形带 ˋLocal-runs:ˋ 行:ˋnoneˋ 或 ˋprobe — REASONˋ 具名唯一探针;有行必校,缺行旧记录不改判。- 简报从 ˋnode scripts/pm/record-recognisers.mjs --brief-templateˋ 起稿:只读条款与输入集内建,⛔ 不删 ⛔ 行。- 简报从 ˋrecord-recognisers.mjs --brief-templateˋ 起稿:只读条款与输入集内建,⛔ 不删 ⛔ 行。- 落地前检两条,过则 Tier S 入队、Tier H 等人批:① 达档条款②复核 PASS 在案(同形记录)。- 请审/求批与落地前检两条,过则 Tier S 入队、Tier H 等人批:① 现 head 同形达档 PASS 在案。- 落地时仍欠复核的 PR 在落地 head 复审,车道席或分诊按 (a)(b)(c) 接;FAIL ⛔ 不修已关 PR。- 每条 must-fix 引该记录立新卡、按发现定级;回退仅限主干红(p0,main-red 约定①)或安全边界。.claude/skills/pm-dispatch/references/landing-operations.md — 101 → 101 lines
- PASS ⇒ ready、auto-merge;FAIL ⇒ 补丁轮;⛔ 免复核不放行。- PASS ⇒ Tier S ready、auto-merge;Tier H 经 SKILL.md ③ 交棒请审;FAIL ⇒ 补丁轮;⛔ 免复核不放行。- 落地后才见欠复核 ⇒ 按 ˋcontract-review.mdˋ 复审落地 head、发现立新卡,⛔ 不修已关 PR。- 契约复核 PASS 落地的 PR 到窗口时已 ready 且 auto-merge 在挂,见 ˋcontract-review.mdˋ。.claude/skills/pm-dispatch/references/lanes/director.md — 86 → 86 lines
- 受管 PR 待人批前核四件:席位记录、维护者速读、中继 ˋpr_request_reviewersˋ 请审、绿 head。- 受管 PR 待人批前核五件:席位记录、速读、现 head PASS、ˋpr_request_reviewersˋ 请审、绿 head。.claude/skills/pm-dispatch/references/dispatch-runbook.md — 245 → 245 lines
- coordinator 按优先级开线程,p1 先;全项目上限由维护者按项目定(ˋcoordinator.mdˋ),满即排队。- 线程 ⛔ 不做 harness 开 PR 后指派/请审:「审核通过才会推送给我审核」,请审是席位交棒。Tests
Self-tests, before (origin/main 28872e6) → after (50118ff), exits captured before any pipe
fleet-write/validate.mjs --self-testfleet-write/execute.mjs --self-testfleet-write/dispatch.mjs --self-testcheck-half-states.mjs --self-testH43 hand-off timing 89/80(57 legacy coverage cases driven with the hand-off DUE + 32 timing cases)record-recognisers.mjs --self-testcheck-owed-reviews.mjs --self-testcheck-governed-queue-guard.mjs --self-testcheck-handover.mjs/fleet-roster.mjs/seat-record.mjs/check-governed-merges.mjs --self-testAblations — one per changed script, committed state first, restore hash-proven by scripts/ablation-replace.mjs (blob == HEAD, git diff HEAD empty), whole tree clean after
Expected direction for every leg: turn red (常态). Observed:
ops.mjs—governedReview: trueplanted back onpr_create(anchor hit 1 → 0, blob 2abc5979 → f52678f1, restored to 2abc5979).validate.mjs --self-testexit 1 with the named pin red: 「the governed-review follow-up runs after exactly pr_ready … 1 of 216 case(s) failed」.execute.mjs --self-testexit 1 by a TypeError at L1303 (the requests battery'spr_create+issue_createstroke stopped after the create — the re-enabled follow-up asked forGET …/pulls/9/files, which the fixtures no longer prime — so the second write never happened): red by crash at the first create-side case the mutation reaches, before the ⭐ negative pin itself was evaluated.execute.mjs— the follow-up forced to run afterpr_createagain (action.op === 'pr_create' ||).execute.mjs --self-testexit 1, same TypeError at L1303 for the same reason (a follow-up after the create), red by crash. Restored to ddd1bfaa == HEAD.check-half-states.mjs— the hand-off gateif (handoff?.state !== 'due') return null;deleted.--self-testexit 1 by a TypeError ath43GovernedReviewRequestGap(handoff.recordon an undefined hand-off, reached from the 「an UNREAD thread is UNJUDGED」 pin): red by crash at exactly the pin the gate protects. Restored to f5c5c23f == HEAD.check-half-states.mjs—contractReviewVerdictOfansweringPASSfor every explicitVERDICT:line.--self-testexit 1 with 6 named ✗ cases, among them 「a FAIL on the current head is BEFORE (got "due,PASS", want "before,FAIL")」, 「the newest PASS on the head decides, and a FAIL after it withdraws the hand-off」, 「**VERDICT: PASS**reads PASS, and FAIL reads FAIL」, 「the explicit VERDICT line wins over prose」. Restored to f5c5c23f == HEAD.check-half-states.mjs(3b, the non-crash reading of leg 3) — the gate narrowed tounread/undefinedonly, so BEFORE is no longer quiet.--self-testexit 1 with ONE named ✗ case out of 5066: 「H43 row: ⛔ BEFORE the hand-off, nobody asked is NOT a half state — quiet」 (it got the finding sentence, wanted null); every DUE case stayed green, so the mutation moved exactly the predicate the card asks for. Restored to f5c5c23f == HEAD;git status --porcelainempty after every leg.Acceptance notes
AGENTS.md(Tier H, outside this dispatch's file list and not edited here) still says in 〈Multi-agent working discipline〉 「the PR's assignee mirrors the card's, set by the executor at pr_create」 — contradicted by os-dev.md L37 after this PR. One sentence to retire; it needs the maintainer's hand on a Tier H file. carrier: the seat (domain:skills#2) files it or hands it to triage; noted here, not filed by the dev.pm:on-hold: its shape 1 (the approver request moves offpr_create) is implemented here; triage decides its disposition after landing.check-half-states.mjsclaimed the relay summons atpr_create; this PR makes that false, so the two spots (and the one self-test pin on the words) now describe the hand-off. No row semantics changed for H69.latestContractReviewOnHeadnow returnsverdictbesideidandsha(additive;record-recognisers.mjsdoes not import it).pr_createcarried noassigneeswhile os-dev.md L37 onmainstill said to send one — the seat ruled the omission for this PR on both claims.test:repo(CI'sTest Core), the lint sweep, dogfood (no!in the title, no(narrowing)arm); every CI family is read from the PR's check-runs by the seat..github/workflows/**line was needed; no new gate, script or workflow.Verification
Local subset = the derived union, run on the final head
50118ffc(node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, change set from the merge base28872e68; 11 paths, +461/−199 lines, under the 3000-line threshold). 67 families, every exit captured before any pipe (cmd > log 2>&1; status=$?), reconciled with--ran: 67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN (✓ dispatch-gates --ran: 67 derived famil(ies) accounted for). One family first answered exit 3 (check:doc-formula-expressions, PREREQUISITE NOT MET — itsdist/inputs were not built in this worktree); afterturbo run build --filter=@objectstack/formula --filter=@objectstack/lintunder the shared verify lock (VERDICT command-exit 0 · held the lock 2s · waited 0s, a full cache replay) it was re-run and answered exit 0. Non-zero exits remaining in the record: 0.The 67 commands and their exits (the `--ran` record)
Local-only readings (CI runs their
--self-testonly):check:pm-skill-ratchet— every ceilinged file at its landed count (SKILL.md 319/319 with the widest-row pin 341 B untouched; os-dev.md 402/402; execution-duties 188/188; contract-review 60/60; landing-operations 101/101; director 86/86; dispatch-runbook 245/245), every edited line ≤120 B;check:pm-skill-id-lint105 files clean;check:nul-bytesclean over 22172 files;check:dev-prereqs/check:skill-frame-freshnessnot applicable (nopackages/specor four-axis frame edit; the frame's md5 at L242–262 is unchanged,abff5f852c8fd09b79ec0623439aa4f0).CI families (
Lint & Repo Gates,TypeScript Type Check,Test Coreincl.test:repo,Governed Surface Queue Guard, the UI four) are read from this PR's check-runs by the seat; nothing of them was re-run locally beyond the derived subset above.This PR's own open through the relay carried no
assigneeskey; the stroke's--jsonread-back (assignees and requested reviewers as the platform lists them) is quoted in the os-dev report comment on card 27345.Generated by Claude Code