Repository navigation
Commit 1ced0f8
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
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
13 | 16 | | |
14 | 17 | | |
15 | 18 | | |
| |||
0 commit comments