Skip to content

skills(pm-dispatch): name the parked shape and exit when the contract-review tier is measured unavailable - #17082

Closed
yinlianghui wants to merge 1 commit into
mainfrom
claude/issue-16912-clause2-tier-unavailable-exit
Closed

yinlianghui wants to merge 1 commit into
mainfrom
claude/issue-16912-clause2-tier-unavailable-exit

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #16912

What changed

Two rule lines in .claude/skills/pm-dispatch/references/contract-review.md, beside the downgrade fuse's safe-state sentence (「卡在队列外等待是安全态」), and one in-place rewrite of the 〈入队与落地〉 line in .claude/skills/pm-dispatch/SKILL.md that asserted the parking is brief. The gate line itself (SKILL.md:640, rewritten by the earlier merged PR) is not touched; no tier policy, label or state is added; the exit is expressed with the existing six states and existing line contracts only.

The lines (before → after, byte widths measured)

references/contract-review.md — 60 → 60 lines (ceiling 60, headroom 0); every line ≤ 120 B.

Added directly after 「改走转录核验的复核子代理;标签在复核完成前原样留置,卡在队列外等待是安全态。」:

- 档位实测不可用 ⇒ 无 PASS 可产,命中闸门的卡成批停靠且不短暂:翻 `pm:on-hold`,⛔ 不干等。      (120 B)
- 带 `Restart-when: 服役档 = CONTRACT_REVIEW_TIER` 与 `Unlock-action: re-check PR #M`,日频判据批扫捞回。 (118 B)

Paid by deleting the two rules this file restated from SKILL.md — content deletions, no re-wrap; the file's own landed standard is 「no rule already stated in SKILL.md」:

- 归属该卡派发席,交付后收集复核当轮席内完成。                                   (66 B, deleted)
- 外部评审链是可选事后审计:分诊定时轮与总监席召唤 ⛔ 不是放行必要条件。            (104 B, deleted)
  • The first restates SKILL.md:643 「交付后复核由派发席在席内完成:达档 PM 自审,或派契约复审档复核子任务。」; its one extra token 「当轮」 is exactly the default the two new lines qualify.
  • The second restates SKILL.md:646 「外部评审链降为可选事后审计,非放行前提。」; the only content lost is the naming of the two chains (分诊定时轮 · 总监席召唤), recoverable from core-rules.md :40 / :147; the audit consequence line 「审计 FAIL 按状态机 label-flip 交回派发席补丁轮。」 stays.

SKILL.md — 812 → 812 (ceiling 812, headroom 0), 〈入队与落地〉, rewritten in place:

before: - 挂标后复核完成前短暂停靠;⛔ 不前瞻预挂。                                 (61 B)
after:  - 挂标后复核完成前短暂停靠;档位实测不可用的改道见降档保险丝;⛔ 不前瞻预挂。   (110 B)

Why the main file needs this one: it is the single sentence asserting the parking is brief; the very next line already points at references/contract-review.md for the 降档保险丝, so the detour is reachable from the enqueue step without a second pointer.

references/core-rules.md — untouched (151/151). The clause is an operational failure mode of the review chain (细则), not a red line; the core summary already carries the gate (:124 「无达档复核 PASS 的契约卡 ⛔ 禁止入队」) and the hold/blocked line contracts (:31, :35).

Why — the consequence the text left unstated

Chain on origin/main: SKILL.md:640 path or declaration limb hit ⇒ no in-seat PASS at CONTRACT_REVIEW_TIER on record ⇒ ⛔ 禁止入队; :643 a PASS comes only from an at-tier PM self-review or an at-tier review subtask; contract-review.md:60 「契约复核 ⛔ 不适用额度耗尽豁免降档」. So when the tier is measured unavailable, every gated card parks at once, and :53 「卡在队列外等待是安全态」 read as a brief stop. Triage narrowed the card to writing, verbatim: 「说明这个「安全态」在档位实测不可用时的形态与出口 —— 是无限期等待、还是有一条明示的改道(例如把卡翻 pm:blocked + 指向档位可用性),以及谁负责在档位恢复时把它们捞回来」.

The exit — four-axis analysis of the three candidates

Candidates inside the existing six states, using existing line contracts only:

  • A. pm:blocked + Blocked-by: #ANCHOR + Unlock-action: re-check PR #M, where ANCHOR is a tier-availability card that closes when the tier returns.
  • B. pm:on-hold + Restart-when: 服役档 = CONTRACT_REVIEW_TIER + Unlock-action: re-check PR #M, recovered by the daily Restart-when: predicate batch scan. Chosen.
  • C. Stay in pm:dispatched; the dispatch seat re-reads the tier every round.

实际业务需求 — the parked shape is live today (triage names a card stuck on it). Readers of each exit, measured in the tree: H9 (scripts/pm/check-half-states.mjs:2107) accepts any non-manual Restart-when: value as fireable, so B's predicate is a legal hold; the daily predicate batch is a named duty (SKILL.md:373 「可执行判据由分诊席每日一个低频子轮批量执行」, dispatch-runbook.md:77Restart-when: 判据批扫」); H11 inventories important cards parked in pm:on-hold / pm:blocked. A's anchor card has no reader and no writer anywhere in the corpus: nobody files it, nobody closes it. C leaves the wait invisible to every parked-state inventory, against SKILL.md:145 「等待他座位也是状态,写在卡上才存在」.

项目长远合理性 — B reuses the precedent already in the main file for "done here, waiting on an external non-card condition": SKILL.md:141 「未发版 ⇒ 转 pm:on-hold + Restart-when: 加消费方安装面判据,⛔ 不回 pm:queue」. Its predicate is the fuse's own reading (contract-review.md:52 读数 = CONTRACT_REVIEW_TIER), so the resume condition and the review precondition are one measurement. A invents an anchor-card lifecycle — a new artifact kind with an open/close owner — to carry a condition that is not a card; state-machine.md:26-27 restricts Blocked-by: targets to a card that closes at that moment and says 「⛔ 不扩词表」.

防 AI 写代码犯错 — the failure to prevent is a seat self-clearing or re-dispatching under an unstated wait (triage's first re-rating trigger). B: the predicate cannot be satisfied by self-declaration (:52 「⛔ 自述档位不是读数」), and the hit is routed by the existing single-value Unlock-action: re-check PR #M (SKILL.md:125 「改写完工卡的解锁动作,只认此一值」), so a finished card is never sent back to pm:queue (state-machine.md:31 「⛔ 永不给完工卡重派 dev」). A adds a second failure surface: a forgotten or duplicated anchor becomes H19 / H26 noise. C gives the machine no line to read.

创业阶段不扩散需求 — B adds zero artifacts: one existing state, two existing line spellings. A adds a card convention nobody asked for. C adds an exception to the reclaim and aging rules.

Recommendation: B, on all four axes. Two readings this PR relies on, flagged for the reviewer:

  1. Unlock-action: re-check PR #M is documented under the pm:blocked heading in state-machine.md:29 but defined state-agnostically in SKILL.md:125 (完工卡); both parked states fire from the same unlock scan (state-machine.md:15), and no script reads the line. The rule pairs it with pm:on-hold on that reading. If the line should stay pm:blocked-only, the hold comment's pre-written wake shape (SKILL.md:142) carries the same instruction in prose and the second new line loses its second code span.
  2. The predicate is evaluated by the fuse read (contract-review.md:51-56, platform-readings.md:331-343): an at-tier subagent's harness-stamped model, never get_session of the default-tier seat (:54).

Boundary, unchanged: H26 lists downstream Blocked-by: dependents of any pm:on-hold target as "a block nothing can release"; for a tier-parked card that row is the designed visibility and its remedy is reading the target's Restart-when:.

Evidence

Governed-surface predicate — node scripts/pm/check-governed-merges.mjs --test .claude/skills/pm-dispatch/SKILL.md .claude/skills/pm-dispatch/references/contract-review.md, exit 3:

governed-surface predicate: 2 of 2 path(s) hit the register (5 surfaces, repo-agnostic).
  ⛔  GOVERNED — a human merge is the review record for this PR (#9495 regime).
      No seat flips it ready, enqueues it, or arms auto-merge (AGENTS.md Prime Directive #14).
      One hit governs the whole PR — 「混合 diff 一条命中即整 PR 分叉」; proportion is not a question.
      .claude/** ×2 — the agent instruction tree (skills, agents, hooks, settings)
        - .claude/skills/pm-dispatch/SKILL.md
        - .claude/skills/pm-dispatch/references/contract-review.md

Draft, human merge: not flipped ready, not queued, no auto-merge, no approval. skip-changeset: nothing under any released package's files[] moves (.claude/** only, fast lane).

Ratchet — pnpm check:pm-skill-ratchet at e13b4e0e8, exit 0:

✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/contract-review.md is 60 lines (ceiling 60; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/core-rules.md is 151 lines (ceiling 151; headroom 0).

Merge-tree probe — git merge-tree --write-tree 854639b31 e13b4e0e8 (origin/main read 06:55Z) → tree 72c89bbe; in that tree contract-review.md 60 lines / widest 120 B, SKILL.md 812 / 342 B (a pre-existing pinned table row), core-rules.md 151 / 120 B. origin/main has not touched .claude/skills/pm-dispatch/ since the branch base edf59e35.

Gate families derived from the tree — node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; derivation anchored at e13b4e0e8): 16 commands, all run in the foreground with the exit code captured before any pipe; --ran reconciliation: 「16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED」.

gate exit verdict line
pnpm check:pm-skill-ratchet 0 the three ceiling lines above
pnpm check:pm-skill-id-lint 0 26 file(s) clean (pattern /#[0-9]{3,}/g)
pnpm check:skill-frame-sync 0 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:nul-bytes 0 OK (scanned 8018 text file(s) … no raw ASCII control bytes)
pnpm check:pm-governed-merges 0 --self-test: 274 assertions
pnpm check:pm-governed-prose 0 2 instruction surface(s) name all 5 registered governed surfaces
pnpm check:doc-authoring 0 398 files clean; 46 published skill files clean
node scripts/pm/check-governed-queue-guard.mjs --self-test 0 self-test
node scripts/check-closing-keyword-parity.mjs (+ --self-test) 0 / 0
node scripts/check-comment-mask-corpus.mjs 0
pnpm check:agent-test-spelling 0
pnpm check:driver-memory-census 0
pnpm check:refd-timer-probe 0
pnpm check:watch-hint-literal 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions 3 → 0 first pass PREREQUISITE NOT MET (nothing measured: @objectstack/formula and @objectstack/lint not built); built under the shared verify lock (VERDICT command-exit 0 · held the lock 219s · waited 0s) and rerun → 「22 record-scoped formula example(s) across 434 files / 1373 TS blocks judged clean」

Reverse verification of the ratchet on the committed head (mutate → run → restore with git checkout HEAD -- PATH; blob hash compared to the HEAD: blob 8fe05320; git diff HEAD empty after each leg):

  • a 61st line appended → 「✗ … contract-review.md is 61 lines; the ratchet ceiling is 60」, exit 1; restored, hash match.
  • the 120 B line grown by one CJK character (123 B) → 「✗ … has 1 line(s) over the 120-byte budget: L52 (123B)」, exit 1; restored, hash match.

Control-byte self-scan of both files: no hits; positive control on a NUL byte: 1 hit.

check-clause2-carriers --pair: not applicable — the claim declares Clause-②: no (text-only change on .claude/**, no contract surface), so needs:contract-review is not applied on either carrier.

验收备注

  • noted, not filed: H26's header calls pm:on-hold a state that "can never close"; with an executable Restart-when: predicate (already the shape at SKILL.md:141) a hold closes through the daily scan. Report-only inventory wording, pre-existing; 承接者:无.
  • noted, not filed: the deleted contract-review.md line was the only place naming 分诊定时轮 and 总监席召唤 as the external review chain; the rule survives at SKILL.md:646. 承接者:无.

维护者速读(草稿)

改了什么 — 契约复核细则的降档保险丝旁边加了两行:契约复审档实测不可用时,过条款②闸门的卡不是短暂停靠,而是成批停在队列外;此时卡翻 pm:on-hold,带可执行判据 Restart-when: 服役档 = CONTRACT_REVIEW_TIER 与既有的 Unlock-action: re-check PR #M,由日频判据批扫在档位恢复后捞回、重回席内复核。主文件〈入队与落地〉里「短暂停靠」那句原地加了一个指向。为付行数棘轮,删掉了该细则里两条主文件已有的重复规则。

为什么改 — 现行文本只说「等待是安全态」,没说这个等待在档位不可用时会变成整批、无出口的停摆;席位撞上了才知道,而且文本没告诉它该等还是该改道、谁来捞回。这一条把形态、出口与捞回责任写进席位真正会读到的位置。

风险与代价(含回滚) — 不改闸门、不改档位政策、不加标签不加状态,只用既有六态与既有行契约。代价:细则文件删了两条重复规则(其中一条唯一损失是「外部评审链」两个成员的点名)。一处需要维护者确认的读法:Unlock-action: 目前写在状态机细则的 pm:blocked 段下,本 PR 按主文件「完工卡的解锁动作」的通用定义把它配到 pm:on-hold。回滚 = revert 本 PR,一个提交。

席位意见 — (留空,席位定稿成评论)

你要做的 — 受管面,人工合并:确认上面那条 Unlock-action: 读法后合并;若希望该行只留给 pm:blocked,告诉我改用 hold 评论预写唤醒形状的拼写。

🤖 Generated with Claude Code

https://claude.ai/code/session_01HxLw5aKDPR5RJgyUR7Exkd


Generated by Claude Code

…-review tier is measured unavailable

The clause-② enqueue gate refuses a PR whose diff hits packages/spec/src/**
(or whose claim declares Clause-②: yes) until an in-seat PASS at
CONTRACT_REVIEW_TIER is on record, and the review is exempt from the
quota-exhaustion downgrade by design. The downgrade fuse in
references/contract-review.md already called the resulting parking a safe
state, but never said what that state looks like when the tier is measured
unavailable: every gated card parks at once, the wait is not brief, and no
text named an exit or a recoverer.

Two rule lines beside the fuse's safe-state sentence now say it: the parked
cards flip to pm:on-hold (never idle in pm:dispatched), carry the executable
predicate `Restart-when: 服役档 = CONTRACT_REVIEW_TIER` plus the existing
single-value `Unlock-action: re-check PR #M` so the hit re-enters the in-seat
review instead of re-dispatching a finished card, and are recovered by the
daily Restart-when predicate batch scan. The main file's 〈入队与落地〉 line
that asserted the parking is brief now points at the fuse for the
tier-unavailable detour, rewritten in place.

The reference file's line ratchet has zero headroom; the two additions are
paid by deleting the two rules the file restated from SKILL.md (post-delivery
review ownership at :643, the external review chain being optional audit at
:646) — content deletions, no re-wrap. No tier policy, label or state is
added; the gate line itself is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HxLw5aKDPR5RJgyUR7Exkd
@github-actions github-actions Bot added size/xs documentation Improvements or additions to documentation labels Sep 9, 2026
@yinlianghui yinlianghui added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 9, 2026 — with Claude

Copy link
Copy Markdown
Collaborator Author

维护者速读 — PR #17082(#16912,skills 席终稿,2026-09-09T07:05Z)

改了什么 — 契约复核的「降档保险丝」一段补两句:契约复审档(fable)实测不可用时,任何 diff 触及 packages/spec/src/** 的 PR 都拿不到入队所需的 PASS,于是整条 spec 车道的卡会成批停在队列外,而且不是短暂;席位的动作是把这些卡翻 pm:on-hold,带机器可读的 Restart-when: 服役档 = CONTRACT_REVIEW_TIERUnlock-action: re-check PR #M,由每日一次的判据批扫在档位恢复时捞回,⛔ 不在 pm:dispatched 里干等。主文件里「短暂停靠」那句改为指向这段。为凑行数,contract-review.md 删了两句主文件已有的复述。两文件 +3/−3,行数上限全部不动。

为什么改 — 分诊复核(5594879773):PR #16915 已把闸门改成「无 PASS 在案禁止入队」,而复核没有额度耗尽豁免 ⇒ fable 不可用时 spec 车道会无限期停摆,文本只说「等待是安全态」,没说它是车道级、无自愈出口的;#16611 当时就卡在这里。这一句让席位能据文本判断「该等还是该改道」。

风险与代价(含回滚) — 纯指令文本;不改档位政策、不加标签、不加状态;回滚 = revert 本 PR。一处需要你看:Unlock-action: re-check PR #M 原本只在 pm:blocked 一节被记载,这里把它配给 pm:on-hold 卡——本席判为同一条行契约(SKILL.md 对「完工卡」通用定义,没有脚本读它),已在 ACCEPT 里答 A;若你要它只留在 blocked,把第二个 code span 删掉即可。

席位意见 — 接受(契约复审档席内复核)。棘轮 812/60/151 未动;id-lint、frame-sync 绿;控制字节 0;mergeable: true;CI 16 绿 / 1 进行中。

你要做的 — 合并;或由 os-zhuang / hotlong 批准,本席随即入队。只需看上面那一处配对。


Generated by Claude Code

@os-zhuang

Copy link
Copy Markdown
Contributor

你不能因为自己当前没有档位去修改卡的状态,完全不合理,去处理其他卡就可以

@os-zhuang os-zhuang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你不能因为当前没有档位就去改卡的状态,建议直接关闭

Copy link
Copy Markdown
Collaborator Author

收到,按原话执行:档位不可用不改卡态——不翻 pm:on-hold、不写 Restart-when:/Unlock-action:;席位转做其它卡,受闸门的卡原样停在终局,下一个读到契约复审档的 fire 接着复核。已派补丁轮到同一 dev、同一分支(普通 push,不 force-push);推上来后本席复核新 head 再请审。


Generated by Claude Code

@yinlianghui yinlianghui closed this Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

Closing this PR per the changes-requested review by os-zhuang (07:54Z), verbatim: 「你不能因为当前没有档位就去改卡的状态,建议直接关闭」. The patch round dispatched after the first comment is withdrawn (nothing pushed). Disposition of #16912 is recorded on the card: the rule the maintainer gives is behavioural — a seat that reads no contract-review tier changes no card state and handles other cards — and needs no new text. Skills seat, session session_01HxLw5aKDPR5RJgyUR7Exkd, 2026-09-09T07:56Z.


Generated by Claude Code

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 needs-user-decision size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants