Skip to content

skills(pm-dispatch): split the entry into SKILL.md + rules/ under #14296 items 1 and 4 (entry 9,708 tokens, package net −21) - #14660

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-14300-pm-dispatch-split
Sep 2, 2026
Merged

skills(pm-dispatch): split the entry into SKILL.md + rules/ under #14296 items 1 and 4 (entry 9,708 tokens, package net −21)#14660
os-zhuang merged 2 commits into
mainfrom
claude/issue-14300-pm-dispatch-split

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes #14300

Round 2 of the skills catalog optimization program #14292 member card for skills/objectstack-pm-dispatch (maintainer mandate 2026-09-02, verbatim: 「审核所有的 skills,进行全面的优化。」). Round 1 (PR #14444, merged 08:57Z) took the diet, 14,549 → 11,567 tokens. This PR is the entry + rules/ split plus the two deferrals the seat's ACCEPT on #14444 recorded (PMD-H-01, the #14229 two-delta sync). Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1 — branch claude/issue-14300-pm-dispatch-split, base ca48cf37, head fef3b449.

Rulings this PR runs on (one line each, verbatim and untranslated)

Files

skills/objectstack-pm-dispatch/SKILL.md (entry, hand-edited), skills/objectstack-pm-dispatch/rules/dev-template.md (new — text moved out of the entry), scripts/check-skills-token-ratchet.mjs (exactly two rows: the new file's row, the entry's re-lock). .claude/skills/pm-dispatch/**, .claude/agents/os-dev.md, CLAUDE.md read as the comparison oracle only; scripts/pm/check-skill-line-ratchet.mjs, generated files, content/docs/releases/** untouched; no other package. Frontmatter untouched ⇒ skills/README.md / content/docs/ai/skills-reference.mdx need no regeneration (check:skill-docs says "Skill docs in sync"). Clause-②: no — protocol text, no platform contract; clause ① applies (a tier-mandated surface) and the skill-face review is the seat's, in-seat. Governed skills/** ⇒ this PR stays DRAFT; review requests are the seat's step.

Token account (convention ceil(utf8 bytes / 4), node scripts/check-skills-token-ratchet.mjs)

file before (origin/main ca48cf37) after (fef3b449) ceiling row
SKILL.md (entry) 11,567 9,708 14,549 → 9,708 (re-locked at the landed count; zero headroom)
rules/dev-template.md 1,838 new row, 1,838 (pinned at the landed count; zero headroom)
package (every file under skills/objectstack-pm-dispatch/; no generated file) 11,567 11,546 −21

Per commit, each droppable on its own: the split commit da02d0c1 lands the package at 11,556 (−11); the sync commit fef3b449 at 11,546 (−10 more). Whole bundle: 157,662 → 157,641; ratcheted subtotal 141,214 / 165,532 → 141,193 / 162,529.

The three conditions, with numbers

Item 4: the entry ends ≤ 10,000 tokens — measured 9,708.

File map (old section → new file, tokens)

old (origin/main) new tokens
## The developer-agent operating template intro + the 4-backtick text fence (:626-799), minus the "When to STOP instead of coding" block rules/dev-template.md — H1 + the same fence with {decision_frame} on the line the block occupied (rules/dev-template.md:99) 1,838 after the sync commit (1,768 as moved)
the "When to STOP instead of coding" block inside that fence (:704-755) — the published-dev copy that check:skill-frame-sync pins to skills/objectstack-pm-dispatch/SKILL.md by file path stays in the entry, in a text fence under the same heading (SKILL.md:620-660; anchors now at :633 "Analyze every option on four fixed axes:" and :654 "Justify your recommendation on all four axes") 633, unchanged
**Report contract.** paragraph stays in the entry (SKILL.md:662-668) — it is the PM's reading of the report, not the dev's 135, unchanged
everything else unchanged in the entry

The frame fence — measured, and what the script would do

scripts/check-skill-frame-sync.mjs COPIES binds published-pm (start "and analyze every option on the four fixed axes below.", binding "recommendation must be justified on … axes") and published-dev (start "Analyze every option on four fixed axes:", binding "Justify your recommendation on … axes") to skills/objectstack-pm-dispatch/SKILL.md by file path. Had the published-dev block moved into rules/ with the template, analyzeCopy() would have read the entry, matched the start anchor 0 times and recorded "could not extract the decision frame: the declaring sentence anchor matched 0 time(s), expected exactly 1" — a hard FAIL (exit 1), not a vacuous pass; the anti-dormancy scan (FINGERPRINTS over .claude and skills, rules/ included) would additionally have flagged rules/dev-template.md as an undeclared copy (/fixed axes/i). check:skill-frame-freshness imports the same COPIES and extractor and would have failed the same way. So both copies stay in the entry (:534 and :633), neither block is edited, and the rules file carries no fingerprint: the sync gate now reports "36 markdown files scanned for undeclared copies" (35 at base — the new file is scanned and clean). Both gates green on every commit.

Per-move / per-deletion 落点 | before | after (keyed by finding id)

id 落点 before → after before after
PMD-B-01 (split) SKILL.md:626-799rules/dev-template.md:1-130 + SKILL.md:620-668 one 2,584-token template section paid in every session the template is loaded when a dispatch is composed; the entry keeps the pointer, the gate-pinned block and the report contract
PMD-B-01 funding (split overhead +77 bytes: rules H1, placeholder line, entry fence, the pointer's link) SKILL.md:382 "- The issue is already claimed; do not touch its assignee." → deleted; SKILL.md:388 "Return ONLY the JSON report defined in the operating procedure." → deleted; template intro sentence "It is written to stand alone: an agent with no prior context and no custom agent type can follow it." → deleted three restatements the dev read twice in one prompt (template rule 2; the template's top paragraph; step 5's "a general-purpose agent with the template is equivalent") the template's own sentences carry each rule once; split commit −11
#14229 delta 1 (verify-lock non-guarantee) rules/dev-template.md:44-50 (resource rule 1) "so memory peaks never stack. Queueing is normal…" — the guarantee list with no non-guarantee, the exact belief the oracle corrects "The lock does not promise an idle machine: it excludes only work routed through it (gate runs, installs and dev servers are not), so wall-clock readings taken under a hold are shared-box readings." (+45)
#14229 delta 2 (ratchet funding discipline) rules/dev-template.md:80-83, after the definition of done no ratchet text in the published template "A size ratchet the project enforces (a line or token ceiling on a file) is paid only by deleting content: a re-wrap is not payment (densifying that adds no content is a repair, not a purchase), and a ceiling is raised only by the maintainer — nothing left to delete ⇒ report "blocked"." (+63)
sync funding SKILL.md:381 "{conventions_file} in that repository is binding — read it before your first edit." → deleted; SKILL.md:383-385 the needs_decision bullet → deleted; :382 "Never merge anything." → deleted; rules/dev-template.md:7-8 "It is parsed mechanically, so the final message is the JSON and nothing else." → deleted; :128 "and HTML comments alike" → deleted; :57-58 "Leftover dependency trees exhaust the container's disk, which fails as confusingly as running out of memory." → deleted five verbatim restatements (the template's binding-file paragraph, the "When to STOP" rule, rule 4, the report block's final-message and HTML-comment rules) and one published-only rationale sentence the oracle's rule 4 does not carry the rule survives in each case; sync commit −10
PMD-H-01 premise false (below)

Rule 4's remaining lines were re-flowed after the deletion (bytes unchanged, 7,352 before and after the re-flow — a re-wrap moves no tokens and pays nothing).

PMD-H-01 — disposition: no stub exists; nothing to delete, no row to drop

Evidence: git ls-tree -r --name-only origin/main -- skills/objectstack-pm-dispatch/ lists exactly SKILL.md; git grep -n "objectstack-pm-dispatch/evals" origin/main returns nothing; CEILINGS in scripts/check-skills-token-ratchet.mjs carries no evals/ row for this package (the audit's package-facts table said the same: "evals/ absent; 8 of 11 published packages have one"). The audit's PMD-H-01 proposed ADDING an evals/README.md (+300, new ceiling); #14296 item 2 = A deletes planned-eval stubs and adds none, which forecloses that addition. Neither a stub to delete (the PR #14585 / #14578 precedent does not apply) nor a real fixture to keep: premise_false: PMD-H-01 — the deferral presumed an evals stub; the package has never had an evals/ directory.

#14229 sync — the two deltas and their oracle lines (.claude/agents/os-dev.md on origin/main, verbatim and untranslated)

  1. Resource rule 1, os-dev.md:85-88: 「同一张清单的非保证:它不保证机器空闲 —— 只排除经这个入口进来的工作,check:* 门禁、install、dev server 不走它,与持锁同核并跑(脚本每次获取与 VERDICT 行同述此界)⇒ 锁下墙钟绝对值一律是共享盒读数,不是安静机器承诺。」 → template resource rule 1 (rules/dev-template.md:47-50).
  2. Standard clauses, os-dev.md:323-327: 「付行数棘轮的唯一合法货币是删内容。 维护者 2026-08-17 裁「⛔ re-wrap(折行合并)不得用作筹行 —— 棘轮治理的是内容体量,行数只是机读代理,新增以删减付账;密度优化仅随净减内容的 PR 顺带」、2026-08-29 裁「筹行(为内容购买行数)⛔ vs 独立密度修复(无内容购买)允许」。分界只问折行有没有为新增内容买行 —— 门禁分不出两种 net-0;⛔ 不买内容的密度修复是修复,不要当筹行拒掉。删不出等量内容 ⇒ 报 blocked,⛔ 不抬 ceiling(人工地板)。」 → one template paragraph after the definition of done (rules/dev-template.md:80-83), carrying the rule without this repo's dates or quoted rulings (the 已发布 skill objectstack-pm-dispatch 仍是两轴决策框架 —— 与 .claude/ 内部三轴(#5130)分叉,且「创业聚焦」轴是否该泛化给第三方项目未定 #5451 route-B convention the published copy follows).

The other three hunks of #14229 (the model-pin comment shrunk to a pointer, the stash mechanism delegated to CLAUDE.md, the footer measurement delegated to AGENTS.md) are internal delegations with no published counterpart — the published template carries no model pin, already states the stash ban with its mechanism (round 1 F-03), and has no footer text — so nothing to sync there.

premise_false

  • PMD-H-01 — the deferral presumed an evals stub; the package has never had an evals/ directory (evidence above).
  • check:doc-links / check:published-readme-links verify the cross-file link — neither gate walks skills/**: check-published-readme-links.mjs sweeps published package READMEs and the spec prompt files; check-doc-anchors.mjs sweeps content/** plus the root README.md / ARCHITECTURE.md; no check:doc-links script exists. The one cross-file link (SKILL.md:622./rules/dev-template.md) was verified by hand: the target exists at that relative path, and the only intra-file anchor (#the-developer-agent-operating-template, SKILL.md:354) still resolves because the heading stays in the entry.
  • check:skill-examples marks travel with their fences — the package has zero os:check marks and zero TypeScript fences (audit package facts), so nothing travelled; the gate is not in this PR's derived family.
  • check:skill-identifier-liveness Leg 2 — re-measured: BINDINGS has no row for this file (8 registered sections, none in skills/objectstack-pm-dispatch/**); the three Leg 1 exemptions (backlogRepo, conventionsFile, routingLabelPrefix) are in the Configuration table, which did not move, and still resolve.
  • check:role-word — 0 occurrences of the word in both files before and after (grep -c = 0; the file is not in the baseline), so the count could not move.

Gates — head fef3b449 (union re-derived AFTER the last move: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, no paths, "gate list derived from the tree of 'objectstack-ai/objectstack' at commit fef3b44"; 25 commands; every exit code captured by redirect before any pipe)

gate exit the gate's own verdict line
node scripts/check-skills-token-ratchet.mjs (+ --self-test) 0 "✓ check-skills-token-ratchet: 32 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted." — rows skills/objectstack-pm-dispatch/SKILL.md 9708 / 9708 (+0), skills/objectstack-pm-dispatch/rules/dev-template.md 1838 / 1838 (+0); self-test "64 cases pass"
pnpm check:skill-frame-sync 0 "✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files · 4 axes: business-need → long-term-soundness → ai-authoring-safety → startup-scope-discipline · binding sentence present in all 4; 4 count mention(s) agree; 36 markdown files scanned for undeclared copies."
pnpm check:skill-frame-freshness (dispatch-named, not in the derived family) 0 "✓ check-skill-frame-freshness: the decision frame in this tree is current with origin/main (fetched just now)."
pnpm check:skill-identifier-liveness 0 "check-skill-identifier-liveness OK — Leg 1: 465 citation(s) over 42 published file(s) checked against 93441 implementation word tokens (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)."
pnpm check:skill-compatibility 0 "✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 79 workspace packages"
pnpm --filter @objectstack/spec run check:skill-docs 0 "✅ Skill docs in sync"
pnpm check:role-word 0 "check-role-word: OK, no new occurrences of the reserved word."
pnpm check:corpus-claim-drift 0 "check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling."
pnpm check:doc-authoring 0 "✓ doc authoring guard: sibling-package prose ids hold the baseline — 831 pinned site(s) across 231 file(s) …"
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 first pass exit 3 "PREREQUISITE NOT MET — the workspace package @objectstack/formula is not built"; after pnpm --filter '@objectstack/lint...' --filter '@objectstack/formula...' run build under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-14300-r2; "VERDICT command-exit 0 · held the lock 130s · waited 406s"): "✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 422 files / 1364 TS blocks judged clean by @objectstack/formula."
pnpm check:pm-governed-merges 0 "✓ check-governed-merges --self-test: 243 assertions …" + "live: the real generator declared 9 output(s) and certified this tree"
pnpm check:pm-dispatch-gates 0 "✓ dispatch-gates self-test: 1240 cases pass."
pnpm check:ratchet-remedy-authority 0 "OK check-ratchet-remedy-authority: 184 scripts swept … 12 mark the expanding remedy ⛔ MAINTAINER-ONLY …"
pnpm check:watch-hint-literal 0 "✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s) …"
node scripts/check-ci-filter-parity.mjs 0 "OK: all 130 declared cross-package glob(s) (92 unique) are covered …"
node scripts/check-cross-package-test-inputs.mjs / pnpm check:cross-package-test-inputs 0 / 0 "OK: 25 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob."
node scripts/check-shard-attestation.mjs 0 "✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s)."
node scripts/pm/bare-root-worklist.mjs --self-test 0 "OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) …"
pnpm check:agent-test-spelling · pnpm check:bash32-floor · pnpm check:cli-command-ids · pnpm check:entry-guard · pnpm check:parse-guard · pnpm check:pnpm-filter-targets 0 each bash32-floor "✓ … 26 tracked shell file(s) … name no bash 4+ construct …"; cli-command-ids "✓ … 315 command-id literal(s) across 112 file(s) … all resolve"; entry-guard "✓ check:entry-guard: 199 scripts/ file(s) …"; parse-guard "✓ check:parse-guard: 198 scripts/ file(s) …"; pnpm-filter-targets "✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) … resolve"
pnpm check:nul-bytes (any edit) 0 "check-nul-bytes: OK (scanned 7996 text file(s) — 7996 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes)."
node scripts/check-empty-changeset.mjs --base origin/main 0 "✓ No empty-frontmatter changeset introduced by this diff (0 declaring changeset(s) added)."

NOT MEASURED: node scripts/check-test-completeness.mjs — exit 3, "PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named" (CI tees the log; by design not measurable here). The derivation printed its stale-tree notice ("1 commit(s) behind origin/main, 1 file(s) it derives from CHANGED") — origin/main moved by one unrelated commit (20b88391) after the branch was cut; neither scripts/check-skills-token-ratchet.mjs nor skills/objectstack-pm-dispatch/** moved on main (git log HEAD..origin/main -- … empty before both pushes), so no merge was needed.

Baseline on the untouched worktree at ca48cf37, before the first move: ratchet "skills/objectstack-pm-dispatch/SKILL.md 11567 / 14549 (-2982)", frame-sync "35 markdown files scanned", liveness "41 published file(s)".

Changeset

skip-changeset: nothing is released by any package — the diff touches skills/** and one root gate script's ceiling rows; scripts/check-empty-changeset.mjs's route for a PR that releases nothing is this label, and it confirms no changeset is added.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…rules/dev-template.md; the gate-pinned decision frame stays in the entry

#14296 item 1 (A) + item 4 (A), under the #14568 = A reading. The
template fence moves verbatim into rules/dev-template.md; the "When to
STOP" block — the published-dev copy that check:skill-frame-sync pins to
SKILL.md by file path — stays in the entry as a fenced block the PM
inserts at the template's {decision_frame} line. Entry 11,567 -> 9,788
tokens; package 11,567 -> 11,556 (-11): the split's structural overhead
(the rules H1, the placeholder line, the entry fence, the pointer's link)
is funded by two dispatch-prompt bullets that restated template rule 2
and the template's top paragraph verbatim, and by the template intro's
stand-alone sentence, which step 5 already states. Ratchet rows: the new
file pinned at 1,768 (its landed count); the entry re-locked at 9,788.
No other row changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ent template — the verify-lock non-guarantee and the ratchet funding discipline

The follow-up sync PR #14444 recorded, from .claude/agents/os-dev.md on
origin/main: (1) resource rule 1 now states the lock's non-guarantee —
it does not promise an idle machine, only excludes work routed through it,
so wall-clock readings under a hold are shared-box readings; (2) a size
ratchet is paid only by deleting content — a re-wrap is not payment, a
densification that adds nothing is a repair, a ceiling is raised only by
the maintainer, nothing left to delete means "blocked". Additions +108
tokens, funded in the same package: three dispatch-prompt non-negotiables
that restated the template's binding-file paragraph, the "When to STOP"
rule and rule 4 verbatim; the template's top-paragraph restatement of the
final-message rule; the sanitizer trap's HTML-comment clause (stated at
the report block); and rule 4's published-only rationale sentence about
disk exhaustion, which the oracle does not carry. Package 11,556 ->
11,546 (-10 for this commit, -21 against main). Ratchet rows re-pinned at
the landed counts: entry 9,708, rules/dev-template.md 1,838.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
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 skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants