Skip to content

skills(pm-dispatch): the lane table routes a scripts/ gate three ways by pointer and names every row-less path - #17226

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-17222-lane-table-rowless-paths
Sep 10, 2026
Merged

skills(pm-dispatch): the lane table routes a scripts/ gate three ways by pointer and names every row-less path#17226
os-zhuang merged 1 commit into
mainfrom
claude/issue-17222-lane-table-rowless-paths

Conversation

@os-justin

Copy link
Copy Markdown
Collaborator

Fixes #17222

One governed file, both halves of the card, under the card's own discipline (quoted on #16993 and #17222): 「同一概念两份真理」 is the failure mode — one statement, pointers to it. ⛔ Not a routing dispute: no lane assignment changes. Every edit is a pointer or a data row; no rule text is added, none is restated. Line-neutral: .claude/skills/pm-dispatch/SKILL.md stays at 812/812, every edited table row stays under the 342-byte pin, and the one edited prose line is 119 of 120 bytes.

Half A — a scripts/ gate resolves from the row a reader lands on

domain:devx row (:248) — 311 → 330 bytes (pin 342)

before:

| domain:devx | packages/lint(与 spec 相交的面均按锚定规则的例外切分)、packages/sdui-parser、content/docs/**、apps/docs、scripts/(门禁类;与 domain:skills 的分界按门禁的 SUBJECT:治理 agent 指令面/governed 面的归 skills,治理代码/文档质量的归本域) |

after:

| domain:devx | packages/sdui-parser、content/docs/**、apps/docs;packages/lint、scripts/(门禁类)、.github/workflows/(门禁接线);三者与 spec 相交的面按锚定规则的例外归 domain:spec,门禁再按 SUBJECT:治理 agent 指令面/governed 面的归 skills,治理代码/文档质量的归本域 |

(inline code spans inside the row are shown without their backticks so the quote stays one line)

  • The scripts/ clause no longer presents a two-way split. packages/lint, scripts/(门禁类) and .github/workflows/(门禁接线) share one pointer — 「三者与 spec 相交的面按锚定规则的例外归 domain:spec」 — to the anchoring exception at :241 (「围着 spec 契约转的归 domain:spec,余留 devx」) and, through the domain:spec label, to the spec row's tool-chain clause at :250 (「按锚定规则的例外归本域的工具链」). The three-way answer (spec / skills / devx) is now reachable from this row without carrying :241's 「等」 across two rows.
  • The SUBJECT split between skills and devx keeps its wording byte-for-byte (「治理 agent 指令面/governed 面的归 skills,治理代码/文档质量的归本域」); only its lead-in changed (「门禁再按 SUBJECT」 instead of 「与 domain:skills 的分界按门禁的 SUBJECT」).
  • The list order changed so the three spec-intersecting surfaces are adjacent (one pointer instead of three copies of it); nothing left the row.
  • :240–:241 (pointer targets) and :206 (the single-writer statement — who WRITES the tool chain, a different rule) are untouched.

:628, the ACCEPT path-fork line — 113 → 119 bytes (cap 120)

before:

- 纯代码面(scripts/pm/ 工具、.claude/ hooks/workflows/settings、非 md 产物)⇒ skills 席自审。

after:

- 纯代码面(scripts/pm/、.claude/ hooks/workflows/settings、非 md 产物)⇒ 复核席为 skills 席自审。

  • The line now says in its own words that its arrow names the review seat (复核席), so a grep for scripts/pm no longer reads it as a lane attribution. The two surface spans (scripts/pm/, .claude/) are byte-identical. The word 工具 after scripts/pm/ was dropped to pay for 复核席为 under the 120-byte line cap — the path names the same thing.
  • This line sits inside the check-governed-prose pinned region (:607–:633, from **ACCEPT 之后的路径分叉 to 本段只适用本循环派发的 dev PR); the region still names all five registered surfaces and no **-shaped span was added, so the gate stays green (verdict quoted below). :609/:610 (the governed-surface definition) are untouched.

Half B — every path has a row or a stated non-assignment

domain:skills row (:249) — 253 → 254 bytes

before:

| domain:skills | .claude/skills/**(含本文件)+ skills/**;根 AGENTS.md + 根 CLAUDE.md;governed 面的治理执行文件:.github/CODEOWNERS + SUBJECT 是 governed 面本身的门禁/审计(现为 scripts/pm/check-governed-merges.mjs) |

after:

| domain:skills | governed 面全量(含本文件;统一定义见「governed 面统一定义」行);governed 面的治理执行文件:.github/CODEOWNERS + SUBJECT 是 governed 面本身的门禁/审计(现为 scripts/pm/check-governed-merges.mjs) |

  • The row cites the one definition (:609 「governed 面统一定义:docs/adr/** + .claude/**(全量,含 agents/hooks/settings)+ skills/**」, :610 for AGENTS.md + CLAUDE.md) instead of re-enumerating a subset of it. An ADR edit, and any .claude/** file, now has a row — through the definition, which stays the single statement. The pointer names :609's literal phrase so a grep finds it in one hop.
  • Consequence to state plainly: grep -n docs/adr on SKILL.md still lands on :609 only — by design, the row points rather than re-spells.

(无固定归属,按落点分诊) row (:252) — 184 → 203 bytes

  • docs/audits/** joins as a stated non-assignment. No lane invented: nothing under .claude/** or in AGENTS.md assigns it (the only mentions are tooling paths in scripts/).

domain:cli row (:251) — 262 → 271 bytes

  • qapackages/qa, so the grep speaks. The row already named it; not a routing change.

.github/workflows/ — in the domain:devx row (see the deviation below)

Deviation from dispatch ruling 3(b), declared

The ruling placed .github/workflows/** in the no-fixed-home row as a stated non-assignment, on the premise that no lane statement covers it. Measured on origin/main bccf3111: .claude/skills/pm-dispatch/references/lanes/devx.md:8 — the devx lane's own job description — already states 「scripts/(门禁类)、.github/workflows/(门禁接线)」 as devx scope. A no-fixed-home entry would contradict that maintainer-merged line, which is the 「两份真理」 the card's discipline forbids (the card's own ⚠️ makes the same argument for docs/adr/** against :609). So the devx row mirrors devx.md:8 byte-for-byte into its gate clause instead. This is not a new lane assignment: it is the existing one, made visible where the reader lands, under the same SUBJECT split a scripts/ gate gets — which is the reading the ruling itself anticipated a triage seat would apply, and that per-card SUBJECT call stays triage's. If the seat rules otherwise, the swap is one line: drop 、.github/workflows/(门禁接线) from :248 (row would read 「三者」 → 「二者」, 289 bytes) and append 、.github/workflows/** to :252 (228 bytes).

Ceilings and pins (check-skill-line-ratchet, before → after, both on this branch)

  • lines: 812/812 → 812/812. No line added or deleted (rows and :628 edited in place), so nothing to pay and no paid_by.
  • widest table row: 342 → 342 (the domain:engine row :246, untouched); pin 342 unchanged, headroom 0 before and after.
  • edited rows: :248 311 → 330 · :249 253 → 254 · :251 262 → 271 · :252 184 → 203 (all ≤ 342).
  • non-table lines: every line ≤ 120 bytes; :628 is 119.
  • Mechanism assumption A confirmed by measurement: the pin is over the file's WIDEST row, not per row — :248 grew by 19 bytes with the gate green, and the widest stayed the untouched engine row. Mutation probe in a detached probe worktree at cdefa340 (row :246 widened by one ASCII byte to 343, on-disk anchor grep -c = 1): ✗ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md has a 343-byte table row at L246; the max-table-row-bytes pin is 342. — exit 1; probe worktree removed, main worktree git status --porcelain empty.

Re-check (the card's block, on cdefa340)

  • grep -c "domain:spec" → 5 (was 4: the devx row now names domain:spec as its pointer)
  • grep -c ".github/workflows" → 1 (:248) · grep -c "docs/audits" → 1 (:252) · grep -c "packages/qa" → 1 (:251)
  • grep -n "docs/adr" → :609 only (the skills row points at it; see above)
  • grep -n "scripts/pm" → :206 (single writer, untouched) · :249 (the skills row's named governed-surface gate) · :628 (now the review seat, in its own words) · the rest are command spellings and the 机械守卫索引 table

Gates (every family dispatch-gates.mjs derives for this file, plus the dispatch-named ones; all at cdefa340)

  • pnpm check:pm-skill-ratchet✓ check-skill-line-ratchet self-test: 157 cases pass. · ✓ … SKILL.md: widest table row is 342 bytes (pin 342; headroom 0). · ✓ … SKILL.md is 812 lines (ceiling 812; headroom 0).
  • pnpm check:pm-governed-prose✓ check-governed-prose self-test: 28 cases pass. · ✓ check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces (docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md) and claim no others.
  • pnpm check:pm-skill-id-lint✓ check-skill-id-lint: 26 file(s) clean (pattern /#[0-9]{3,}/g).
  • pnpm check:skill-frame-sync✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
  • pnpm check:skill-frame-freshness✓ … the decision frame in this tree is current with origin/main (fetched just now).
  • pnpm check:pm-half-states✓ check-half-states self-test: 3019 cases pass. · pnpm check:pm-clause2-carriers✓ check-clause2-carriers self-test: 319 cases pass (…) · pnpm check:pm-widening-tells✓ check-widening-tells self-test: 173 cases pass (…) — assumption D holds: no edited line is a pinned string in any of the three (grep of every edited phrase over scripts/ returns nothing).
  • pnpm check:pm-dispatch-gates (run detached, over the 600 s cap) — ✓ dispatch-gates self-test: 1624 cases pass.
  • pnpm check:agent-test-spelling, pnpm check:doc-authoring, pnpm check:pm-governed-merges, node scripts/pm/check-governed-queue-guard.mjs --self-test, pnpm --filter @objectstack/lint run check:doc-formula-expressions (after building @objectstack/formula + @objectstack/lint under the verify lock — the gate refuses on an unbuilt dist), pnpm check:nul-bytes, node scripts/check-closing-keyword-parity.mjs --self-test and the gate, node scripts/check-comment-mask-corpus.mjs, pnpm check:watch-hint-literal, pnpm check:refd-timer-probe, pnpm check:driver-memory-census — all exit 0.
  • Reconciliation: ✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED. (change set derived from the merge base bccf3111: the one file).
  • node scripts/pm/check-governed-queue-guard.mjs (the gate itself) is CI-measured only — it reads the workflow event payload.

core-rules.md twin

references/core-rules.md 〈域车道〉 (:64–:65) carries only the anchoring rule with a pointer to SKILL.md's exception; no sentence changed here has a twin there (each edited phrase grepped over references/ — nothing). Left untouched, as ruling 5 requires.

PR #17220 regions and merge order

PR #17220 (origin/claude/issue-17017-awaiting-maintainer-carrier at af85c612) touches SKILL.md at :108, :128 and :707–:711; this PR touches :248, :249, :251, :252 and :628 — disjoint, not touched. Both merge orders are clean (HEAD cdefa340, origin/main bccf3111):

  • git merge-tree --write-tree origin/main HEAD → exit 0, tree 6463089164df2920162298ab3670d9aa139b6da2
  • git merge-tree --write-tree origin/claude/issue-17017-awaiting-maintainer-carrier HEAD → exit 0, tree d3800a96a05da4381eec04aa133ec6d37ab3617d

Changeset

skip-changeset: .claude/** publishes nothing (a governed, repo-internal agent playbook; no package files[] reaches it). No gate demanded a changeset.

Acceptance notes

维护者速读(草稿)

改了什么:只改一个文件 .claude/skills/pm-dispatch/SKILL.md,五行原地改写、行数不变(812/812)。域车道表里:devx 行的 scripts/ 条从「devx 与 skills 二选一」改成指向锚定规则例外的一句(与 spec 契约相关的门禁归 spec,其余按 SUBJECT 分 skills/devx),并把 .github/workflows/ 照 devx 车道岗位说明原样列入;skills 行改为引用「governed 面统一定义」那一行,不再自抄一份子集(于是 ADR 与整棵 .claude/ 都有了归属);「无固定归属」行加上 docs/audits/**;cli 行把 qa 写全成 packages/qa。复核段的「纯代码面 ⇒ skills 席自审」一行加上「复核席为」三字,说明它讲的是谁复核、不是归哪个车道。

为什么改:分诊席实测,同一目录 scripts/pm/ 在文件里有四处说法互不衔接,而 docs/adr/** 等路径在表里根本没有行;已经造成一张卡分错车道、一张险些分错。修法遵守上一张同类卡定下的纪律:一处陈述、其他地方只做指针,不再多抄一份规则。

风险与代价(含回滚):纯文档指针改动,不动任何门禁脚本、不动锚定规则本身、不改任何既有归属;所有相关门禁本地全绿,行数上限与表格行宽度上限都没抬。唯一需要维护者过目的判断:.github/workflows/ 我按 devx 车道岗位说明列进了 devx 行,而不是派发裁决建议的「无固定归属」行,理由是岗位说明已经这样写了,两处说法不一才是这张卡要消灭的东西;不同意时只需把它从 devx 行挪到「无固定归属」行,一行的事。回滚 = revert 这一个提交。

席位意见:

你要做的:确认 .github/workflows/ 的放行位置后,人工合并本 PR。


Generated by Claude Code

… by pointer and names every row-less path

Half A: the `domain:devx` row's `scripts/` clause no longer presents a two-way
split (devx vs skills by SUBJECT); `packages/lint`, `scripts/` and
`.github/workflows/` share one pointer to the anchoring exception (spec-contract
subject ⇒ `domain:spec`, the spec row's tool-chain clause), then the SUBJECT
split between skills and devx follows. The landing-path line under the ACCEPT
fork says in its own words that it names the REVIEW seat, not the lane.

Half B: the `domain:skills` row cites the governed-surface definition instead of
re-enumerating a subset of it (so `docs/adr/**` and `.claude/**` in full have a
row); `docs/audits/**` joins the no-fixed-home row as a stated non-assignment;
`.github/workflows/` is spelled in the devx row as the devx lane description
already states it; `packages/qa` is spelled as the path in the cli row.

Line-neutral at 812/812; every edited row stays under the 342-byte table-row
pin; the edited landing-path line is 119 of 120 bytes.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoTv7pn338AZ71owsp19gQ
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Sep 9, 2026
@os-justin os-justin added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed documentation Improvements or additions to documentation labels Sep 9, 2026 — with Claude

Copy link
Copy Markdown
Collaborator Author

维护者速读

改了什么 — 只改 PM 派发技能的主文件 .claude/skills/pm-dispatch/SKILL.md,五行原地改写、总行数不变。域车道表里:devx 行的 scripts/ 条从「devx 与 skills 二选一」改成一句指向锚定规则例外的话(和 spec 契约相关的门禁归 spec,其余门禁再按主题分 skills / devx),并把 .github/workflows/ 按 devx 车道岗位说明原样列入;skills 行改为引用「governed 面统一定义」那一行,不再自抄一份子集,于是 ADR 和整棵 .claude/ 都有了归属;「无固定归属」行加上 docs/audits/**;cli 行把 qa 写全成 packages/qa。复核段那句「纯代码面 ⇒ skills 席自审」加了「复核席为」三个字,说明它讲的是谁复核,不是归哪个车道。

为什么改 — 分诊席实测:同一个目录 scripts/pm/ 在这份文件里有四处说法互不衔接,而 docs/adr/**.github/workflows/**docs/audits/** 在表里根本没有行,已经造成一张卡分错车道、一张险些分错。修法沿用上一张同类卡(#16993)定下的纪律:一处陈述,其他地方只做指针,不再多抄一份规则。

风险与代价(含回滚) — 纯指针改动:不动任何门禁脚本、不动锚定规则本身、不改任何既有归属;行数上限与表格行宽上限都没抬,相关门禁本席在该提交上复跑全绿;与另一张等你合并的 PR #17220 在同一文件的不同区域,两种合并顺序都干净。唯一需要你过目的判断:.github/workflows/ 列进了 devx 行,依据是 devx 车道岗位说明(references/lanes/devx.md)本来就这样写,两处说法不一正是这张卡要消灭的;不同意时只需把它挪到「无固定归属」行,一行的事。回滚 = revert 这一个提交。

席位意见 — 通过。dev 对派发裁决的这一处偏离本席接受,理由如上;其余四处逐行核过,与卡上的再检查命令一致。

你要做的 — 确认 .github/workflows/ 放在 devx 行可以,然后人工合并本 PR(受管面,席位不合)。


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-user-decision size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

3 participants