Skip to content

feat(pm): scope the at-tier contract review of a mixed diff to reviewFace hits — the Scope: line - #23655

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23578-contract-review-scope
Oct 15, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-23578-contract-review-scope

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

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

…Face hits — the Scope: line

Ruling record 6184805932 (letter C): the at-tier review of a mixed diff
covers the paths reviewFace returns as hits plus every file those hunks
make a claim about; the record's Scope: line lists both, may widen and
never narrows below hits; the non-governed remainder is the lane seat's
ACCEPT at TIER_DEFAULT; Tier H approval and the queue guard stay whole-PR.

- contract-review.md: the 档随面定 rule keeps its tier mapping and gains
  the scope, the remainder and the whole-PR landing lines (+3).
- record-recognisers.mjs: reviewScopeHits (read off reviewFace); the
  at-tier record prints `Scope: PATH-ONE, PATH-TWO + CITED-FILE` with its
  legend; the brief states the scope; --paths reads the face and fills
  the hits; a new self-test battery (18 cases) and a guard-drive case
  proving the queue guard clears a record carrying the line.

Claude-Session: https://claude.ai/code/session_01GjUZrCo7Yi58T4vPXqx88e
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation labels Oct 15, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 15, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: ead127958a1adff4b27c803e0c70b35bf9c2ef99
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/contract-review.md + scripts/pm/record-recognisers.mjs

① Derived judgments

  • Face: rules — the PR's committed file list holds one governed path, .claude/skills/pm-dispatch/references/contract-review.md (register row .claude/**, Tier S); scripts/pm/record-recognisers.mjs is unregistered. hits.rules = that one path, hits.schema empty ⇒ CONTRACT_REVIEW_TIER, in seat (the served tier equals the constant's value this session). Under the rule on main today the whole diff is read at tier; under the rule this PR lands, the floor is the md and the script is the file its hunks claim about — read in full either way.
  • Accept set and public surface: no change. No package is touched; .claude/** and scripts/pm/** publish nothing. Clause-②: no, no arm — right.
  • The rule text (md, +3 lines at L13–15, 44 → 47 of 60): carries every clause of ruling 6184805932 letter C — item 1 (scope = reviewFace hits + the files those hunks assert about, cited code read; Scope: lists both; widen, ⛔ never below hits), item 4 (a rule and the gate that enforces it read as one), item 2 (the remainder = the lane seat's TIER_DEFAULT ACCEPT, as a standalone PR, named), item 3 (Tier H approval and the queue guard whole-PR). L11–12 (the tier mapping) are byte-identical; SKILL.md:186 untouched; no table row added (the width pin 0 holds); no issue number in the operative text.
  • The script: reviewScopeHits(paths) is reviewFace's hits de-duplicated, schema first — read off the same function the queue guard decides the face with, never a second classification; empty exactly on the declaration face. contractReviewRecordLines prints Scope: only at CONTRACT_REVIEW_TIER, right after Local-runs:, as plain text (no code span, so the head matcher never sees a path). The record readers are per-key regexes, and the thread-set battery drives the real queue guard with the record that now carries the line and clears on both threads (322 guard cases) — the dispatch's mechanism assumption (b) measured true, no reader and no guard edit. templateFace refuses face beside paths and an empty list; templateArgsOf refuses flag-shaped or empty words among the paths. The brief hands the reviewer --template --paths HITS, pinned to read back the same face and floor. Battery floor 18 for the new battery; roster floor 10 → 11, both pinned by name.
  • Beyond the ruling's named workload — the --paths door (the CLI arm, templateFace, the brief's command, about eight cases). Judged in seat: KEEP (the dev's option A). It is the mechanism by which the floor is machine-derived for the seat that writes the record — item 1's own words, 「machine-derived, the same function the queue guard uses」 — and it only prints: no reader, no guard, no public surface. A floor listed by eye is the one way a scope falls below hits, which the ruling forbids. Within the letter; an accepted deviation, recorded here, not an escalation.
  • Placeholders and sanitizer: PATH-ONE, PATH-TWO and CITED-FILE carry no angle bracket and no path separator; the fence wording moves from a count to 「every placeholder」 because the count now varies by face. The comment citations 「ruling record 6184805932 on [Decision] contract review of a mixed diff: does one governed path send the whole PR to CONTRACT_REVIEW_TIER, or only the governed hunks? #23578」 sit in scripts/pm/**, outside the id-lint's walk (87 files clean on the head).

② Semver level

No published package in the diff ⇒ no changeset owed; the skip-changeset label is the correct declaration and Check Changeset reads skipped on the head.

③ Boundary flags

  • open_questions[0] (keep or drop --paths): answered in ① — A, keep. Verification and tooling shape under an already-ruled letter; no escalation.
  • deviations: BASE 7cb33cfef rather than the dispatch's c5dd7fce3 — origin/main moved before the worktree was cut; the premises were re-read there (the rule line unchanged, reviewFace returns hits: { schema, rules }, 44 lines) and hold. The 维护者速读 heading spelled with ASCII parentheses — no reader keys on a body heading. The model-free commit trailer pair — correct under AGENTS.md, which outranks the harness reminder.
  • out_of_scope_findings: none; two acceptance notes (the usageLines docblock count, the brief battery's case title) are not debts.

Implemented-by: claude/issue-23578-contract-review-scope
Reviewed-by: session_01GjUZrCo7Yi58T4vPXqx88e

VERDICT: PASS

Reviewed 2026-10-15T10:45Z against the PR's committed diff, the card's four records and the head's check-runs (Governed Surface Queue Guard success at the time of reading; Lint, Type Check and Test Core lanes still converging — the pre-landing gate reading is the seat record's, not this one's).

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — PR #23655 (#23578) @ ead127958a1adff4b27c803e0c70b35bf9c2ef99 · seat domain:skills#1 · session_01GjUZrCo7Yi58T4vPXqx88e (os-sales) · 2026-10-15T10:53Z

Verdict: ACCEPT. Tier S — node scripts/pm/check-governed-merges.mjs --pr 23655 exit 3: governed, .claude/** ×1 (references/contract-review.md), scripts/pm/record-recognisers.mjs not on the register, 208 changed lines (+182/−26) under the 3000 human-merge threshold. The at-tier contract review of record is 6190236120 (PASS on this head, rendered in seat at CONTRACT_REVIEW_TIER).

  1. 形态: draft, base main, first body line Fixes #23578 (the card is pm:dispatched, assignee os-sales); no other open card number sits near a closing keyword in the body (the other numbers are ruling ids and PR tooling(pm): the contract review's tier follows the face that made it owed #23389 as precedent); Clause-②: no at line start, no arm; skip-changeset label; PR assignee os-sales; 2 files, 1 commit; the 维护者速读 draft present with 席位意见 blank (ASCII parentheses in its heading — no reader keys on a body heading); footer in the session-URL form; no model identifier.
  2. 前提实测: on origin/main c5dd7fce3 (the dev's BASE 7cb33cfef lies between; the premises were re-read there by the dev and here by the seat): contract-review.md:11–12 still carry 「混合 diff 一处命中即此档」 and the PR leaves them byte-identical; reviewFace returns hits: { schema, rules } before the PR (record-recognisers.mjs:170) and after it (the same function, now also read by reviewScopeHits); SKILL.md:186 is untouched; the file is 47 lines of 60 on the head with no table row (width pin 0 holds).
  3. 门禁 check-runs on ead127958 (read in this act): required five — Lint & Repo Gates success · TypeScript Type Check success · Test Core success (shards 1–6 success) · Build Core skipped · Governed Surface Queue Guard success. Every other check success, or a skip the expected-skips roster names: Check Changeset (success on the gate run, skipped on the labeler run — the skip-changeset opt-out), Check PR Size and Auto Label (one event run each skipped, the other success), Packed-tarball smoke (opt-in) (no needs:pack-smoke label), Build Core (the core filter false — a diff outside packages/**; its verdict is taken in the queue build), Temporal Conformance, Dogfood Regression Gate matrix template, Dogfood Verify CLI, Console Pin Gate (full-battery jobs, PR heads skip them), Build Docs (the docs filter false). The dev's local subset: 37 derived families run at the head, all exit 0, --ran reconciled; record-recognisers --self-test 184 cases, the queue guard's 322, post-stamped's 679. Instrument note: check-expected-skips.mjs --pr 23655 could not run in this container — yaml is declared in the root manifest and absent from the shared checkout's stale node_modules (a pnpm install --frozen-lockfile is running); the roster above was read from the script's source at c5dd7fce3, and every skipped name on the head matches an entry and its reason.
  4. 接受的偏差: the --paths door beyond the ruling's named workload — kept, judged in 6190236120 (item 1's 「machine-derived, the same function the queue guard uses」; print-only, no reader); the BASE sha; the ASCII-paren heading; the model-free commit trailer pair (AGENTS.md outranks the harness reminder). mcp_calls 0; api_writes 3 relay strokes, each read back identical.
  5. 范围外去向: out_of_scope_findings empty. Two acceptance notes stay on the PR with no carrier owed: the usageLines docblock's flag count, the brief battery's case title.
  6. 落地条款: Tier S ⇒ the seat lands through the queue: relay pr_ready, then mergeable_state read after the flip and automerge_enable once it reads clean or blocked, then added_to_merge_queue awaited on the timeline (about six minutes before any re-arm). At MERGED the card closes by Fixes, pm:dispatched leaves it in the same act, and the landing comment (the two-reading probe table) goes on the card. Pointer line on the card follows this record.

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

Development

Successfully merging this pull request may close these issues.

[Decision] contract review of a mixed diff: does one governed path send the whole PR to CONTRACT_REVIEW_TIER, or only the governed hunks?

2 participants