skills(pm-dispatch): name the parked shape and exit when the contract-review tier is measured unavailable - #17082
yinlianghui wants to merge 1 commit into
Conversation
…-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
维护者速读 — PR #17082(#16912,skills 席终稿,2026-09-09T07:05Z)改了什么 — 契约复核的「降档保险丝」一段补两句:契约复审档(fable)实测不可用时,任何 diff 触及 为什么改 — 分诊复核(5594879773):PR #16915 已把闸门改成「无 PASS 在案禁止入队」,而复核没有额度耗尽豁免 ⇒ fable 不可用时 spec 车道会无限期停摆,文本只说「等待是安全态」,没说它是车道级、无自愈出口的;#16611 当时就卡在这里。这一句让席位能据文本判断「该等还是该改道」。 风险与代价(含回滚) — 纯指令文本;不改档位政策、不加标签、不加状态;回滚 = revert 本 PR。一处需要你看: 席位意见 — 接受(契约复审档席内复核)。棘轮 812/60/151 未动;id-lint、frame-sync 绿;控制字节 0; 你要做的 — 合并;或由 os-zhuang / hotlong 批准,本席随即入队。只需看上面那一处配对。 Generated by Claude Code |
|
你不能因为自己当前没有档位去修改卡的状态,完全不合理,去处理其他卡就可以 |
os-zhuang
left a comment
There was a problem hiding this comment.
你不能因为当前没有档位就去改卡的状态,建议直接关闭
|
收到,按原话执行:档位不可用不改卡态——不翻 Generated by Claude Code |
|
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 Generated by Claude Code |
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.mdthat 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 「改走转录核验的复核子代理;标签在复核完成前原样留置,卡在队列外等待是安全态。」:
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」:SKILL.md:643「交付后复核由派发席在席内完成:达档 PM 自审,或派契约复审档复核子任务。」; its one extra token 「当轮」 is exactly the default the two new lines qualify.SKILL.md:646「外部评审链降为可选事后审计,非放行前提。」; the only content lost is the naming of the two chains (分诊定时轮 · 总监席召唤), recoverable fromcore-rules.md:40 / :147; the audit consequence line 「审计 FAIL 按状态机 label-flip 交回派发席补丁轮。」 stays.SKILL.md— 812 → 812 (ceiling 812, headroom 0), 〈入队与落地〉, rewritten in place: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.mdfor 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:640path or declaration limb hit ⇒ no in-seat PASS atCONTRACT_REVIEW_TIERon record ⇒ ⛔ 禁止入队;:643a 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:
pm:blocked+Blocked-by: #ANCHOR+Unlock-action: re-check PR #M, where ANCHOR is a tier-availability card that closes when the tier returns.pm:on-hold+Restart-when: 服役档 = CONTRACT_REVIEW_TIER+Unlock-action: re-check PR #M, recovered by the dailyRestart-when:predicate batch scan. Chosen.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-manualRestart-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:77「Restart-when:判据批扫」);H11inventories important cards parked inpm: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, againstSKILL.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-27restrictsBlocked-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-valueUnlock-action: re-check PR #M(SKILL.md:125「改写完工卡的解锁动作,只认此一值」), so a finished card is never sent back topm:queue(state-machine.md:31「⛔ 永不给完工卡重派 dev」). A adds a second failure surface: a forgotten or duplicated anchor becomesH19/H26noise. 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:
Unlock-action: re-check PR #Mis documented under thepm:blockedheading instate-machine.md:29but defined state-agnostically inSKILL.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 withpm:on-holdon that reading. If the line should staypm: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.contract-review.md:51-56,platform-readings.md:331-343): an at-tier subagent's harness-stampedmodel, neverget_sessionof the default-tier seat (:54).Boundary, unchanged:
H26lists downstreamBlocked-by:dependents of anypm:on-holdtarget as "a block nothing can release"; for a tier-parked card that row is the designed visibility and its remedy is reading the target'sRestart-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:Draft, human merge: not flipped ready, not queued, no auto-merge, no approval.
skip-changeset: nothing under any released package'sfiles[]moves (.claude/**only, fast lane).Ratchet —
pnpm check:pm-skill-ratchetate13b4e0e8, exit 0:Merge-tree probe —
git merge-tree --write-tree 854639b31 e13b4e0e8(origin/main read 06:55Z) → tree72c89bbe; in that treecontract-review.md60 lines / widest 120 B,SKILL.md812 / 342 B (a pre-existing pinned table row),core-rules.md151 / 120 B.origin/mainhas not touched.claude/skills/pm-dispatch/since the branch baseedf59e35.Gate families derived from the tree —
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths; derivation anchored ate13b4e0e8): 16 commands, all run in the foreground with the exit code captured before any pipe;--ranreconciliation: 「16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED」.pnpm check:pm-skill-ratchetpnpm check:pm-skill-id-lintpnpm check:skill-frame-syncpnpm check:nul-bytespnpm check:pm-governed-mergespnpm check:pm-governed-prosepnpm check:doc-authoringnode scripts/pm/check-governed-queue-guard.mjs --self-testnode scripts/check-closing-keyword-parity.mjs(+--self-test)node scripts/check-comment-mask-corpus.mjspnpm check:agent-test-spellingpnpm check:driver-memory-censuspnpm check:refd-timer-probepnpm check:watch-hint-literalpnpm --filter @objectstack/lint run check:doc-formula-expressions@objectstack/formulaand@objectstack/lintnot 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 theHEAD:blob8fe05320;git diff HEADempty after each leg):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 declaresClause-②: no(text-only change on.claude/**, no contract surface), soneeds:contract-reviewis not applied on either carrier.验收备注
H26's header callspm:on-holda state that "can never close"; with an executableRestart-when:predicate (already the shape atSKILL.md:141) a hold closes through the daily scan. Report-only inventory wording, pre-existing; 承接者:无.contract-review.mdline was the only place naming 分诊定时轮 and 总监席召唤 as the external review chain; the rule survives atSKILL.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