Skip to content

pm-dispatch: a published schema, skill or ADR PR owes a full review — item ④ design judgment in the contract-review record, brief and rule - #26514

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-osntoo
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-osntoo

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Warren · project thread
Fixes #25765
Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:契约复核在 ①②③ 之外加第 ④ 项「设计判断」:凡 PR 已提交树碰到已发布 schema(packages/spec/src/** 非测试)、skills/** 与 .claude/skills/**、docs/adr/** 三面,席位 ACCEPT 前欠的达档复核就是完整复核 —— 逐个面文件判改动对它所引的代码与验收场景是否成立(ADR 另判首个消费者与执行计划),只审面文件、被引代码读而不审,由起草者之外的 agent 在契约档跑,每个实质 head 一轮,只落发现的 commit 由同一复核者 delta 复核,无 must-fix 即止。记录仍是同一条 ## Contract review 评论(多一个 ④ 节,⛔ 不另开第二条记录);--template 打出 ④ 节与说明,--brief-template 打出对抗性的 ④ 指令与「只审面文件」规则。
  • 为什么改:项目负责人 2026-10-25 下令 spec、skills、ADR 的改动都要在契约档做完整复核,10:20Z 补充「只针对 PR 中的重要文件」(原话逐字在卡 pm-dispatch review: a PR touching published spec, skills or docs/adr/** owes an independent full review at CONTRACT_REVIEW_TIER before the seat's ACCEPT, not only the contract review #25765 正文与评论 6396446237,本文不改写)。卡上实测:一张 ADR PR 两次契约复核 PASS 之后,独立完整复核仍找出三处设计缺陷,全部被负责人采纳 —— 契约复核读的是 diff 对裁决,从不问设计对首个消费者成不成立。
  • 风险与回滚:只改 .claude/skills/pm-dispatch/ 两个文件与 scripts/pm/record-recognisers.mjs;无新门禁、无发布面、无 changeset。行数 49→55(上限 60)、319→319(上限 319,同行改写);脚本自测 201→215 例。风险在成本:每张三面 PR 多一轮达档复核(卡上实测每轮 10–18 分钟);以及 ④ 只挂 schema 与 governed 两面、收窄面不挂,若负责人要把收窄面也纳入需另下令。回滚 = revert 本 PR。
  • 先看:① references/contract-review.md 第 29–32 行(④ 定义、只审面文件、cadence)与第 40 行(独立性);② scripts/pm/record-recognisers.mjs contractReviewBriefLines 的两处 ④ 段;③ SKILL.md 第 190 行指针行的后半句。
  • 两分钟验证:node scripts/pm/record-recognisers.mjs --brief-template | grep -n ④ 看到「④ judges the hits files ONLY」与「④ Design judgment」两段;node scripts/pm/record-recognisers.mjs --brief-template --face narrowing | grep -c ④ 打印 0;pnpm check:pm-record-recognisers 打印 215 cases pass。
  • 需要你做的:无,席位落地(Tier S:.claude/** + scripts/pm/**,契约复核 PASS 与席位 ACCEPT 后由席位 ready → 入队)。

What changes

Items 1–6 of the card (「What to change」 1–4 in the body, 5–6 in comment 6396446237), as one PR of three files. The tier is spelled everywhere by its constant name CONTRACT_REVIEW_TIER.

Faces — measured, nothing added

The card asks whether skills/** and docs/adr/** already fall under SKILL.md's governed-rules-text definition. They do: SKILL.md 〈路径分叉〉 「governed 面统一定义」 lists docs/adr/** + .claude/**(全量) + skills/** + docs/NORTH-STAR.md + .github/workflows/**, and the rules face in record-recognisers.mjs reads the governed register (governedPathsIn). The published-schema face is packages/spec/src/** minus test files (SUSPECT_TIER_GLOBS). Read on origin/main at 00a4593a with node scripts/pm/record-recognisers.mjs --template --paths PATH:

path Served-tier: Scope: hit
docs/adr/0141-x.md CONTRACT_REVIEW_TIER yes (rules face)
skills/objectstack-data/SKILL.md CONTRACT_REVIEW_TIER yes (rules face)
.claude/skills/pm-dispatch/SKILL.md CONTRACT_REVIEW_TIER yes (rules face)
packages/spec/src/data/x.zod.ts CONTRACT_REVIEW_TIER yes (schema face)
packages/spec/src/data/x.test.ts TIER_DEFAULT no

So all three surfaces of the order are the schema face and the rules face already; this PR adds no face and edits no definition. It adds the depth (item ④), the scope of ④ (the hits files only, the cited code read to judge them), the cadence and the independence clause, on those two faces. The narrowing face (at tier, but by construction free of schema and governed paths) and the declaration face carry no ④.

.claude/skills/pm-dispatch/references/contract-review.md — 49 → 55 lines (ceiling 60)

Record shape, before (one line):

- 同形 = `## Contract review` 题头、所审 head sha 独占码段、①②③ 逐项、独立性对、PASS/FAIL。

After (two lines):

- 同形 = `## Contract review` 题头、head sha 独占码段、①②③ 逐项(schema/governed 两面加 ④)、
  独立性对、PASS/FAIL。

Added after the ② ③ definition line (four lines: ④'s definition and scope, then cadence):

- ④ 设计判断只欠 schema 与 governed 规则文本两面,spec、skills、ADR 皆已在内 ⛔ 不另立面:
  逐 `hits` 文件判改动对所引代码与验收场景是否成立,ADR 另判首个消费者与执行计划;
  被引代码读而不审;①–④ 合称完整复核,余面同形无 ④,⛔ 无第二条记录。
- 实质 head 各欠一轮完整复核;只落发现的 commit 由同一复核者 delta 复核;无 must-fix 即止。

Added after the 独立性对 line (one line — independence):

- ④ 恒由起草者之外的 agent 达档跑,起草已达档不免;喂入同上,⛔ 不喂起草者的结论。

The existing scope rule (混合 diff 的达档复核范围 = reviewFace 的 hits 路径 + 其 hunk 所断言的文件(读被引代码)) is the surface-file rule the owner refined the order with; ④ restates it as 「逐 hits 文件判 … 被引代码读而不审」 and the remainder stays the lane seat's ACCEPT (unchanged line). The regeneration / prose-only head-move exception is unchanged: those are not substantive heads. Every line ≤ 120 bytes (longest new line 116).

.claude/skills/pm-dispatch/SKILL.md — 319 → 319 lines (ceiling 319, headroom 0)

One line reworded, the ACCEPT pointer line in 〈路径分叉〉. Its first half — the pointer format 指针 ACCEPT → PR #n comment ID (the placeholder for the comment id is written in angle brackets in the file; spelled out here so the body sanitizer leaves it alone) — is unchanged. The second half, after the ;:

Before:

技能面 hunk 复核随面定档:席未达档起隔离达档复核。

After:

受管/spec 面欠完整复核 ①–④,席未达档起隔离达档复核。

111 → 118 bytes. The retired words 「随面定档」 (the tier follows the face) remain stated in contract-review.md 「档随面定」; the SKILL.md line now names what the governed and published-schema faces owe (the full review ①–④) and who runs it when the seat is below tier.

scripts/pm/record-recognisers.mjs — 2054 → 2134 lines

  • REVIEW_FACES gains fullReview (true on schema and rules, false on narrowing and declaration); recordCarriesDesignJudgment(face, tierName) reads it (a null face is the bare template, their tier).
  • contractReviewRecordLines takes an optional faceId and prints the fourth section; contractReviewTemplateLines passes the face through and gains a ④ note; contractReviewBriefLines gains the ④ instruction and the surface-file scope rule.

--template, fenced record after (the bare template, --face schema, --face rules, --paths over a mixed list):

### ③ Boundary flags

### ④ Design judgment

Implemented-by: `claude/issue-NNNN-slug`

--template, note added after the Scope note:

  · ④ Design judgment  on the schema and rules faces only — the published spec, skills and ADR surfaces the
                    full-review order names; the narrowing and declaration faces carry no ④. For each `hits`
                    file: does the change hold against the code it cites and the scenario it is accepted
                    against — an ADR against its first consumer and its execution plan? The cited code is
                    READ to judge it, never reviewed; a must-fix found here is a FAIL like any other.

--brief-template, scope rule added after the ACCEPT at TIER_DEFAULT line:

  ④ judges the `hits` files ONLY: lockfiles, generated output, changesets and prose elsewhere in the PR are
  not reviewed; the cited code is READ to judge them, never reviewed.

--brief-template, judge item added after ③:

  ④ Design judgment — for EVERY `hits` file: does the change hold against the code it cites and the
     scenario it is accepted against — an ADR against its first consumer and its execution plan? Read the
     cited code in the live tree and try to break the design; name each finding must-fix or should-fix.
     A must-fix is a FAIL. ⛔ Judge the tree, never the PR body's account of it.

--face narrowing and --face declaration print none of the four blocks (the ④ note in the template's calibration text names them as faces that carry no ④).

Self-test: 14 pins added (8 in the template battery, 6 in the brief battery), floors raised 19 → 27 and 10 → 16 so a pin that stops registering reds; the battery roster count (12) is unchanged. The pins cover: ④ right after ③ in the bare record and one record shape (four ### headings, never a second record); schema, rules and --paths print it; narrowing and declaration do not (fenced record checked, not the calibration text); the face table marks exactly schema,rules; an unknown faceId is refused; a record carrying ④ still reads FOUND and its tier STANDS (④ is prose to every reader); the note text; the brief's ④ instruction, its surface-file rule, per face; the brief stays free of angle brackets, model identifiers and digit-shaped card numbers.

File Before After Ceiling
.claude/skills/pm-dispatch/references/contract-review.md 49 55 60 (headroom 5)
.claude/skills/pm-dispatch/SKILL.md 319 319 319 (headroom 0)
scripts/pm/record-recognisers.mjs 2054 2134 not ratcheted

Why

The owner's order: a change on a published schema, a skill or an ADR owes a full review by an independent agent at the contract tier before the seat's ACCEPT — the floor, not a replacement for who drafts (the sibling card #25729 is untouched). Measured on the card: a contract review reads the diff against its order and never asks whether the design works for its first consumer; that question is what ④ makes mandatory. Triage (comment 6431838043) fixed the carrier: contract-review.md + the brief template, ⛔ no new gate — the full review is a record the seat reads, like the contract review.

Tests

  • pnpm check:pm-record-recognisers (the script's own suite, run by lint.yml line 1165): ✓ record-recognisers self-test: 215 cases pass — on origin/main at 00a4593a it prints 201; +14 pins.
  • node scripts/pm/check-governed-queue-guard.mjs --self-test (loads this file through the real lazy import and drives every queue state with the printed record): exit 0.
  • npx eslint scripts/pm/record-recognisers.mjs: exit 0 (the repo-wide pnpm lint is CI's run).
  • No ablation: the diff changes printed text and a face flag, both pinned by the self-test's positive and negative cases (narrowing / declaration carry no ④); no behaviour outside the self-test's reach changed.

Acceptance notes

  • Carrier: item ④ in the ONE ## Contract review record (the seat's recommendation on the card), not a second record — contract-review.md says 「⛔ 无第二条记录」 and the self-test pins four ### headings and one record shape.
  • ④ on the narrowing face: no. The order names published spec, skills and ADRs; the narrowing face exists only when the diff has no schema and no governed path. Extending ④ there would widen the order; a one-flag change (fullReview: true on narrowing) if the owner wants it.
  • Independence was already the Implemented-by:/Reviewed-by: pair plus the feeding rule; the new line adds what the card asks: a change drafted at the contract tier still owes the review, by an agent other than its drafter, never fed the drafter's conclusions.
  • Cadence is new text: one full review per substantive head; a commit that only applies the findings gets a delta review of that commit by the same reviewer; the cycle stops at the first round with no must-fix. The existing regeneration / prose-only head-move exception stays.
  • Citing the card in the skill — not done, by rule. The dispatch order allows the skill text to cite the card's evidence; pnpm check:pm-skill-id-lint (pattern # + 3 digits) and .claude/agents/os-dev.md (「教训写成自含规则,⛔ 不引卡号」) forbid card numbers in .claude/skills/pm-dispatch/**. The rules are written self-contained; provenance lives in this body and in the script's docblock, where ruling-record citations are the file's own convention.
  • Not in scope, not changed: who drafts ADR text (pm-dispatch model tiering: a card whose surface touches docs/adr/** is dispatched at CONTRACT_REVIEW_TIER with effort xhigh, no one-line exit #25729); re-reviewing merged PRs; references/_index.md does not exist for pm-dispatch (no generator owns one).
  • Observation, not filed: the bare --template / --brief-template (no --face, no --paths) print ④, because the bare template is the tier of a schema or governed-path face; a narrowing-only PR already has to be printed with --face narrowing (the self-test refuses --paths over such a list), so no new trap.

Verification

Local gates on the final head 54224ebf — derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (41 families), each exit code captured before any pipe, reconciled with --ran: ✓ dispatch-gates --ran: 41 derived famil(ies) accounted for — 41 run, 0 NOT-MEASURED. One family, check:doc-formula-expressions, first exited 3 (PREREQUISITE NOT MET: @objectstack/formula and @objectstack/lint dist absent in a fresh worktree); after pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint under os-verify-lock.sh (VERDICT command-exit 0, held 99 s) it re-ran and exited 0. check:pm-dispatch-gates ran detached (308.9 s).

Exit codes (41)
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs --self-test :: exit 0
node scripts/check-self-test-wired.mjs :: exit 0
node scripts/check-self-test-wired.mjs --self-test :: exit 0
node scripts/check-self-test-workflow-commands.mjs :: exit 0
node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0
node scripts/check-whole-set-label-write.mjs :: exit 0
node scripts/check-whole-set-label-write.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0
node scripts/pm/check-governed-queue-guard.mjs --self-test :: exit 0
node scripts/pm/check-harness-current.mjs --self-test :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:bash32-floor :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-command-ids :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:entry-guard :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:parse-guard :: exit 0
pnpm check:pm-expected-skips :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-governed-prose :: exit 0
pnpm check:pm-record-recognisers :: exit 0
pnpm check:pm-skill-id-lint :: exit 0
pnpm check:pm-skill-ratchet :: exit 0
pnpm check:pnpm-filter-targets :: exit 0
pnpm check:pnpm-flag-spellings :: exit 0
pnpm check:ratchet-remedy-authority :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:scripts-symbol-anchors :: exit 0
pnpm check:skill-frame-sync :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:pm-dispatch-gates :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
  • pnpm check:pm-skill-ratchet: contract-review.md is 55 lines (ceiling 60; headroom 5), SKILL.md is 319 lines (ceiling 319; headroom 0), widest SKILL.md table row 341 (pin 341).
  • pnpm check:pm-skill-id-lint: 104 file(s) clean.
  • pnpm check:pm-dispatch-gates: ✓ dispatch-gates self-test (fast tier): 1935 cases pass (308.9 s).
  • Control-character scan over the three files: clean. No model identifier in the diff, the commit or this body.

Two-minute check:

node scripts/pm/record-recognisers.mjs --template | grep -n "④"
node scripts/pm/record-recognisers.mjs --brief-template | grep -n "④"
node scripts/pm/record-recognisers.mjs --brief-template --face narrowing | grep -c "④"   # prints 0
pnpm check:pm-record-recognisers   # 215 cases pass

CI on the PR: the required contexts run on the head after this PR opens; this body is written before them (⛔ not waited on, per the order) and the seat's ACCEPT reads the check-runs.

Human Minimum

Each item is one rule from CONTRIBUTING.md › Human Minimum.

  • 1. No schema touched; packages/spec holds no runtime logic — n/a.
  • 2. Every name I added uses the casing for its kind (fullReview, recordCarriesDesignJudgment).
  • 3. No formatter ran; eslint on the edited file passes (repo-wide pnpm lint is CI's).
  • 4. One issue, one branch off an up-to-date main (00a4593a), one pull request — on the card thread's harness branch, the measured platform exception to claude/issue-N-slug named in the seat's Claim.
  • 5. Nothing publishes: .claude/** and scripts/pm/** are the fast lane, skip-changeset declared at pr_create; both declaration lines are at the top of this body.
  • 6. packages/spec untouched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the 维护者速读 block and the quoted rule lines are the four Chinese channels the skill allows).
  • The Before Submitting list in CONTRIBUTING.md is done.

Generated by Claude Code

…em ④ design judgment in the record, brief and rule

The at-tier contract review of the schema and governed-rules faces gains a
fourth item: the design judged against the code it cites and the scenario
it is accepted against (an ADR against its first consumer and execution
plan), by an agent other than the drafter, over the surface files only,
once per substantive head with a delta round by the same reviewer.

- references/contract-review.md: ④ definition, cadence, independence (55/60)
- SKILL.md: the ACCEPT pointer line names the full review ①–④ (319/319)
- record-recognisers.mjs: `fullReview` on the face table, ④ heading in the
  record on the schema/rules faces, the ④ note in --template, the
  adversarial ④ instruction and surface-file scope rule in --brief-template,
  self-test pins with raised battery floors

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

Copy link
Copy Markdown
Contributor Author

Contract review

Reviewed at 2026-10-27T06:25Z — PR #26514 (card #25765, pm-dispatch: the full-review rule, Tier S), independent contract review at the ceiling tier, read-only, adversarial to the dispatch order, the claim and the dev's report. Inputs: the card body and its five comments (re-fetched over REST at 2026-10-27T06:14Z), the PR body, file list and diff over REST, the three files on origin/main (14f3099, whose tree for every file read here equals the branch point 00a4593) and on the head via git show, scripts/pm/check-governed-merges.mjs, scripts/pm/dispatch-gates.mjs, scripts/pm/check-skill-line-ratchet.mjs, scripts/pm/check-skill-id-lint.mjs, .claude/agents/os-dev.md, references/execution-duties.md and .github/workflows/lint.yml on origin/main, the check-runs and the lint jobs' step lists on the head.

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 54224ebf52a41689f74083074d636d48c5c85cc6
Local-runs: probe — printed the record and brief templates of the head's own record-recognisers.mjs (--template and --brief-template, bare, --face narrowing and --paths over this PR's files, AGENTS.md and a skills/objectstack-ui list) from a git-archive copy of the head tree under the scratchpad, to read the shape item ④ introduces and the brief its first consumer receives; exit 0, printed text only — no self-test, no gate family, no build, nothing in the shared checkout
Scope: .claude/skills/pm-dispatch/references/contract-review.md, .claude/skills/pm-dispatch/SKILL.md + scripts/pm/record-recognisers.mjs (the third path of the diff: the printer and self-test the two rule files cite, read as one change with them), scripts/pm/check-governed-merges.mjs (GOVERNED_SURFACES and governedPathsIn, the rules-face register), scripts/pm/dispatch-gates.mjs (SUSPECT_TIER_GLOBS, the schema face), scripts/pm/check-skill-line-ratchet.mjs (the two ceilings and the 120-byte line cap), scripts/pm/check-skill-id-lint.mjs (why the card is not cited in the skill), .claude/agents/os-dev.md (body shape, HTML-comment exception, card-number ban), .claude/skills/pm-dispatch/references/execution-duties.md (where the retired per-face wording survives), .github/workflows/lint.yml (lane map)

Check-runs on the head, read at 2026-10-27T06:20Z: 45 total — 28 success, 17 skipped, 0 failure, 0 in progress (at 2026-10-27T06:14Z three were still running: Test Core 1/8, Type Check · consumer gates, Type Check · workspace; all three completed success). Lane map read in lint.yml on origin/main and confirmed on the jobs' step lists: check:pm-skill-ratchet (step 19, PM skill line ratchet), check:pm-skill-id-lint (step 20) and check:pm-record-recognisers (step 31, Contract-review record recogniser self-test, lint.yml line 1165) in Lint · repo & tooling gates — success; check:role-word (step 18, Reserved-word docs ratchet, line 2236) in Lint · docs & code guards — success; check:pm-dispatch-gates (step 5) in Lint · PM dispatch-gates — success; Governed Surface Queue Guard success; Check Changeset success with skip-changeset; the three claim/closing guards success. The 17 skipped are the UI, docs-build and opt-in lanes the path filter skips for a diff with no ui/** or content/**. Merge state: blocked at 2026-10-27T06:20Z while the last aggregate runs closed, clean at 2026-10-27T06:24Z; still a draft with no review and no PR comment, as Tier S intends until the seat readies it on this record and its own ## 席位核对.

① Derived judgments

Nothing published changes: no packages/** file, no schema, no changeset. The public surfaces are the pm-dispatch rule text (governed, Tier S) and the two printers of record-recognisers.mjs. Each change, named right or wrong against the card's items 1–6 and the files on origin/main:

  • Faces (card item 3) — right, verified in the register, not taken from the body. reviewFace reads governedPathsIn(list, repo) for the rules face and deriveTier(list, [], SUSPECT_TIER_GLOBS) for the schema face. GOVERNED_SURFACES on origin/main holds the adr row (docs/adr/**, Tier H), the whole-tree row for .claude/** (Tier S) and the skills-catalog row (skills/**, Tier H), so every surface the owner named already reads as the rules face or the schema face at CONTRACT_REVIEW_TIER; no face is added and SKILL.md line 183's governed definition is untouched. Right. One precision the note does not state: the rules face is the WHOLE register — AGENTS.md, CLAUDE.md, docs/NORTH-STAR.md, .github/workflows/** and the six ui/ mirrors also print ④ (measured: --template --paths AGENTS.md prints ### ④ Design judgment at CONTRACT_REVIEW_TIER). That is wider than 「spec skills adr」, which the owner's 「或者至少」 makes a floor, so it is within the order; the ④ note's words 「the published spec, skills and ADR surfaces the full-review order names」 equate the face with the three surfaces and should read 「the governed register, which holds the three surfaces」 — should-fix, see ③.
  • contract-review.md lines 22–23 (record shape) — right. 「①②③ 逐项(schema/governed 两面加 ④)」 matches recordCarriesDesignJudgment(face, tier): true at CONTRACT_REVIEW_TIER for a null face (the bare template) or a face with fullReview: true (schema, rules); false on narrowing, declaration and below tier. Byte-identical to the body's fenced after-block.
  • Lines 30–32 (④ definition and scope, card items 1 and 5) — right. 「逐 hits 文件判改动对所引代码与验收场景是否成立,ADR 另判首个消费者与执行计划;被引代码读而不审」 is the owner's refinement 6396446237 item 5 and the existing scope rule at line 14 (reviewFace hits + the files the hunks assert, cited code read); 「①–④ 合称完整复核,余面同形无 ④,⛔ 无第二条记录」 is the card's carrier choice (a fourth item, not a second record) and is the right choice against the locator: it reads the NEWEST ## Contract review on the head, so a second record would shadow the first.
  • Line 33 (cadence, card item 6) — right, the owner's words: one full review per substantive head, a delta review of a findings-only commit by the same reviewer, stop at the first round with no must-fix. The existing regeneration / prose-only head-move exception at lines 44–45 stays and is consistent (those are not substantive heads).
  • Line 41 (independence, card item 2) — right: the drafter never reviews its own change, drafting at tier is no exemption, the feeding rule of line 36 applies. The Implemented-by:/Reviewed-by: pair (line 40) is the machine-read half; this line is the human-read half.
  • SKILL.md line 190 (card item 4) — right, and the retired words are not lost. Old: 「技能面 hunk 复核随面定档:席未达档起隔离达档复核」; new: 「受管/spec 面欠完整复核 ①–④,席未达档起隔离达档复核」. The tier-follows-the-face rule survives verbatim in contract-review.md line 11 「档随面定」 and references/execution-duties.md line 113 「自审随面定档」; the pointer format before the semicolon is unchanged; 「受管面」 is already the file's own word (lines 26 and 164). Measured 118 bytes (was 111), under the 120-byte cap; 319 lines on both sides.
  • Line ceilings — right. contract-review.md 49 → 55 of 60; SKILL.md 319 of 319; every non-fence line of contract-review.md ≤ 120 bytes (the seven new or changed lines measure 115, 29, 114, 112, 101, 116, 113 — the dev's 「longest new line 116」 is line 33, correct); check:pm-skill-ratchet green on the head is the verdict.
  • record-recognisers.mjs — right. fullReview on the frozen face table (true schema and rules, false narrowing and declaration); recordCarriesDesignJudgment pure; contractReviewRecordLines takes an optional faceId and refuses an unknown one instead of printing the bare record; contractReviewTemplateLines passes the face through, so --paths over a mixed list resolves to the schema or rules face and prints ④; contractReviewBriefLines prints the ④ instruction and the surface-file scope rule on the same faces and neither on narrowing or declaration (measured on the head copy: --brief-template --face narrowing prints zero ④). No reader changed: the locator, the head-span, Served-tier:, Reviewed-by: and Local-runs: readers are untouched by the diff, and no other script imports the changed functions (grep over scripts/** and .github/** on the head finds no caller outside the file). The record I am writing is itself the live test that a four-section record reads FOUND on the readers origin/main runs.
  • Self-test — right, and the floors are measured. Counting t( assertions per battery on both trees: the template battery 21 → 29 (+8), the brief battery 12 → 18 (+6), every other battery unchanged, 201 → 215 total — the dev's 14 pins, 8 + 6. The floors 19 → 27 and 10 → 16 rise by exactly the pins added and keep the two-case headroom each battery already had on origin/main (floors are 「at or above」, per the file's own comment); the roster stays 12. Every new printed line is pinned: the record heading (position right after ③, four ### headings, the identity lines after it); all five lines of the template note (fragments from lines 1, 2, 3, 4 and 5); both lines of the brief's scope rule; all four lines of the brief's ④ item; the positive faces (schema, rules, --paths mixed) and the negative faces (narrowing fenced record, declaration with and without its face, below tier); the face table 「exactly schema,rules」 with every face answering a boolean; the unknown-faceId refusal; a ④ record still FOUND and STANDING on a real head; angle brackets, model identifiers and digit-shaped card numbers kept out of the brief.
  • PR body — right. All eleven fenced blocks are byte-identical to the file on origin/main or the head, or to the printer on the head (checked by substring match, not by eye); the line-count table (49 → 55, 319 → 319, 2054 → 2134) matches wc -l on both trees; the six 速读 labels are in the fixed order with 需要你做的 = 无,席位落地 (right for Tier S); English sections in the os-dev order.

② Semver level

Right. skip-changeset with nothing published: .claude/** and scripts/pm/** belong to no npm package; Check Changeset success. Clause-②: no (line 4) and Metadata-protocol: none (line 5) are line-initial, after Fixes #25765 on line 3 behind the two harness attribution lines — the shape the dispatch order itself specified and os-dev.md line 323's exception allows (Fixes immediately after the harness lines); the two closing-keyword guards on the head are green. No Skills-docs: line is owed (no (narrowing) arm, Metadata-protocol: none).

③ Boundary flags

The report (6435101147) carries deviations (8), line_budget, open_questions: [], out_of_scope_findings (one observation, carrier none); branch claude/project-thread-osntoo = the claim's branch; mcp_calls: 0 (the two harness tools named are not GitHub MCP); api_writes: 2 (relay pr_create, the report comment). Author objectstack-fleet[bot], so no off-relay author to name. Each flag, answered:

  1. Harness attribution lines 1–2 then Fixes on line 3 — nothing: os-dev.md line 323 and the dispatch order both prescribe it; the guards are green. Note only: the harness attribution comment's key word matches MODEL_IDENTIFIER_FORM by shape, but no gate scans the PR body with it and it names no model; the dev's 「no model identifier in this body」 holds in substance. The commit carries the model-free trailer pair.
  2. GitHub MCP assignee step skipped; relay set os-warren and skip-changeset; no reviewer requested — nothing, right for Tier S.
  3. The card not cited in the skill text — right, by rule: check-skill-id-lint pattern /#[0-9]{3,}/ over .claude/skills/** and os-dev.md line 20 forbid it; the dispatch order's hypothesis 3 yields to os-dev.md, as the order itself says. Provenance in the script docblock is that file's convention (ruling-record ids are cited there already). Nothing.
  4. Harness trailer not followed — right per os-dev.md 284; the commit's trailers are the harness session-URL trailer and a model-free co-author trailer. Nothing.
  5. One amend before the first push, never force-pushed — one commit on the branch, commits: 1. Nothing.
  6. Turn cut by an API error, resumed — nothing.
  7. PULL_REQUEST_TEMPLATE headings folded — nothing, same reading as on PR skills(objectstack-ui): teach list-view grouping and orderBy, the duration measure, action copy holes, and a flow action's onSuccess #26385.
  8. ④ not on the narrowing face — the dev's open question, answered: nothing is lost for the order as written, and widening is the owner's call, not this PR's. Faces read the committed file list in order: schema first, then rules, then the declaration. A Clause-②: no (narrowing) on a PR whose diff touches packages/spec/src/** non-test or any governed path reads as the schema or rules face and carries ④ already. The narrowing face exists only when the diff holds none of those paths, so by construction it holds none of the three surfaces the owner named. What it can hold is a narrowing of a published accept set implemented in runtime code alone (say packages/objectql): the card's filer parenthetical 「"spec" = the published-schema face … and cards of the domain:spec lane」 would reach it by lane, but no face reads a lane label, and neither the triage line nor the dispatch order adopted that parenthetical. So: faithful to the order; a one-flag widening (fullReview: true on narrowing, line 30 reworded, two self-test pins flipped) if the owner wants it — a card candidate, below.
  9. The dev's observation that the bare --template and --brief-template print ④ — agreed, no trap: --paths over a list carrying a changeset and no declaration is refused with the instruction to pass --face narrowing or --face declaration, and a list with no schema, governed or changeset path reads as the declaration face at TIER_DEFAULT, no ④.
  10. Base reconciled: the PR's base sha 73683ee sits 13 commits past the branch point 00a4593 and origin/main (14f3099) two further; none of those 15 commits touches the three files, the register, the suspect globs, the queue guard, the ratchet or lint.yml (git log over those paths is empty), so the judgments above hold against origin/main as it stands.
  11. Should-fix, not must-fix (next head or a follow-up card): (a) the ④ note's wording, per ① — the rules face is the governed register, wider than the three surfaces; (b) the brief's ④ names the accepted scenario for an ADR only (first consumer and execution plan); for a skill file the scenario is the card's eval prompt and the spec it teaches on origin/main, and for a schema file the ruling or ADR it implements and its first consumer — the printed brief leaves a seat to supply that by hand (measured: --brief-template --paths skills/objectstack-ui/SKILL.md … prints the generic ④ item with the three paths as hits, sensible but scenario-less).

④ Design judgment

Judged per hits file against the code it cites and the scenario it is accepted against; the cited code read, not reviewed.

  • contract-review.md — holds. Its first consumer is this lane's next brief (the seat will generate it from the new --brief-template), and its first scenario is this PR: a Tier S pm-dispatch head with a rules-face hit. Filled truthfully here: the design (④ as a fourth section of the one record) holds against the locator (newest ## Contract review on the head; a ### line is never the marker, pinned in the locator battery of the self-test, so ④ is prose to the readers), against the independence pair (unchanged keys), and against the queue guard (presence of Reviewed-by: and a standing Served-tier: — neither reads section headings). Tried to break it: a seat that copies an old ①②③ record onto a rules-face PR is refused by nothing — no gate reads ④'s presence, exactly as triage ordered (⛔ no new gate), so the enforcement is the seat's ## 席位核对 reading the record against lines 22–23; the rule says so (「同形 = …」) and the seat's checklist line 191 (核对六项: 形态) is where it is checked. A second record is forbidden by line 32 and the locator would shadow it anyway. The cadence line reads cleanly beside the line 44 exception. No must-fix.
  • SKILL.md line 190 — holds. The pointer format is unchanged and the clause names what the two path-read faces owe (①–④) and who runs it below tier; ①–④ resolves in contract-review.md; nothing else in .claude/** still states the record as ①②③ alone (grep on the head finds only line 22, now amended). No must-fix.
  • record-recognisers.mjs (read as the gate of the rule) — holds against its callers: contractReviewRecordLines keeps its signature (faceId optional), --template without arguments prints the at-tier default with ④, which is the right default for the tier the bare template already declares; the narrowing-face omission is a flag read off the one table, never a second list. Should-fix only, named in ③ (11a, 11b).

Implemented-by: claude/project-thread-osntoo
Reviewed-by: session_01LqKsGyMNFwwnbF5FTAqyPn (independent contract-review subagent)

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

维护者速读

改了什么:pm-dispatch 技能的契约复核规则加第 ④ 项「设计判断」:碰已发布 schema 面或受管规则面(含 spec、skills、ADR,按受管登记表)的 PR,达档复核除 ①②③ 外还逐个命中文件判「改动对所引代码与验收场景是否成立」(ADR 另判首个消费者与执行计划);范围只限面上文件,被引代码读而不审;一次实质 head 一轮完整复核,只改复核意见的提交由同一复核者做增量复核,无 must-fix 即止;复核者不得是起草者。记录模板与简报模板(scripts/pm/record-recognisers.mjs)印出 ④,自检加 14 条钉住;contract-review.md 49 → 55 行(上限 60),SKILL.md L190 同行改写(319/319)。
为什么改:田騏 10-25 的原话「spec skills adr 都需要fable 完整的复核」「fable 复核应该只针对pr中的重要文件」;PR #25717 两轮合同复审都 PASS 后,独立完整复核才找出三处必须改的设计缺陷。
风险与回滚:只改技能文本与模板打印/自检,无门禁新增(分诊 ⛔ no new gate);回滚 = revert 本 PR(一个提交)。风险在 ④ 只靠席位核对 contract-review.md L22–23 的形态检查执行,没有门禁读它——一张旧式 ①②③ 记录贴到规则面 PR 上不会被机器拒绝。
先看:① references/contract-review.md L22–23、L30–33、L41;② SKILL.md L190;③ record-recognisers.mjs 的 fullReview 标志与 --template / --brief-template 的 ④ 段。
两分钟验证:pnpm check:pm-record-recognisers(215 例)与 pnpm check:pm-skill-ratchet 全绿;node scripts/pm/record-recognisers.mjs --template --paths docs/adr/0001-x.md 印出 ### ④ Design judgment。
需要你做的:无。Tier S,契约复核 PASS + 本核对后席位 ready 并布自动合并。
席位意见:同意落地。两条 should-fix 不压本 PR,进后续卡:④ 注解把规则面写成「spec/skills/ADR 三面」,实际是整张受管登记表(含 AGENTS.md、workflows);简报 ④ 只写了 ADR 的验收场景,skill 文件应对卡上 eval 题与所教 spec、schema 文件应对其实现的裁决/ADR 与首个消费者。另一条归你裁:④ 要不要也盖「收窄申报」面(只在运行时代码收窄已发布接受集、不碰三面路径时才会出现),一个标志翻转。

席位核对

ACCEPT · domain:skills#2 · session_01LqKsGyMNFwwnbF5FTAqyPn · 2026-10-27T06:28Z — seat review of record for #25765 on head 54224ebf, against GitHub, not the report's own account. Every changed path sits under .claude/** (the register's Tier S row) or scripts/pm/**; no skills/**, no ADR, no AGENTS.md ⇒ Tier S: the record of the review tier is the independent ## Contract review at comment 6435325292 (Served-tier: CONTRACT_REVIEW_TIER, head 54224ebf, VERDICT: PASS, Local-runs: probe — printing the head's own templates from a git-archive copy, declared; four sections ①–④, the first record in this lane carrying the ④ this PR introduces; drafted by a reviewer other than the implementer, the card thread's dev). This seat adds the landing read and lands it itself.

  1. Shape. Draft, base main, mergeable: true (clean), one commit; body lines 1–2 the harness attribution block, line 3 Fixes #25765, Clause-②: no, Metadata-protocol: none line-initial; ## 维护者速读 six labels in order; every one of the 11 fenced before/after blocks byte-identical to main/head (reviewer substring-checked). Files: references/contract-review.md (+7/−1, 49 → 55 of 60), SKILL.md (+1/−1, L190 118 B, 319/319), scripts/pm/record-recognisers.mjs (+91/−11) — exactly the claim's surface (claim 6434496126). Labels documentation, size/m, skip-changeset (nothing published). Branch claude/project-thread-osntoo, named by the claim; base 73683ee1, 13 commits past the branch point 00a4593a, none touching the three files, the register, the suspect globs, the queue guard, the ratchet or lint.yml.
  2. Record, measured. The reviewer read the faces in the register, not the body: GOVERNED_SURFACES on origin/main holds docs/adr/** (H), .claude/** (S), skills/** (H) and reviewFace reads governedPathsIn + deriveTier(…, SUSPECT_TIER_GLOBS), so the owner's three surfaces were already faces, no face added, SKILL.md L183 untouched; the rules face is the whole register (④ also prints for AGENTS.md — within 「或者至少」). SKILL.md L190's retired words 「随面定档」 survive at contract-review.md L11 and execution-duties.md L113. Self-test batteries 21 → 29 and 12 → 18 (201 → 215), floors 19 → 27 and 10 → 16 rise by exactly the pins added; every new printed line pinned by fragment, negatives for narrowing/declaration/below-tier pinned; no other script imports the changed printers. ④ as a fourth section holds against the locator (newest ## Contract review; a ### line is never the marker), the independence pair and the queue guard. The seat re-read the diff and the body and reads the same.
  3. Gates, pinned to head 54224ebf. 45 check-runs, 28 success and 17 skipped (path-filtered UI/docs/opt-in lanes), none red or pending (reviewer's read 2026-10-27T06:20Z); check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-record-recognisers in Lint · repo & tooling gates; check:role-word in Lint · docs & code guards; check:pm-dispatch-gates in Lint · PM dispatch-gates; Governed Surface Queue Guard, Check Changeset, the claim/closing guards — all success.
  4. Accepted deviations. (a) Fixes on line 3 behind the harness's two attribution lines. (b) Branch is the thread's harness branch. (c) pr_create through the relay, 0 GitHub-MCP calls. (d) The card is not cited in the skill text (check-skill-id-lint forbids #NNN under .claude/skills/**; provenance lives in the script docblock). (e) ④ is enforced only by the seat's 形态 check against contract-review.md L22–23 — no gate reads it, by triage's ⛔ no new gate; a seat that copies an old ①②③ record onto a rules-face PR is refused by nothing. (f) The harness attribution comment's key word matches MODEL_IDENTIFIER_FORM by shape; no gate scans the body with it and it names no model (same reading as PR skills(objectstack-ui): teach list-view grouping and orderBy, the duration measure, action copy holes, and a flow action's onSuccess #26385).
  5. Carrier. Should-fix items the reviewer named (11a: the --template ④ note equates the rules face with the three surfaces — it is the governed register; 11b: the brief's ④ names the accepted scenario for an ADR only — add the per-surface scenario: skill file → the card's eval prompt and the spec it teaches on main; schema file → the ruling/ADR it implements and its first consumer) and the owner's-call widening (④ on the narrowing face: one fullReview: true flag, L30 reworded, two pins flipped) go into ONE follow-up card the seat files after landing (dedupe design judgment narrowing face fullReview brief scenario per surface). The dev offered a findings-only delta head; the seat declined it under the cadence rule this PR writes (no must-fix ⇒ stop).
  6. Landing. Tier S ⇒ on this record the seat readies the PR and arms auto-merge through the relay (pr_ready, automerge_enable), follows it to MERGED, closes pm-dispatch review: a PR touching published spec, skills or docs/adr/** owes an independent full review at CONTRACT_REVIEW_TIER before the seat's ACCEPT, not only the contract review #25765 with the landing record and files the follow-up card. From this landing on, every contract review brief in this lane is generated from the new --brief-template and every record carries ④ on a schema- or rules-face hit.

Generated by Claude Code

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/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant