Skip to content

docs(pm): add docs/qa/** to the domain:devx row of the lane table - #17526

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-17459-lane-table-docs-qa-row
Sep 11, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/issue-17459-lane-table-docs-qa-row

Conversation

@os-litant

@os-litant os-litant commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #17459

What changed

One row of the 域车道 table in .claude/skills/pm-dispatch/SKILL.md — line 247, the domain:devx row. Nothing else in the file or the repo moves (git diff --stat f8e57905..HEAD: 1 file, 1 insertion, 1 deletion).

Before (origin/main at f8e57905) — 341 bytes:

| domain:devx | sdui-parser、content/docs/**、apps/docs、.githooks/、docker/README.md、examples/** 仅测试基建面;packages/lint、scripts/(门禁类)、.github/workflows/(接线)三者与 spec 相交面按锚定规则例外归 domain:spec,门禁按 SUBJECT:governed 面归 skills,代码/文档质量归本域 |

After (this PR's head) — 338 bytes:

| domain:devx | sdui-parser、content/docs/**、apps/docs、docs/qa/**、.githooks/、docker/README.md、examples/** 仅测试基建面;packages/lint、scripts/(门禁类)、.github/workflows/(接线)三者按锚定规则例外归 domain:spec,门禁按 SUBJECT:governed 面归 skills,代码/文档质量归本域 |

(Code spans inside the row are flattened above for readability; the diff carries the exact bytes.)

Two deltas inside the one row:

  • added 、docs/qa/** (15 bytes) after apps/docs — the checklist tree now has a lookup, beside the other two docs trees the row already carries.
  • removed 与 spec 相交面 (18 bytes) from the packages/lint / scripts/ / .github/workflows/ clause — the payment. It restated a condition that the retained pointer 按锚定规则例外 already carries: the anchoring rule six lines above the table (line 241, 「唯一例外 packages/lint 等与 spec 相交的 devx 面:围着 spec 契约转的归 domain:spec,余留 devx」) is what makes the routing of those three paths conditional, and the pointer is what binds the row to it. The three paths, the pointer and the domain:spec destination all stay in the row; no fact leaves the table.

Review round 1 corrected the payment: the first cut (commit 5d834e00) paid with the pointer instead and kept the restated condition, which left the row reading as an unconditional routing of every spec-intersecting face of the three to domain:spec — a widening of the anchoring exception under the name of a byte payment. Commit 42521c38 restores the pointer and drops the restatement.

Authority for the routing

The maintainer answered the card's question by acting, not by writing. On #17453 — whose change lands in docs/qa/platform-checklist/areas/approvals.json — the issue events endpoint (/repos/objectstack-ai/objectstack/issues/17453/events, read in this session on 2026-09-10) records:

  • labeled domain:services by os-litant at 2026-09-10T15:27:36Z (the triage seat's judgment call, recorded on the card as such)
  • unlabeled domain:services by hotlong at 2026-09-10T15:28:53Z
  • labeled domain:devx by hotlong at 2026-09-10T15:28:53Z

⇒ docs/qa/** routes on the tree, to domain:devx. The triage seat's comment on the card records the same reading and settles the question: 「⛔ Do not re-open the routing question in the PR — it is answered. The PR writes down the answer.」 This PR writes it down; it does not re-argue the four readers the card enumerated.

Why the row names docs/qa/** and not docs/**

The triage comment suggested phrasing the clause to generalise (all docs/** trees ⇒ domain:devx). Written that way the row would contradict two routings the table already carries: docs/audits/** sits on the catch-all row (无固定归属,按落点分诊), and docs/adr/** is a governed surface (domain:skills via the governed-face definition). The maintainer's act evidences exactly one tree, so the row names that tree; the next docs tree gets its own act and its own clause. If the maintainer wants the general rule instead, that is a one-word edit on this same row plus two edits elsewhere in the table, and a separate decision.

Four-axis note — the one judgement: where the clause sits, and what pays for it

  • 实际业务需求 — a real card was routed by judgment call and re-routed by the maintainer within 8 minutes; the next docs/qa/platform-checklist/** card arrives with the next checklist sweep (checklist-author runs are scheduled work), so the lookup is exercised, not speculative. Measured: docs/qa appeared in no row of the table (grep -n 'docs/qa' SKILL.md = 0 hits on f8e57905).
  • 项目长远合理性 — the answer lives in the table every seat reads, on the row it belongs to, rather than in a label trail; nothing is added to lanes/*.md or CODEOWNERS, so the table stays the one routing authority.
  • 防 AI 犯错 — a lookup that resolves is harder to get wrong than a precedent a seat has to know to search for; the clause is specific (docs/qa/**), so no seat can read it as licence to route docs/adr/** or docs/audits/** by tree. The bytes paid are a restated condition the retained pointer already carries, so the row's routing of the three devx tooling paths stays conditional on the anchoring rule — a payment that had instead removed the pointer would have widened that rule, which is why round 1 swapped it.
  • 创业阶段不扩散 — one clause, +0 lines, −3 bytes on the row, widest row and ceiling unchanged, no generalisation beyond what the maintainer's single act evidences.

Verification

Tree: 42521c38 (this PR's head; every gate below ran on it with a clean working tree — round 1 ran the same 16 families green on 5d834e00, and the whole set was re-run in full on the new head). Every exit code captured by redirect before any pipe; each verdict line is the gate's own.

Ratchet (node scripts/pm/check-skill-line-ratchet.mjs), SKILL.md verdict lines byte-identical to the origin/main baseline (diff of the two greps printed IDENTICAL):

  • ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md: widest table row is 342 bytes (pin 342; headroom 0).
  • ✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0).

Row 247 measured with awk 'NR==247' SKILL.md | tr -d '\n' | wc -c: 341 on origin/main, 338 at head (335 at the round-1 head). The pin's headroom was 1 byte (the widest row is line 245 at 342), so the 15-byte clause could not ride on it; paid by −18 inside the same row. Line count 812 → 812. The committed row is byte-identical to the row the reviewing seat specified (cmp of the two = equal, 338 B).

Derived families (node scripts/pm/dispatch-gates.mjs --commands, derived at 42521c38 from the branch changeset — identical list to round 1; reconciled with --ran: ✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED (a DERIVED zero — all 16 recorded an exit code and none of them is 3).):

command exit verdict line (gate's own, abridged)
node scripts/check-closing-keyword-parity.mjs 0 check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators …)
node scripts/check-closing-keyword-parity.mjs --self-test 0 ✓ check-closing-keyword-parity --self-test: 24 assertions, 5 mutations of the shipped parsers each driven to red.
node scripts/check-comment-mask-corpus.mjs 0 ✓ comment-mask corpus sweep: 6582 files, 0 disagree, 0 unparseable
node scripts/pm/check-governed-queue-guard.mjs --self-test 0 ✓ check-governed-queue-guard self-test: 183 cases pass
pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 ✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 438 files / 1375 TS blocks judged clean by @objectstack/formula. — its prerequisite (@objectstack/formula + @objectstack/lint built) was met under the verify lock (turbo run build --filter=@objectstack/formula --filter=@objectstack/lint, VERDICT command-exit 0); the very first run in round 1 had been exit 3 PREREQUISITE NOT MET (NOT MEASURED, not a finding)
pnpm check:agent-test-spelling 0 ✓ check-agent-test-spelling: 0 violations — 499 file(s) · 7980 bare -- token(s) · 1674 launcher-rooted run(s) · 12 separator(s) JUDGED
pnpm check:doc-authoring 0 ✓ doc authoring guard: sibling-package prose ids hold the baseline — 821 pinned site(s) across 231 file(s) … no growth, no burn-down unrecorded.
pnpm check:driver-memory-census 0 check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live …
pnpm check:nul-bytes 0 check-nul-bytes: OK (scanned 8312 text file(s) … no raw ASCII control bytes). — plus a direct control-byte grep over SKILL.md: 0 hits
pnpm check:pm-governed-merges 0 ✓ check-governed-merges --self-test: 274 assertions …
pnpm check:pm-governed-prose 0 ✓ 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 0 ✓ check-skill-id-lint: 27 file(s) clean
pnpm check:pm-skill-ratchet 0 ✓ check-skill-line-ratchet self-test: 157 cases pass. plus the two SKILL.md verdict lines above
pnpm check:refd-timer-probe 0 OK check-refd-timer-probe: 6577 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.
pnpm check:skill-frame-sync 0 ✓ check-skill-frame-sync: the one declared copy of the decision frame is internally coherent (.claude/skills/pm-dispatch/SKILL.md …)
pnpm check:watch-hint-literal 0 ✓ check-watch-hint-literal: 69 declaration(s) across 4 rostered name(s) …

Path face: node scripts/pm/check-governed-merges.mjs --test .claude/skills/pm-dispatch/SKILL.md → exit 3, ⛔ GOVERNED — a human merge is the review record for this PR (#9495 regime). The dispatch named a --branch mode of this script; it is not on f8e57905 (a grep for the literal --branch in the script returns 0 hits), so the dispatch's own fallback — the --test predicate with the path list — is what ran.

Not owed: no package is touched, so there is no ① build closure and no ② package test/typecheck; the formula + lint build above was a gate prerequisite, not a package under test.

Acceptance notes

  • noted, not filed: references/lanes/devx.md does not mention docs/qa/**. The table is the routing authority and the lane file is read after the table resolves, so nothing is wrong; out of this PR's declared file surface. 承接者: the devx seat, on its next lane-file edit.
  • noted, not filed: .github/CODEOWNERS carries no docs/qa rule (already recorded on the card). The maintainer's act routes on the tree, and CODEOWNERS routes only docs/adr/; nothing to add. Out of the declared file surface. 承接者: none.
  • noted, not filed: the dispatch prompt's check-governed-merges.mjs --branch mode is not landed on f8e57905; the prompt's own fallback was used. Prompt drift, no repo file to change. 承接者: the skills seat's dispatch template.
  • noted, not filed: the triage comment's suggestion to generalise to docs/** was not taken, for the reason in the section above; if the maintainer prefers the general rule, that is a follow-up decision, not a defect. 承接者: the maintainer, at review.

Clause-②: no — instruction text; no accept set or public surface moves.

Changeset: none — .claude/** publishes nothing from any released package; skip-changeset applied.

维护者速读(草稿)

改了什么:pm-dispatch SKILL.md 的域车道表 domain:devx 行加了一个词 docs/qa/**(平台测试清单树),并删掉同一行里一句重复陈述的条件(与 spec 相交面)来付字节账;指向锚定规则的回指 按锚定规则例外 保留,因为那个条件正由它承载。整个文件行数(812)、最宽表行(342 字节)都没有动。

为什么改:#17453 那张卡落在 docs/qa/platform-checklist/**,表里查不到该树,分诊席按「文档跟随它记录的子系统」打了 domain:services,您在 8 分钟后把它改成了 domain:devx。本次改动把您的这个动作写进表里,下一个席位不再重新推导。

风险与代价(含回滚):零运行时影响,只影响分诊席查表;回滚就是 revert 这两个 commit。删掉的只是一句重复陈述的条件,保留的回指 按锚定规则例外 已经承载同一条件(第 241 行「围着 spec 契约转的归 domain:spec,余留 devx」),三个路径的归属和它们的条件都还在表里;第一版曾反过来删掉回指、保留重复条件,那会把这条例外读成无条件归 spec,评审第一轮已纠正。

席位意见:(席位定稿)

你要做的:确认 docs/qa/** ⇒ domain:devx 是您的本意 —— 表里现在写的是这一棵树,没有泛化成 docs/**,因为 docs/audits/**(按落点分诊)和 docs/adr/**(governed 面)各有已定归属。认可即人工合并;想要泛化规则的话请在评审里说一句,那是另一个决定。


Generated by Claude Code

The 域车道 table named docs/qa/** in no row, so a card landing in
docs/qa/platform-checklist/** was routed by judgment call. The maintainer
settled it by acting: on the card that raised it, domain:services was
replaced with domain:devx for a fix in that tree. This writes the answer
into the domain:devx row beside content/docs/** and apps/docs.

The row is metered by the file's max-table-row-bytes pin (342, headroom 0)
and the file sits at its 812-line ceiling, so the 15-byte clause is paid
inside the same row: the back-reference 按锚定规则例外 (21 bytes) is dropped
from the packages/lint / scripts/ / .github/workflows/ clause, whose rule is
stated verbatim six lines above the table. Row width 341 -> 335 bytes; the
file's widest row (342) and line count (812) are unchanged.

Claude-Session: https://claude.ai/code/session_01YKEjmbYNvYWJvWGSWx26zK
Co-authored-by: Claude <noreply@anthropic.com>
… the anchoring pointer

Review round 1: the byte payment in the domain:devx row must keep the
pointer 按锚定规则例外 and drop the restated condition 与 spec 相交面
instead. The pointer is what makes the routing of packages/lint,
scripts/ and .github/workflows/ conditional on the anchoring rule's
qualifier (围着 spec 契约转的归 domain:spec,余留 devx); without it the
row read as an unconditional routing of every spec-intersecting face to
domain:spec, a widening under the name of a byte payment. The condition
is carried by the pointer, so dropping the restatement loses nothing.

Row 247: 335 -> 338 bytes (pin 342); file stays 812/812; widest row 342.

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

Copy link
Copy Markdown
Collaborator Author

维护者速读

改了什么 —— .claude/skills/pm-dispatch/SKILL.md 域车道表 domain:devx 一行(第 247 行)原地改写:在 apps/docs 后加 docs/qa/**;为付字节账,删去同一行里重述的条件「与 spec 相交面」,保留回指「按锚定规则例外」—— 条件本身由第 240 行的锚定规则承载(「围着 spec 契约转的归 domain:spec,余留 devx」)。该行 341 → 338 字节(表行上限 342),文件仍 812/812,棘轮两行读数与 main 一致。

为什么改 —— #17453 落在 docs/qa/platform-checklist/**,表里查不到这棵树,分诊席按「文档跟随它记录的子系统」打了 domain:services,您 8 分钟后改成了 domain:devx(#17453 事件记录,15:28Z)。把您的动作写进表,下一个席位不再重推。没有泛化成 docs/**:docs/audits/**(按落点分诊)和 docs/adr/**(governed 面)各有既定归属。

风险与代价(含回滚) —— 纯指令文本,一行;只影响分诊查表,无运行时面。第一版补丁反过来删了回指、留下重述条件,会把这条例外读成「相交面无条件归 spec」,本席复核第一轮退回,第二个 commit 改正;本席在 head 42521c38 上逐字节比对该行与本席给出的目标行,一致。CI 在 head 上收敛中(21 过 / 15 跳 / 1 在跑,无失败)。回滚 = revert 这两个 commit。

席位意见 —— 通过。受管面(.claude/**):本席不翻 ready、不入队、不批准。

你要做的 —— 一个动作:人工合并本 draft PR(若您更想要 docs/** 的泛化规则,评审里说一句,那是另一个决定)。

skills 席,session session_01YKEjmbYNvYWJvWGSWx26zK,2026-09-10T19:34Z。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review September 11, 2026 06:28
@os-zhuang
os-zhuang enabled auto-merge September 11, 2026 06:28
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 11, 2026
Merged via the queue into main with commit 735a205 Sep 11, 2026
43 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-17459-lane-table-docs-qa-row branch September 11, 2026 06:52
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

Development

Successfully merging this pull request may close these issues.

[finding] the 域车道 table in pm-dispatch SKILL.md has no entry for docs/qa/**, so checklist-area cards are routed by judgment call

2 participants