Skip to content

Commit 1ced0f8

Browse files
feat(pm): scope the at-tier contract review of a mixed diff to reviewFace hits — the Scope: line (#23655)
Fixes #23578 Clause-②: no ## What this does Executes ruling record 6184805932 on the card (letter C, the maintainer's 「同意」): the at-tier contract review of a mixed diff is scoped to the paths `reviewFace` returns as `hits` plus every file those hunks make a claim about; the record's `Scope:` line lists both; the non-governed remainder is the lane seat's ACCEPT at `TIER_DEFAULT`; Tier H approval and the queue guard stay whole-PR. The ruling, quoted from the record: > 1. The at-tier review of a mixed diff covers the paths `reviewFace`'s `hits` returns (governed rules text and published schema alike) plus every file those hunks make a claim about; the reviewer reads the cited code. The record's `Scope:` line lists the `hits` paths (machine-derived, the same function the queue guard uses) and the extra files read. The reviewer may widen the scope, never narrow it below `hits`. > 2. The non-governed remainder is the lane seat's ACCEPT at `TIER_DEFAULT`, exactly the review it gets as a standalone PR; the ACCEPT names it. > 3. Tier H human approval stays whole-PR and the queue guard is unchanged (it reads the tier by face already). `SKILL.md:186` is untouched. > 4. A governed hunk and a non-governed hunk that are one semantic change (a rule and the gate that enforces it) are read as one under item 1. ### `.claude/skills/pm-dispatch/references/contract-review.md` (+3 lines: 44 to 47, ceiling 60) - L11–12, the 档随面定 tier mapping, are unchanged byte for byte. A mixed diff still owes ONE review at `CONTRACT_REVIEW_TIER` on one hit; what this changes is that review's scope. - New L13–14: the scope of that review = `hits` + the files their hunks claim about (the reviewer reads the cited code). A rule and the gate that enforces it are read as one. The record's `Scope:` line lists both and may widen, never below `hits` (items 1, 4). - New L15: the remainder = the lane seat's ACCEPT at `TIER_DEFAULT`, as for a standalone PR, named there. Tier H approval and the queue guard stay whole-PR (items 2, 3). - `SKILL.md:186` is untouched, and no table row was added. ### `scripts/pm/record-recognisers.mjs` - `reviewScopeHits(paths)` is the floor, read off `reviewFace` itself: schema hits first, each path once. It is empty exactly on the declaration face. - `--template`: the at-tier record carries `Scope: PATH-ONE, PATH-TWO + CITED-FILE` right after `Local-runs:`, plus a `· Scope` legend entry. The declaration face prints no `Scope:`, because it has no hits and its whole review is the lane seat's own. - `--brief-template`: at tier, a Scope paragraph after "Inputs" (the hits, the claimed files, widen-never-narrow, and the remainder's ACCEPT tier). The declaration-face brief is byte-identical to before. - `--paths PATH...` takes the PR's changed paths in place of `--face` (refused beside `--face`, refused when empty). It reads the face off them through `reviewFace` and prints the `hits` filled in. The brief then hands the reviewer `--template --paths HITS`, which reads back the same face and the same floor (pinned). - The fence wording "replace the three / four placeholders" became "replace every placeholder", since the count now varies by face. - No reader reads `Scope:`, and `check-governed-queue-guard.mjs` is not edited. ## PM mechanism assumptions, measured - (a) At `7cb33cfef`, `reviewFace` returns `{ face, tierName, words, hits: { schema, rules } }`, which holds. `contract-review.md` was 44 lines (ceiling 60) and its widest table row was 0 bytes. - (b) The record reader tolerates an unknown line: **holds**. The readers are per-key regexes. The thread-set battery drives the real queue guard (`runGuard`, merge-group event, Tier S path) with the record `contractReviewRecordLines()` now prints, `Scope:` included. The guard clears on both threads, and a new case asserts that the cleared record carries the line. The writer side holds too: a one-off probe of `post-stamped.mjs` `recordKeyedLineRefusals` on a `--paths`-printed record returns `[]`. No recogniser change was needed. - (c) Net +3 lines; `check:pm-skill-ratchet` reports 47 lines, ceiling 60, headroom 13, widest table row 0 (pin 0). - (d) `check:pm-record-recognisers` passes 184 cases (165 before, plus an 18-case letter-C battery and 1 guard case; the roster floor is 10 → 11). `check:pm-skill-id-lint` reports 87 files clean. ## Boundary flag for the reviewer: `--paths` `--paths` goes beyond the dispatch's placeholder-only route. The reason: the ruling calls the `hits` "machine-derived, the same function the queue guard uses", and the card and claim say the line is "read off `hits`". With placeholders alone, a seat lists governed paths by eye, which is exactly how a scope drops below `hits`. The bare output still prints the word placeholders. If the seat prefers placeholder-only, removing `--paths` means deleting `templateArgsOf`'s third branch, `templateFace`'s paths arm, the brief's paths command and the cases that exercise them. ## Verification (all at head `ead127958`) - `node scripts/pm/record-recognisers.mjs --self-test`: exit 0, "✓ record-recognisers self-test: 184 cases pass". - Derived gates: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths, merge base `7cb33cfef`) gives 37 commands. All 37 ran and all exited 0. - `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first exited 3 (PREREQUISITE NOT MET: `@objectstack/formula` and `@objectstack/lint` unbuilt; nothing measured). It re-ran with exit 0 after `turbo run build` of those two packages under `os-verify-lock.sh` (VERDICT command-exit 0). - `pnpm check:pm-dispatch-gates` (fast tier): exit 0, 1884 cases. - `--ran` reconciliation: "37 derived famil(ies) accounted for — 37 run, 0 NOT-MEASURED (a DERIVED zero — all 37 recorded an exit code and none of them is 3)". - Suites of the script's importers: `node scripts/pm/check-governed-queue-guard.mjs --self-test` exit 0 (322 cases), and `pnpm check:pm-post-stamped` exit 0 (679 cases). - No package is touched, so no package build or test applies locally. CI runs the full farm. - The diff publishes nothing (`.claude/**` and `scripts/pm/**` only), so there is no changeset and it carries `skip-changeset`. ## Acceptance notes - `usageLines`' docblock said "Four flags" while five already existed. It now says "a closed set of flags". - The brief battery's case title "the four placeholders" is kept: `BRIEF_TEMPLATE_PLACEHOLDERS` still holds the four slots a seat fills by value, and the scope floor is filled by `--paths`, not by value. ## 维护者速读(草稿) - **改了什么**:一张混合 PR(受管文件和普通文件混在一起)只把受管路径(`reviewFace` 的 `hits`)和这些改动所涉及的其他文件送达档复审;复审记录多一行 `Scope:`,写明审了哪些文件。其余部分照它单独开 PR 时那样,由车道席位按默认档审。复审模板工具新增 `--paths`,可直接从 PR 的文件清单算出该审的受管路径,不靠人眼挑。 - **为什么改**:执行裁决记录 6184805932(字母 C,您的「同意」)。此前一处受管命中就整张 PR 达档复审:受管只占 0.2% 的 PR 也花了约 17.7 万 token、10 分钟。 - **风险与代价(含回滚)**:风险是复审漏看受管部分与其余代码之间的不一致。对策是范围已包含受管改动「所涉及的文件」,复审者可以放宽、不可收窄。人工批准(Tier H)与合并队列守卫都不变,仍管整张 PR。回滚:revert 本 PR(两个文件);`Scope:` 行没有任何机器读取,旧记录不受影响。 - **席位意见**: - **你要做的**:无需操作。本 PR 只改 `.claude/**` 与 `scripts/pm/**`,属 Tier S,由席位在达档复核 PASS 后落地。 --- _Generated by [Claude Code](https://claude.ai/code/session_01GjUZrCo7Yi58T4vPXqx88e)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 286eb9e commit 1ced0f8

2 files changed

Lines changed: 182 additions & 26 deletions

File tree

‎.claude/skills/pm-dispatch/references/contract-review.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
⛔ 不在其列:派发席按本席档在 ACCEPT 逐句对照 diff 核,ACCEPT 点名所核句。
1111
- 档随面定:已发布 schema 或 governed 规则文本 ⇒ `CONTRACT_REVIEW_TIER`,混合 diff 一处命中即此档;
1212
仅凭 `Clause-②: yes` 申报而欠 ⇒ `TIER_DEFAULT`,由车道席位作复核记录;档恰等不作下限。
13+
- 混合 diff 的达档复核范围 = `reviewFace` 的 `hits` 路径 + 其 hunk 所断言的文件(读被引代码);
14+
规则与执行它的门禁同属一改者一并读;记录 `Scope:` 行列两者,可放宽、⛔ 不窄于 `hits`。
15+
- 余部归车道席位 `TIER_DEFAULT` 的 ACCEPT,同单独开 PR 并点名;Tier H 人批与队列守卫仍整张 PR。
1316
- 面读 PR 已提交树的文件清单,同队列守卫判 governed 路径;⛔ 不读席位自述。
1417
- 已发布面以包的 `exports` 映射为准:从入口类型图不可达、且 `exports` 不可寻址的 `.d.ts` 是
1518
出货字节,⛔ 不是已发布接受集,改它不触发 `Clause-②: yes`;legacy node10 深引用在契约之外。

0 commit comments

Comments
 (0)