Skip to content

docs(pm): runbook step that pastes the decision frame into every dispatch prompt - #15057

Draft
os-steve wants to merge 1 commit into
mainfrom
claude/issue-14869-runbook-frame-paste-step
Draft

docs(pm): runbook step that pastes the decision frame into every dispatch prompt#15057
os-steve wants to merge 1 commit into
mainfrom
claude/issue-14869-runbook-frame-paste-step

Conversation

@os-steve

@os-steve os-steve commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #14869

The internal dispatch runbook constructed the dispatch prompt without ever naming the four-axis decision frame. After the batch-3 item-4 ruling (option B, recorded 2026-09-03 on #14685, comment 5520452691) the frame keeps two copies, both PM-side, and the dev definition expects it to arrive in the prompt from the PM's own copy — .claude/agents/os-dev.md:398-401, verbatim and untranslated:

升级分析的四轴决策框架由派发词携带 —— 派发的 PM 从自己那份副本填入(已发布模板里
rules/dev-template.md{decision_frame} 槽位):每个方案逐轴分析,推荐也按那
些轴给出理由;派发词没带,停下向 PM 索取,⛔ 不自拟一套轴。

That clause is unchanged by this PR — it is quoted here only because the new bullet is the PM-side half it was waiting for. Until now the runbook was an instruction surface promising a behaviour it no longer produced: the failure is loud rather than silent, but it costs one round-trip per dispatch.

The change — one bullet, one file, +4 lines, nothing else

.claude/skills/pm-dispatch/references/dispatch-runbook.md, § 派发词构造细则, inserted into the clause list immediately after the 两份读数 clause (the other "what every brief carries at dispatch time" entry) and before 文件面两句原文:

- **决策框架整段现取现粘、逐单随派发词下发**(维护者 2026-09-03 裁):内部 PM 副本在
  `.claude/skills/pm-dispatch/SKILL.md`,自「每个方案必须沿四条固定评估轴分析…」
  至「推荐意见必须基于这四条轴给出理由…」逐字粘贴,⛔ 不重打、⛔ 不另立第三份副本
  (`check:skill-frame-sync` 拒);派发词记该副本的 commit 与 md5,os-dev 定义没带就停下索取。

Conventions matched against the file it lands in: Chinese prose, English machine identifiers in backticks, ASCII (/)/:/,/; (the file uses ASCII 115/115/96/158/101 times against 9/9/0/0/0 full-width), the ideographic and , the bare U+26D4 no-entry glyph with no variation selector (44 occurrences, 0 VS16), and the (维护者 2026-0x-xx 裁) date-citation form its neighbour at :246 uses. No issue numbers — check:pm-skill-id-lint scans this directory with /#[0-9]{3,}/.

Line widths, bytes: 109 · 100 · 119 · 110, all inside the file's 120-byte budget (its widest pre-existing line is exactly 120).

The frame text is NOT copied — the bullet points at it

Anchor measurement, re-taken on this branch rather than trusted from the brief:

what reading
first anchor .claude/skills/pm-dispatch/SKILL.md:868每个方案必须沿四条固定评估轴分析,这是决策分析的核心原则,不是可选项:
last anchor .claude/skills/pm-dispatch/SKILL.md:885推荐意见必须基于这四条轴给出理由;四轴冲突时如实呈现权衡,
both unique in that file grep -c returns 1 and 1
block md5 sed -n 868,885p .claude/skills/pm-dispatch/SKILL.md | md5sum = b9a0de17880c39e412055e656a953222 (matches the brief's number)

Frame-sync reading — why quoting both anchors in full is safe here, and the caveat that comes with it. The anti-dormancy scan detects a copy by FINGERPRINTS (/fixed axes/i, /固定评估轴/, /条评估轴/, and an English N-axis frame shape) over the population walkMarkdown builds from SCAN_ROOTS = ['.claude', 'skills']. That walk skips SCAN_SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'references']), and this file lives in .claude/skills/pm-dispatch/references/ — so the runbook is not in the scanned population at all and cannot read as a third copy. Recomputed independently before editing: 40 files, runbook absent; the gate's own pass line then reported the same 40. Neither anchor had to be truncated.

That blind spot is larger than this PR and is not this PR's to fix — filed separately and unassigned as #15056 (32 of 72 hand-written markdown files under the two scan roots are invisible, including all 12 published skill reference pages). It is called out here because the two interact: this bullet's first anchor contains 四条固定评估轴, which would match FINGERPRINTS, so whoever narrows that skip set has to distinguish a deliberate anchor pointer from a copy in the same stroke.

Line ratchet — paid from existing headroom, no ceiling edit

lines ceiling headroom
origin/main d5b330dc (git show origin/main:… | wc -l) 276 280 4
this branch cce4a1eb 280 280 0

Gate's own verdict line: ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 280 lines (ceiling 280; headroom 0).

No ceiling was edited, no other bullet was re-wrapped, and no cross-file move was declared or needed — the four lines fit the headroom exactly.

Gates

Family list re-derived from the real change set after the commit, not from the brief: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths passed — the script takes the change set from the merge base itself), which reported change set derived from git — 1 path(s) vs merge base d5b330dc6 and Reconciliation — 12 famil(ies). Identical to the 12 the brief carried; nothing added, nothing dropped.

All twelve run at head cce4a1eb, working tree clean. Each exit code captured by redirect before any pipe; each row quotes the gate's own verdict line, never a bare $?.

family exit the gate's own verdict line
check:pm-skill-ratchet 0 ✓ check-skill-line-ratchet: … dispatch-runbook.md is 280 lines (ceiling 280; headroom 0).
check:skill-frame-sync 0 ✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
check:pm-skill-id-lint 0 ✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
check:doc-authoring 0 ✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
check:agent-test-spelling 0 ✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare … token(s) …
check:pm-governed-merges 0 ✓ check-governed-merges --self-test: 245 assertions …
check:nul-bytes 0 check-nul-bytes: OK (scanned 8180 text file(s) … no raw ASCII control bytes).
check:refd-timer-probe 0 OK check-refd-timer-probe: 5832 source file(s) swept; …
check:watch-hint-literal 0 ✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s) …
check:doc-formula-expressions 0 ✓ check:doc-formula-expressions (field-level …): 14 predicate(s) … judged clean; 6 skipped as undeterminable.
scripts/check-closing-keyword-parity.mjs 0 check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords …).
scripts/check-comment-mask-corpus.mjs 0 ✓ comment-mask corpus sweep …: 5837 files, 0 disagree, 0 unparseable …

One honest note on the tenth row: its first run exited 3, and 3 is this gate's PREREQUISITE NOT MET code, in the gate's own words "Nothing was measured: this gate exited before running a single check, so this result says NOTHING about what it gates." It named two unbuilt workspace packages in turn (@objectstack/formula, then @objectstack/lint); both were built and the gate re-run to the exit 0 above. The exit 3 is recorded as NOT MEASURED, never as a failure.

Beyond the twelve: grep -naP for raw ASCII control bytes over the edited file returned no hits, and the diff is 1 file changed, 4 insertions(+).

Governed surface

.claude/** — opened as a draft, no ready flip, no auto-merge, no reviewers requested from this seat; the dispatching seat reviews in-seat and requests the approvers. skip-changeset applies: nothing here publishes from any released package.


Generated by Claude Code

…atch prompt

The internal dispatch runbook constructed the dispatch prompt without ever
naming the four-axis decision frame. After the batch-3 item-4 ruling (option B,
2026-09-03) the dev definition expects the frame to arrive in the prompt from
the PM's own copy and stops and asks when it does not, so the runbook was an
instruction surface promising a behaviour it no longer produced -- one
round-trip per dispatch until the step is written down.

Adds one bullet to the clause list of the dispatch-prompt construction section,
beside the "two readings handed down at dispatch" clause it belongs with: the
internal-pm frame section is taken fresh and pasted verbatim per card, from
`.claude/skills/pm-dispatch/SKILL.md`, delimited by its two anchor sentences;
never retyped; the brief records the copy's commit and md5; the os-dev
definition stops and asks when the frame is missing.

The frame text itself is NOT copied -- the bullet points at the existing copy by
its anchors, so `check:skill-frame-sync` keeps watching exactly two copies.

Line ratchet: 276 -> 280 of the 280 ceiling; no ceiling edit, no re-wrap, no
cross-file move needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
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