skills(pm-dispatch): rank a forced takeover below an in-flight claim - #17373
Conversation
A maintainer-ordered forced takeover takes the seat, its queue, cards not yet started and PRs awaiting landing; it does not take a card whose dev is in flight. Those finish under the original claimant and return to the new seat through the landing record or the `Release:` line. The mechanism is named rather than narrated: a subagent dev's return message, liveness probe and resume exist only in the dispatching session. SKILL.md 〈座位贴协议〉 stays at 812 lines: the two new lines are paid by cutting the lessons-prose/timer-audit line (its two rules survive in dispatch-runbook 行文纪律 and the hand-off checklist step 6) and folding the 改正文 + 审计评论 rule into the reference pointer. core-rules mirrors the precedence in place (151/151); the hand-off checklist step 9 now names in-flight dev cards with their dispatching session ID (91/91). Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK Co-authored-by: Claude <noreply@anthropic.com>
维护者速读改了什么 —— PM 技能文本三个文件,行数全部不变(812 / 151 / 91)。主文件〈座位贴协议〉新增两行:① 维护者的「强制接管」令拿走座位、队列、未开工的卡和等落地的 PR,⛔ 不拿正在由开发 agent 处理中的卡——那些由原席位跟到落地,再经落地记录或 为什么改 —— 您 09-09 的裁决(原话在卡上):「强制接管也不应该抢已经在处理的任务」。规则文本里已有「在飞由原认领者跟完」,但没有一行说它压过接管令,上一次接管评论因此把本车道所有在飞卡一并划走;「接管转移的是卡、转移不了子代理的回报通道」这条架构事实此前没写进任何接管条文。 风险与代价(含回滚) —— 只改协议文本,不改代码与门禁;行数净零、每行 ≤120 字节、决策框架块 md5 不变、派生的 16 个门禁族在 dev 本地全绿;PR 的两个必查 CI job 在本席复核时(10:0xZ)仍在跑,人合前会收敛,本席下次巡检复读。代价:接管后的新席位对处理中的卡只能等它落地或释放,不能主动介入——这正是裁决要的。回滚 = revert 本 PR 的单个提交。 席位意见 —— 通过。本席在契约复审档对照 diff 自读:两行新规与裁决同向;「在飞」一词与座位贴台账既有用法一致(在飞 = dev 在跑,与「待落地 PR」分列,主文件 :74 / :280 / :685 同义);卡上的提案 3(转贴豁免)经 dev 实测为多余(dev 的报告本就先落卡,任何席位可读),没写——正确。dev 报告的一条派发词失误归本席:派发词的 grep 读数漏了主文件 :106 的一处「接管」,不影响结论。受管面:本席不翻 ready、不入队、不批准。 你要做的 —— 一个动作:人工合并本 draft PR。 skills 席,session Generated by Claude Code |
Fixes #17033
Governed surface (
.claude/**) — draft only; a human merge is the review record.Maintainer ruling implemented (verbatim, as quoted on the card): 「如果你的当前任务对方也在处理了,那技能有问题,需要更新,强制接管也不应该抢已经在处理的任务。」
What changed — three files, every ceiling net-zero (SKILL.md 812/812 · core-rules 151/151 · seat-post-protocol 91/91)
Base
143c715; head5d1d938. Line numbers below are at the base; bytes are UTF-8 (MAX_LINE_BYTES = 120, CJK is 3 bytes a character)..claude/skills/pm-dispatch/SKILL.md〈座位贴协议〉 — 812 → 812 lines- 接管/移交 = 改正文 + 审计评论(评论只作审计不承载状态),接管压缩是标准步骤。- 维护者强制接管令取席位、队列、未起工卡与待落地 PR;⛔ 不取在飞卡,由原认领者跟完。- 子代理 dev 的返回消息、探活与续派只在派发会话;落地或 `Release:` 后归新席位。- 经验教训散文不再入技能文本;交接按收尾清单逐步走完,并 `list_triggers` 清点自设定时器。- 四段模板、状态词表、接管/退场收尾清单细则见 `references/seat-post-protocol.md`。- 接管/移交 = 改正文 + 审计评论(只作审计);收尾清单等细则见 `references/seat-post-protocol.md`。Two lines added, two paid. The dispatch's suggested one-liner measures 171 bytes and the 「fold :269 and :286」 payment measures 160 bytes, so neither fits the 120-byte cap; the construct is kept and split: :269 carries scope + prohibition + 原认领者跟完, :270 carries the mechanism + the hand-back.
.claude/skills/pm-dispatch/references/core-rules.md〈座位贴协议〉 — 151 → 151 lines- 交接按收尾清单逐步走完并清点自设定时器;归档自己派出的会话是不可移交的义务。- 交接按收尾清单走完;强制接管 ⛔ 不取在飞卡,由原认领者跟完;归档自派会话不可移交。Judgment — binding-level: yes, so the mirror is owed. (a) SKILL.md :42 ranks 维护者裁决 above AGENTS.md, 红线, 核心条款 and 细则, in that order; a takeover order arrives as a maintainer instruction, so a prohibition that must hold against one has to sit at 核心条款 level, not only among 细则. (b) The digest's 座位贴协议 section already carries the two adjacent hand-off invariants of the same family (:76 在飞安置而非归零, :78 归档不可移交). (c) SKILL.md :44 「一条规则在本文与核心条款一处改动,另一处同 PR 同改」 — once the rule is in SKILL.md and judged core, the same-PR mirror is a requirement, not an option. Rewritten in place: no line added.
.claude/skills/pm-dispatch/references/seat-post-protocol.md交接收尾清单 step 9 — 91 → 91 lines9. 确须留跑的会话在座位贴里点名,写明归档不随交接转移,⛔ 不留作接任者的欠账。9. 在飞 dev 卡与留跑会话在贴里点名(卡号 + 派发会话 ID);跟完与归档 ⛔ 不随交接转移。The step already spoke of sessions that must keep running; it now also names in-flight dev cards with their dispatching session ID, and says that finishing them, like archiving, does not transfer. Rewritten in place: no line added.
Where every cut rule survives (value gate ②: 「被砍内容若在别处无家,砍掉就是丢规则」)
.claude/agents/os-dev.md:20 (the dev-side twin: rules only, lessons written as self-contained rules); the AGENTS.md header (rules only, no incident narrative)list_triggers清点自设定时器 (from :285, and from core-rules :78)list_triggers清点本会话全部自设定时器,逐个清理或随移交物转交。」Zone-2 measurements (all at
143c715)grep -n '接管' SKILL.mdhits three lines, not two: :106 (「弃飞无接管」, one of the four release causes in the assignee table row), :269 and :286; none ranks a takeover against an in-flight claim. 「原认领者跟完」 exists for two of the three seat-exit paths — 惰性回收 (dispatch-runbook :52, under 座位贴活性巡查) and epic 僵尸回收 (seat-post-protocol :74, under Epic 车道收尾与僵尸回收, explicitly 「子树内」) — and was absent for the third, 维护者交接令 (SKILL.md :695). The new SKILL.md :269 is what generalises it to that path.os-dev-reportcomment is written by the dev itself, on the card, before its return message, so it outlives the dispatching session and any seat can read it. What does not transfer: 探活 (:569–:577), 续派 / 停摆复位 (:581–:583) and the return message — amode:subagentdev shares the PM's session (:475 「mode:subagent的 dev 与 PM 同会话同 ID」) and has no handle another session can address. ⇒ the card's proposal 3 (a one-way relay exemption) is moot and is not written; the precedence line plus 「原认领者跟完」 is the whole fix. Proposal 2 lands as the step-9 rewrite, not as a new clause.Route on the four axes, briefly: 实际业务需求 — a real, maintainer-confirmed takeover order enumerated 「every
pm:dispatchedcard in the lane whatever session claimed it」; the boundary it needed did not exist in the text. 项目长远合理性 — the rule names the mechanism (subagent of the dispatching session; report channel already on GitHub) rather than adding a relay ritual. 防 AI 犯错 — a ⛔ at 核心条款 level is structurally harder to read past than a 细则 line; the checklist step makes the in-flight set explicit (card + session ID) instead of implied. 创业阶段不扩散 — two lines in, two lines out; no new checklist step, no new gate, no ceiling raised.Gates (run at
5d1d938; every exit code captured before any pipe)node scripts/pm/dispatch-gates.mjs --commandsderived 16 commands from the committed change set;--ranreconciles 「16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED」. Verdict lines:pnpm check:pm-skill-ratchet— exit 0: 「SKILL.md is 812 lines (ceiling 812; headroom 0)」 · 「core-rules.md is 151 lines (ceiling 151; headroom 0)」 · 「seat-post-protocol.md is 91 lines (ceiling 91; headroom 0)」; every line within 120 bytes.pnpm check:pm-skill-id-lint— exit 0: 「27 file(s) clean」.pnpm check:skill-frame-sync— exit 0: 「the one declared copy of the decision frame is internally coherent」; md5 of SKILL.md :734–:752 =22f2339f0acb64cdb50c7adc9db681c3, unchanged.pnpm check:pm-governed-prose— exit 0: 「2 instruction surface(s) name all 5 registered governed surfaces」.pnpm check:nul-bytes— exit 0: 「no raw ASCII control bytes」.pnpm check:pm-governed-merges— exit 0 (self-test, 274 assertions).node scripts/pm/check-governed-merges.mjs --teston the three paths — exit 3: 「GOVERNED — a human merge is the review record」,.claude/**×3.pnpm --filter @objectstack/lint run check:doc-formula-expressions— first run exit 3 「PREREQUISITE NOT MET」 (unbuilt@objectstack/formula/@objectstack/lint, nothing measured); built both under the verify lock (VERDICT command-exit 0), re-run exit 0.pnpm check:agent-test-spelling,pnpm check:doc-authoring,pnpm check:driver-memory-census,pnpm check:refd-timer-probe,pnpm check:watch-hint-literal,node scripts/check-closing-keyword-parity.mjs(and--self-test),node scripts/check-comment-mask-corpus.mjs,node scripts/pm/check-governed-queue-guard.mjs --self-test— all exit 0.pnpm check:pm-dispatch-gates(named by the dispatch, not in the derived 16) — exit 0: 「dispatch-gates self-test: 1674 cases pass.」 It ran past the foreground cap; waited on its PID withtail --pid.Declared narrowing:
--ranreported STALE TREE — a sibling's fetch movedorigin/maintod29fdcfa(five commits) during this run. Zero of those commits touch.claude/**or any script behind the 16 derived families (the one script change,scripts/check-single-claim-paths.mjs, is an artifact-roster family outside the derived set), so the derivation is unchanged andmainwas not merged into this three-line governed diff. The repo-widepnpm lintsweep is CI-owned and was not run here.Acceptance notes
mode:clouddev is a separate session, so its 续派 can technically be delivered by another seat through a poke trigger (seat-post-protocol :33); the new :270 is written for the subagent case, and the mode-blind prohibition on :269 plus checklist step 8 (archive not transferable) cover the cloud case. 承接者: 无 — behaviour is already correct; recorded so the two lines are not read as one.scripts/clause covers gates only — a non-gatescripts/**script has no row,scripts/pm/**is stated only inreferences/lanes/skills.md, and three devx.md:8 paths have none — the successor gap to #17222 #17225 and [finding].claude/agents/os-dev.mdstates sibling repos have noscripts/pm/— objectui has one, and a dispatch built on that premise reached a governed file this shift #17244 are queued on other regions of the same files; no card since names takeover). No card filed by this run.维护者速读(草稿)
改了什么:PM 技能文本三处、三个文件,行数全部不变。新增一条规则:维护者下令「强制接管」时,新席位拿走座位、队列、还没开工的卡和等落地的 PR;正在由开发 agent 处理中的卡不拿,由原席位跟到落地,再经落地记录或
Release:行交回新席位。并写明机制:处理中的开发 agent 是派发会话的子代理,它的回报、探活和续派只有那个会话做得到。核心条款同步一行;交接清单第 9 步改为逐张点名处理中的卡与派发会话 ID。为什么改:您 2026-09-09 的裁决(原话在卡上)所要求的「在飞由原认领者跟完」规则文本里已有,但没有任何一行说明它压过强制接管令,上次接管评论因此把「本车道所有 pm:dispatched 卡」一并划走。另外「接管转移卡、转移不了在飞的测量通道」这一架构事实此前没写进任何接管条文。
风险与代价(含回滚):只改协议文本,不改代码与门禁;行数预算全部净零,靠删两行支付,被删内容在别处都有家(正文有逐条对照表)。代价是接管后的新席位对在飞卡只能等它落地,不能主动介入。回滚 = revert 本 PR 的单个提交。
席位意见:(留空)
你要做的:人工合并本 draft PR(受管面,席位不得合并)。
Generated by Claude Code
Generated by Claude Code