Skip to content

skills(pm-dispatch): a mid-task narrowing names its replacement owner and the moment - #17794

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-17729-narrowing-names-replacement-owner
Sep 12, 2026
Merged

os-zhuang merged 1 commit into
mainfrom
claude/issue-17729-narrowing-names-replacement-owner

Conversation

@claude

@claude claude Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #17729

A mid-task note that narrows a standing clause and names neither who takes the narrowed duty over nor when it acts leaves the dev holding half a contract. The measured instance was a live dual-carrier split that the seat had to repair by hand. This lands the rule in the runbook section where the dispatch-word rules live.

The edit: one clause, riding an existing bullet by density

.claude/skills/pm-dispatch/references/dispatch-runbook.md line 222, inside the in-flight-overlap interception group (lines 220-222).

Before (23 bytes):

- ⛔ 不硬造 diff。

After (119 bytes, cap 120):

- ⛔ 不硬造 diff。中途收窄标准条款须点名替换承接人与时点,缺一 dev 报 blocked 不半执行。

The appended clause is 96 bytes. The file is still 241 lines: no line added, no rule deleted, no re-wrap used as payment, ceiling untouched.

The four elements, mapped to the words

Element Words that carry it
(a) an instruction that narrows a standing contract mid-task 中途收窄标准条款
(b) names the replacement owner 须点名替换承接人
(c) and the moment the replacement acts 与时点
(d) a narrowing naming neither is refused by the dev (report blocked) rather than executed half 缺一 dev 报 blocked 不半执行

标准条款 is the term the file and .claude/agents/os-dev.md already use for the standing clauses (see line 226 「条件性标准条款…」 and line 231 「信封断言本体是 os-dev 标准条款」), so the clause names the same object the contract does.

Why this host

Lines 220-222 are the runbook's one rule group about a note sent to a dev mid-task: the seat intersects each round's newly landed PRs with the in-flight file surfaces and sends a four-sentence warning. Line 222 is that group's tail rule about how the dev must not contort to comply with such a note (do not manufacture a diff). The new clause is the same channel's other failure mode — the note that narrows instead of warning — and the dev-side posture it prescribes (refuse, report blocked) is the same kind of rule as the one already there.

It is also the only bullet in the section that can hold the clause at all. Free bytes re-measured on this branch against the 120-byte convention: line 222 has 97 free; the next largest are line 211 with 70, line 230 with 69, lines 214 and 228 with 63, line 201 with 61. The clause is 96 bytes, so no semantically closer host had room even in principle — the semantic choice and the byte budget point at the same line, and no trade-off had to be made.

Governed verdict

node scripts/pm/check-governed-merges.mjs --test .claude/skills/pm-dispatch/references/dispatch-runbook.md :: exit 3

governed-surface predicate: 1 of 1 path(s) hit the register (5 surfaces, repo-agnostic).
  ⛔  GOVERNED — a human merge is the review record for this PR (#9495 regime).
      .claude/** ×1 — the agent instruction tree (skills, agents, hooks, settings)

This PR stays draft. No seat flips it ready, enqueues it, or arms auto-merge; the maintainer hand-merges after the skills seat's review.

Gates

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths passed: the script derives the change set itself from the merge base) and reconciled with --ran on the final diff at 902f019c:

Run reconciliation — 14 derived, 14 run, 0 NOT-MEASURED, 0 UNRUN.
✓ dispatch-gates --ran: 14 derived famil(ies) accounted for — 14 run, 0 NOT-MEASURED
  (a DERIVED zero — all 14 recorded an exit code and none of them is 3).

All 14 exited 0. The ratchet's own verdict lines:

✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md: widest table row is 0 bytes (pin 0; headroom 0).
✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 241 lines (ceiling 241; headroom 0).

pnpm --filter @objectstack/lint run check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET — @objectstack/formula and @objectstack/lint unbuilt in a fresh worktree; nothing measured). After pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2 under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0), it re-ran :: exit 0.

Control-character self-scan over the changed file (grep -naP over the control ranges): no hits. Repo-wide pnpm lint is CI's run; the narrowed reading here is total — pnpm exec eslint --no-inline-config --format json over the one changed file reports File ignored because no matching configuration was supplied, i.e. the eslint config matches zero of this PR's files, so this diff cannot move any untouched file's verdict.

No changeset: .claude/** is the skip-changeset fast track — nothing in any package's files[] moves.

Acceptance notes

  • noted, not filed: the dispatch word asked for node scripts/pm/dispatch-gates.mjs --commands .claude/skills/pm-dispatch/references/dispatch-runbook.md (with a path); .claude/agents/os-dev.md says to derive without paths so the script reads the real change set from the merge base. The os-dev clause wins per its own conflict rule, and the two agree here anyway (one path, committed). Carrier: the next runbook edit that touches the derivation sentence.

维护者速读(草稿)

改了什么dispatch-runbook.md 〈派发词构造细则〉第 222 行末尾加一句:中途收窄标准条款的指令必须点名替换承接人与时点,缺一由 dev 报 blocked,不半执行。文件仍是 241 行,不动 ceiling,不删任何规则。

为什么改 — 实测事故:座位中途把「挂/清 needs:contract-review」收归自己,却没说另一半由谁、在何时做;dev 已挂了 PR 侧、停下来报了旗(正确行为),卡与 PR 的双载体半态一直活着,直到座位手工补挂。规则把这种半态从「靠 dev 临场判断」变成「派发侧必须写全,否则 dev 拒收」。

风险与代价(含回滚) — 风险是 dev 对一条本来还能推进的收窄指令报 blocked,多一轮往返;代价上限是一轮。回滚成本为零:单行单句,git revert 即回到原句。

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

你要做的 — 这是受管面(.claude/**),按 #9495 规矩由你手工合并;先看上面「四要素对照表」确认这一句确实四件事都说到了,再看措辞是否合你对这份文件语气的要求(一 bullet 一规则、⛔/⇒ 记号、无卡号)。


Generated by Claude Code

… and moment

A dispatch-word note that narrows a standing clause mid-task and names neither
who takes the duty over nor when leaves the dev holding half a contract: the
measured outcome was a live dual-carrier split that a seat had to repair by
hand. The rule rides the in-flight interception bullet by density — the file is
line-ratcheted at its ceiling, so no line is added and none is deleted.

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

claude Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿)

改了什么 — PM 派发技能的派发词细则 references/dispatch-runbook.md 第 222 行「⛔ 不硬造 diff。」后面加一句:「中途收窄标准条款须点名替换承接人与时点,缺一 dev 报 blocked 不半执行。」 —— 席位在任务中途给 dev 发的「这项改由我做」类收窄,必须说清楚谁接、什么时候接;两样都没说的,dev 按不完整报 blocked,不做一半。文件仍 241/241 行,该行 24 → 119 字节(上限 120),不加行、不删规则、不动上限。

为什么改 — 实测事故:#16804 / PR #17725 上席位中途把「挂/清 needs:contract-review」收回给自己,没说另一半谁做、何时做,dev 已挂了 PR 侧、停下来问(做对了),结果卡侧空着,形成 C1 双载体半状态,席位手工补的。这一句让下一次同样的收窄在派发词里就把接手人和时点写全。

风险与代价(含回滚) — 一句话、受管面;14 条派生门禁全绿、棘轮 241/241 绿、受管判定 GOVERNED 是预期。回滚 = revert 本 PR。

席位意见 — 席内按契约复审档复核通过,建议合并。

你要做的 — 受管面:请人工合并 PR #17794(本席不翻 ready、不入队、不挂 auto-merge)。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 12, 2026 06:04
@os-zhuang
os-zhuang enabled auto-merge September 12, 2026 06:04
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 12, 2026
Merged via the queue into main with commit a77b4e9 Sep 12, 2026
35 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-17729-narrowing-names-replacement-owner branch September 12, 2026 06:28
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 17, 2026
…eview to the skills seat (objectstack-ai#17806)

Fixes objectstack-ai#17490

## What changed

One line of `.claude/skills/pm-dispatch/SKILL.md` (the governed ACCEPT
fork, rule ①) is replaced in place. Nothing else moves: same line count,
the four-axis frame block untouched, no reference twin, the tiering
ruling's own text untouched.

| | line 610 | bytes (no newline) |
|:--|:--|--:|
| before (`a77b4e92e`, identical on the dispatch tip `6682c5d8`) | `- ①
复核结论照常写在 issue 上;技能面 PR 的复核席须跑在契约复审档位。` | 96 |
| graded candidate (comment 5624178855, re-measured on the base) | `- ①
复核结论照常写在 issue 上;技能面 PR 须由契约复审档的席复核,档外席交 skills 席。` | 114 |
| **after (this PR)** | `- ① 复核结论照常写在 issue 上;技能面 hunk 须由契约复审档的席复核,档外席先交
skills 席。` | **119** |

Line cap is 120 bytes (`scripts/pm/check-skill-line-ratchet.mjs`, "Why
120 bytes"); 119 is under it. File stays 812 lines, ceiling 812,
headroom 0 — no line added, no rule deleted, no re-wrap, no density
payment.

### The three ruled elements, mapped to the words

The ruled direction is option 3 on the card (5624178855): the seat that
cannot run the tier hands the `skills/**` hunk's review to the skills
seat, which records it on the card before the four-piece terminal fires;
the lane's own review of the code half stands.

| element | words |
|:--|:--|
| (a) the conclusion still goes on the issue | `复核结论照常写在 issue 上` —
unchanged from the old line |
| (b) the review of the `skills/**` hunk runs at the contract-review
tier | `技能面 hunk 须由契约复审档的席复核` — the skills-face hunk must be reviewed by
a seat AT the contract-review tier |
| (c) a seat outside that tier hands that review to the skills seat |
`档外席先交 skills 席` — an out-of-tier seat hands it to the skills seat first
|

Two wording changes against the graded 114 B candidate, both inside the
ruled direction and inside the cap:

- `PR` → `hunk` (+2 B). The ruling hands over the **hunk's** review and
keeps the lane's review of the code half; with `PR` the sentence read as
handing the whole PR review across seats, which contradicts that second
clause. `hunk` is already vocabulary in this skill
(`references/dispatch-runbook.md` lines 101 and 151). For a PR that is
entirely `skills/**`, hunk = PR, so nothing narrows.
- `交` → `先交` (+3 B). The ruling says the handed-off review is recorded
on the card **before the four-piece fires**; `先` carries that ordering,
closing the failure mode where a seat fires the four-piece and hands off
afterwards, leaving the PR at the maintainer with no at-tier read.

Kept from the candidate: `技能面` (the term the old line and line 600's `触
skills/** 的 PR` pairing already use), `契约复审档`, `skills 席`.

### core-rules twin check

`git grep -n '契约复审档位' origin/main --
.claude/skills/pm-dispatch/references/core-rules.md` ⇒ exit 1 (no hit).
A wider probe `git grep -n '复核席\|技能面 PR' origin/main --
.claude/skills/pm-dispatch/references/core-rules.md` ⇒ exit 1 (no hit).
The only tier sentence in core-rules (line 112, `语义面卡恒契约复审档施工,契约卡达档复核归
spec 席`) is about the build tier and the spec seat's clause-② review,
not the governed fork's rule ① — not a twin. `references/core-rules.md`
is untouched.

The phrase `契约复审档位` also appears in `references/contract-review.md` line
57 (`产出裁决的每轮都须读到契约复审档位`) — that is the contract-review reading's own
tier requirement, a different rule; untouched.

### Premise check (all three PM readings held)

1. Line 610 on `6682c5d8` and on the actual base `a77b4e92e`
(origin/main moved by one commit between dispatch and branch cut — PR
objectstack-ai#17794, which touches only `references/dispatch-runbook.md`; `git diff
--stat 6682c5d HEAD -- SKILL.md` is empty) is the 96 B sentence above,
97 B with its newline. Ratchet verdict on the base: `SKILL.md is 812
lines (ceiling 812; headroom 0)`. No open PR touches SKILL.md or
core-rules.md: the 30 most recently updated open PRs (newest at 06:19Z,
i.e. none after the PM's 06:29Z reading) were listed via REST; the two
pm/ci PRs in that list (objectstack-ai#17799, objectstack-ai#17801) were file-listed and touch
`scripts/pm/check-clause2-carriers.mjs` and workflow/script files only.
2. The interim was already executed at tier by the previous skills seat
on card 17134 (PR objectstack-ai#17462); that card was read only, not touched.
3. `node scripts/pm/dispatch-gates.mjs --tier
.claude/skills/pm-dispatch/SKILL.md` prints `Model tier — MANDATORY:
claude-fable-5-1`. This PR was authored at that tier (claude-fable-5-1).

### Governed verdict

`node scripts/pm/check-governed-merges.mjs --test
.claude/skills/pm-dispatch/SKILL.md` ⇒ exit 3: `governed-surface
predicate: 1 of 1 path(s) hit the register (5 surfaces, repo-agnostic).`
/ `⛔ GOVERNED — a human merge is the review record for this PR`. ⇒ draft
at the human terminal; no ready flip, no queue, no auto-merge from any
seat. `skip-changeset` applied additively (`.claude/**` publishes
nothing).

## Verification (final commit `8b7dae6c0`)

Gate set derived, not recalled: `node scripts/pm/dispatch-gates.mjs
--commands --repo objectstack-ai/objectstack` (change set derived
three-dot from the merge base `a77b4e92e`, 1 path) ⇒ 16 commands. All 16
run on `8b7dae6c0` with exit captured before any pipe (`cmd > log 2>&1;
ex=$?`), all exit 0; reconciliation `node scripts/pm/dispatch-gates.mjs
--repo objectstack-ai/objectstack --ran FILE` ⇒ `Run reconciliation — 16
derived, 16 run, 0 NOT-MEASURED, 0 UNRUN.` The same 16 ran once before
the commit on the identical bytes; the command list was byte-identical
pre/post commit.

Verdict lines as printed by the gates on `8b7dae6c0`:

- `✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is
812 lines (ceiling 812; headroom 0).`
- `✓ check-skill-id-lint: 27 file(s) clean (pattern /#[0-9]{3,}/g).`
- `✓ check-skill-frame-sync: the one declared copy of the decision frame
is internally coherent (.claude/skills/pm-dispatch/SKILL.md; no second
copy to compare — …)` — plus the direct proof the block did not move:
`sed -n 734,755p SKILL.md | md5sum` ⇒ `3327d02c56f8a0eca88569dad2270f32`
before and after the edit (the dispatch's expected hash).
- `✓ check-governed-prose: 2 instruction surface(s) name all 5
registered governed surfaces (…) and claim no others.`
- `check-nul-bytes: OK (scanned 8456 text file(s) … no raw ASCII control
bytes).` — plus the manual control-byte self-scan on SKILL.md (`grep
-naP` over the C0/DEL range) ⇒ no hits.
- `pnpm check:pm-governed-merges`, `check-governed-queue-guard
--self-test`, `check-closing-keyword-parity` (+ `--self-test`),
`check-comment-mask-corpus`, `check:agent-test-spelling`,
`check:doc-authoring`, `check:driver-memory-census`,
`check:refd-timer-probe`, `check:watch-hint-literal` — each printed its
own ✓/OK line, exit 0.
- `pnpm --filter @objectstack/lint run check:doc-formula-expressions`:
first run exit 3 `PREREQUISITE NOT MET` (`@objectstack/formula` /
`@objectstack/lint` not built — NOT MEASURED, not a finding). Built both
under the shared verify lock (`os-verify-lock.sh`, `VERDICT command-exit
0`, held 182 s), re-run ⇒ `✓ check:doc-formula-expressions: 22
record-scoped formula example(s) across 438 files / 1374 TS blocks
judged clean`, exit 0; included in the post-commit union above.

On-disk proof of the edit: `grep -cF` of the old line 1 → 0 and of the
new line 0 → 1; `git show HEAD:…SKILL.md | sed -n 610p` prints the new
line. No repo-wide `pnpm lint` run locally (CI-owned); no package
build/test owed — the diff touches no package (no ① closure, no ②).

Not measured locally: CI convergence (owned by the review side).

## Acceptance notes

- noted, not filed: `references/contract-review.md` line 57 uses the
spelling `契约复审档位` for the contract-review reading's own tier, while
SKILL.md line 610 now spells the same tier `契约复审档` (as lines 505–527
do). Both spellings already coexisted on the tip; no gate reads either.
Carrier: whoever next edits contract-review.md; none queued.
- Out of scope, untouched by design: the tiering ruling's text (card
17285 / PR 17294 — those cards remain as they are), card 17134's labels,
the four-axis block (lines 734–755).

## 维护者速读(草稿)

**改了什么**:`.claude/skills/pm-dispatch/SKILL.md` 第 610 行(治理面 ACCEPT
分叉的规则①)原地换了一句话,96 字节变 119 字节,行数 812 不变。旧句要求「技能面 PR
的复核席须跑在契约复审档位」;新句改为「技能面 hunk 须由契约复审档的席复核,档外席先交 skills 席」。

**为什么改**:旧规则①与分档裁决(契约复审档只留给 skills 席、spec 席的条款②复核与维护者召集的
director)构成一对谁都满足不了的矛盾:一个 `domain:cli` 席复核一张顺手修了 `skills/**` 里一行的
PR,被要求跑一个它被禁止跑的档位。这不是边角:「已发布的说法本轮变假就地修、不立卡」这条规则天然会让普通车道的 PR 顺带碰到
`skills/**`。一张 p1(PR objectstack-ai#17462)已经撞上。方向由 skills 席自分诊定为选项
3(5624178855,轮次报告否决窗已过):档外席把 `skills/**` 那一块的复核交给 skills 席,skills
席在四件套之前记到卡上;代码那一半仍由本车道自己复核。

**风险与代价(含回滚)**:每次顺带的 skills 修补多一次跨席交接 —— 几行
hunk、一条评论,不是一张卡。文字层面只动这一行,分档裁决原文、四轴框架块、objectstack-ai#17134
的标签都没碰;`references/core-rules.md` 无孪生句(已 grep 核实),未动。回滚 = revert 这一个
commit,不牵连任何生成物。

**席位意见**:(留空,席位定稿时填)

**你要做的**:读第 610 行这一句,认可则人工直合;不认可则在此 PR 评论里写下你要的措辞,由 skills 席改。

---
_Generated by [Claude
Code](https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK)_

Co-authored-by: Claude <noreply@anthropic.com>
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

2 participants