Skip to content

pm-dispatch: a triage fold proposal binds only before any named card has an open PR; a foreseen follow-up is a card - #21676

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-21467-fold-proposal-and-uncarded-follow-up
Oct 4, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-21467-fold-proposal-and-uncarded-follow-up

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #21467
Clause-②: no

Two protocol lines in the execution seat's playbook, as the card's triage grade directs (comment 5962064937). Opened as a draft that is red on check:pm-skill-ratchet: the file sits at its line ceiling, so the seat has to pick how the two lines are paid before this can land. See "Open: the line ceiling" below.

What changed

.claude/skills/pm-dispatch/references/execution-duties.md, section 〈候选与批次〉. Two lines inserted; no other line moved or changed.

line text bytes
34 - 分诊折叠提议仅是建议,点名各卡皆无 open PR 才有效;否则各卡各自落地,拒折理由记一行。 119
43 - 分诊预见的后续工作是一张卡,触发条件落地时立卡;⛔ 分诊一句话永不授权无卡编辑。 116

How each clause of the direction maps to the text:

  • Fold. "advisory" maps to 仅是建议. "binds only while none of the cards it names has an open PR" maps to 点名各卡皆无 open PR 才有效. "once one does, each card lands on its own" maps to 否则各卡各自落地. "the execution seat records the decline in one line" maps to 拒折理由记一行.
  • Follow-up. "a follow-up that a grade foresees is a card, filed when its trigger lands" maps to 分诊预见的后续工作是一张卡,触发条件落地时立卡. "a triage line never authorises an edit without a card" maps to ⛔ 分诊一句话永不授权无卡编辑.

Why both lines are in 〈候选与批次〉:

  • The direction says "the seat picks the section", singular, so both lines go into one section.
  • The fold decision is made in this section: family dispatch, the five admission gates and the fold-or-serial answer are lines 27 to 33. Line 33 also names where that answer is written (the serial-queue entry and/or the chain-head claim), so the one-line decline goes there too. Line 34 sits directly under it.
  • This section also decides what counts as a card before anything is claimed. Line 43 sits under the rules for work derived from in-flight cards (lines 40 to 42: in-scope work becomes a sub-issue, and an escalated card says which half it carries).
  • The dispatch suggested putting the follow-up line near the claim rules (〈认领〉). Its ⛔ half would read the same there. I did not take that suggestion because the direction names a single section.

Reading 1: placement and size

  • The new lines are 34 and 43 (numbered after the insert). The file goes from 183 to 185 lines (+2 / -0). git diff --stat origin/main...HEAD shows 1 file changed, 2 insertions(+).
  • Both lines are under the ratchet's 120-byte line cap (119 B and 116 B). Neither cites an issue or PR number.

Reading 2: the two pm-skill gates, at head 0583520

pnpm check:pm-skill-id-lint, exit 0:

✓ check-skill-id-lint self-test: 14 cases pass.
✓ check-skill-id-lint: 34 file(s) clean (pattern /#[0-9]{3,}/g).

pnpm check:pm-skill-ratchet, exit 1. Its self-test passes (234 checks); the failing line from the run is:

✗ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/execution-duties.md is 185 lines; the ratchet ceiling is 183. Keep the surface compressed: principles in SKILL.md, on-demand detail in .claude/skills/pm-dispatch/references/ — provenance is one line, stories live on cards, not in operational text. Raising a ceiling requires a maintainer ruling quoted in the PR.

That is the run's only failure. Neither new line trips the max-line-length rule.

Open: the line ceiling

The dispatch assumed check:pm-skill-ratchet only measures SKILL.md. That turned out to be wrong. The CEILINGS map in scripts/pm/check-skill-line-ratchet.mjs lists references/execution-duties.md at 183 lines with zero headroom, and the gate's own message says a raise needs a maintainer ruling quoted in the PR. So any net added line turns Lint & Repo Gates red.

This PR does neither of the things that would fix it. It does not raise the ceiling: scripts/** is outside the declared file surface, and the dev contract forbids raising it. It does not delete other lines either: the dispatch fenced every other line. The seat has two options:

  • A: a ruled raise from 183 to 185. Quote a maintainer ruling in this PR body and edit the one CEILINGS row. Every existing line stays where it is.
  • B: pay in place, net 0. Delete two lines whose content already reaches the same reader by another route:
    • Line 60, - 释放是显式动作:让卡离手者同笔清 assignee + `Release:` 行(会话/因/去向);下一任重新认领。 The same rule appears in references/state-machine.md line 41 (same fields, same same-write rule), in the assignee row of SKILL.md 〈状态模型〉 (离手恒走释放), and in the claim paragraph of AGENTS.md ("Release is an explicit act").
    • Line 165, - 复位走梯度,每次比上一次更具体;第三次停摆判 unreliable,按接手协议重派。 The same rule appears in references/dispatch-runbook.md 〈停摆复位梯度〉 (梯度逐级; ③ 第三次停摆判 unreliable,按接手协议重派到该分支). A seat already has to open that section to get the 姿态句 text that line 164 tells it to send.

The report comment on the card compares A and B along the four axes.

Gates, at head 0583520 (after merging origin/main at 417443e)

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, run with no paths, derived 17 commands. That is the same list as the dispatch. I also ran pnpm check:pm-settings-deny-roster, because its roster lives under .claude. Every command went through scripts/pm/os-verify-lock.sh, and each exit code was captured before any pipe. doc-formula-expressions first refused with exit 3 (PREREQUISITE NOT MET). I built its prerequisites with turbo run build --filter=@objectstack/formula --filter=@objectstack/lint (exit 0) and re-ran it.

exit command
0 node scripts/check-closing-keyword-parity.mjs
0 node scripts/check-closing-keyword-parity.mjs --self-test
0 node scripts/check-comment-mask-corpus.mjs
0 node scripts/pm/check-harness-current.mjs --self-test
0 pnpm --filter @objectstack/lint run check:doc-formula-expressions
0 pnpm check:agent-test-spelling
0 pnpm check:cross-package-test-inputs
0 pnpm check:doc-authoring
0 pnpm check:driver-memory-census
0 pnpm check:gitlink-declared
0 pnpm check:nul-bytes
0 pnpm check:pm-governed-merges
0 pnpm check:pm-skill-id-lint
1 pnpm check:pm-skill-ratchet
0 pnpm check:refd-timer-probe
0 pnpm check:skill-frame-sync
0 pnpm check:watch-hint-literal
0 pnpm check:pm-settings-deny-roster

node scripts/pm/dispatch-gates.mjs --ran: ✓ dispatch-gates --ran: 17 derived famil(ies) accounted for — 17 run, 0 NOT-MEASURED (a DERIVED zero — all 17 recorded an exit code and none of them is 3).

Left to CI and not measured here: the type-check lanes, and the wide-population and roster families that dispatch-gates lists outside its derived set. This diff touches no TypeScript and no package.

No changeset: .claude/** publishes nothing, so skip-changeset applies.

Acceptance notes

  • One dispatch assumption turned out to be false: execution-duties.md is under the line ratchet at 183 lines with zero headroom. Details are in "Open: the line ceiling".
  • The two overlaps named in option B (lines 60 and 165) are density observations, not defects. They are noted here and not filed. Carrier: the seat, if it picks B; otherwise none.
  • The ratchet also printed a hint unrelated to this diff: .claude/skills/spec-property-retirement/SKILL.md has table-row pin headroom 2 ("lower the pin to 324"). Noted, not filed. Carrier: none.
  • The first gate derivation read a tree two commits behind origin/main (it flagged STALE TREE because an unrelated baseline JSON had changed). I merged origin/main at 417443e and re-ran every gate on the merged head.
  • The follow-up line is not where the dispatch suggested (〈认领〉). The reason is under "What changed".

维护者速读(草稿)

  • 改了什么:在执行席手册 execution-duties.md 的〈候选与批次〉加两行规则。第一行:分诊提出的"把几张卡并进一个 PR"只是建议,只要其中任一张已经开了 PR,就各卡各自落地,执行席记一行拒绝理由。第二行:分诊预见的后续工作必须是一张卡,等触发条件落地时再立卡;分诊的一句话不能授权任何无卡的改动。
  • 为什么改:分诊曾在同一张卡上同时给出这两种指示,执行席当时只能凭判断拒绝。协议里没有对应规则,下一个席位可能做出相反判断,例如重开已验收的 PR,或者做一次没有认领、没有文件面、没有验收锚点的改动。
  • 风险与代价(含回滚):纯协议文本,不加门禁,不影响运行时。代价是该文件从 183 行变成 185 行,超出行数棘轮上限(183,余量 0),所以本 PR 目前 check:pm-skill-ratchet 是红的。需要在"维护者裁决抬上限"和"删两行重复规则抵账"之间选一个。回滚方式:revert 本 PR。
  • 席位意见:
  • 你要做的:席位选 A(抬上限)时,需要你给一句裁决原话;选 B 时你不用做任何事。

Generated by Claude Code

claude added 2 commits October 4, 2026 02:30
…has an open PR; a foreseen follow-up is a card

Two protocol lines in the execution seat's candidates-and-batch section.
A triage fold proposal is advisory and is in force only while none of the
cards it names has an open PR; otherwise each card lands on its own and the
seat records the decline in one line. A follow-up a grade foresees is a
card, filed when its trigger lands; a triage line never authorises an edit
without a card.

Claude-Session: https://claude.ai/code/session_01CB6W87z22K2yjUCDyVrJRk
Co-authored-by: Claude <noreply@anthropic.com>
…ed rules, net 0 against the execution-duties ceiling

The release line restates references/state-machine.md (the releaser row)
and the stall-reset gradient line restates the dispatch runbook's stall
reset section; both owning copies keep their full text and stay on the
reader's path. The file returns to its ceiling of 183 lines; no ceiling
moves.

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

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: c3020ab1f3c6cceadd6dc0bcf93c8ebdb1593df8
Local-runs: probe — node scripts/pm/check-skill-line-ratchet.mjs and node scripts/pm/check-skill-id-lint.mjs run once each in a detached read-only worktree at this head, so the ratchet reading in ③ is this seat's own; nothing built, nothing else run.

Read-only shape otherwise: the diff against the merge base 417443e, card #21467 with every comment (the triage direction, the first dev report, the seat's amendment 5976088949), the owning copies of the two deleted lines on origin/main, and this head's check-runs. Reviewed by the dispatch seat in seat (served tier equals the constant's value, read from get_session). Review face: .claude/skills/**, harness-loaded protocol text (Tier S). Readings taken at 2026-10-04T04:04Z.

① Derived judgments

  • Accept set: unchanged. Protocol prose in one per-fire references file (.claude/skills/pm-dispatch/references/execution-duties.md, +2/−2); no gate, script, schema or runtime behaviour moves. Clause-②: no holds. ⛔ No new gate, as the direction required.
  • The direction's two sentences, each read by this seat off the diff, both in 〈候选与批次〉: the fold line (after the fold-or-serial answer line) says a triage fold proposal is advisory, holds only while none of the named cards has an open PR, and otherwise each card lands on its own with the decline recorded in one line; the follow-up line (after the escalated-card line) says a follow-up a grade foresees is a card filed when its trigger lands, and ⛔ a triage line never authorises an edit without a card. Both are self-contained rules citing no card number (check-skill-id-lint: 34 files clean, this seat's own run).
  • The payment, as the seat ruled on the card (5976088949): the two deleted lines are restatements whose owning copies stay on the reading path — the release line's twin is references/state-machine.md (the 释放者 row, same fields, same same-write rule) with the per-fire mention kept in SKILL.md 〈状态模型〉; the stall-gradient line's twin is references/dispatch-runbook.md 〈停摆复位梯度〉, which the stall path of the surrounding lines already sends the seat to. Neither line landed under a maintainer-ruled raise of this file (both arrived with the per-phase split that set its ceiling), so the ruled-clause precedent is untouched. The optional pointer on the SendMessage line was not added; that line stands as it was.
  • Line reading: 183 → 183 (the seat's own count on the head blob); the branch carries a merge of origin/main (a merge commit, no rewrite) and the patch commit on top.

② Semver level

  • No released package publishes from this diff (.claude/** ships nowhere); no changeset owed; skip-changeset is the correct declaration. No ADR-0087 disposition applies.

③ Boundary flags

  • Dev flags: the first report's open_questions[0] (how to pay the ceiling) is answered by the seat's amendment and closed by this head; no second report exists: the dev subagent was terminated by the platform's usage wall after pushing the patch commit, so this seat reads the patch head directly under the direct-acceptance fallback (draft PR present, CI all green on the head, the subagent confirmed dead, the report not delivered) with no reduction of the review criteria. out_of_scope_findings: the two density observations are consumed by this very patch; the spec-property-retirement table-row pin hint is noted, not a card.
  • Ratchet, this seat's own run at the head: every .claude/skills/** entry within its ceiling, execution-duties.md at 183 of 183 (headroom 0 as before); check-skill-id-lint clean.
  • Deviation read: the first round's placement choice (both lines in one section, the direction's "the section" read as singular) and the 维护者速读 section kept per os-dev.md — recorded, no action; mcp_calls 0; api_writes 4 over 3 dispatches in the first round plus one git push for the patch, as the thread shows; the first report comment 5976067948 is present and parses.
  • Check-runs on this head at this write: 17 success, 9 skipped, none in progress — the enqueue gate reads them at landing, not this record.

Implemented-by: claude/issue-21467-fold-proposal-and-uncarded-follow-up
Reviewed-by: session_01CB6W87z22K2yjUCDyVrJRk

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 4, 2026 04:05
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 4, 2026 04:06
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit 7d07814 Oct 4, 2026
28 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-21467-fold-proposal-and-uncarded-follow-up branch October 4, 2026 04:33
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/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants