Skip to content

Commit fd12471

Browse files
claude[bot]claude
andauthored
fix(pm): judge a review of record's Served-tier: line on every pair that has one (#18251)
Fixes #18174 `check-clause2-carriers --pair` read a review of record's `Served-tier:` line only beside a gate clear, so `references/contract-review.md` :29's 「无此行不成裁决」 was enforced on one path of two. ## The defect, measured One spelling, two answers, same script, same day: | pair | gate hung? | the record's `Served-tier:` | `--pair` | |---|---|---|---| | objectstack PR #18157 / card #17991 (record 5661052272) | no — `Clause-②` never declared `yes` | a stamp control, then prose, then the constant — unreadable to this file's own reader | **0** | | objectui PR #9486 / card #9191 (record 5662548425) | hung and cleared | the same spelling | **4**, C7 | The seam: `reviewOfRecord` answered `not-owed` before reading a thread unless the pair was in C6's completed state (`needsRecordRead` → `gateBindingState(pair).state === 'completed'`), and `c7ServedTierBelow` returned `null` for anything but `found`. Measured on this branch's base `b3b43b6`: a non-gated pair carrying an unreadable record, one carrying the live shape, and one carrying no record at all were indistinguishable — `pairRows` empty for all three, `reviewOfRecord` `not-owed` for all three. ## The change - **`locateReviewOfRecord(pair)`** — the gate-independent locator: the same imported H51 heading / head-sha recognition, the same `Reviewed-by:` third fact, the same newest-governs choice, with no reference to the gate. No recognition moved. - **`reviewOfRecord(pair)`** — that locator under C6's population gate. C6's row, its 「not-owed」 scope, its shape sentence and its remedy are unmoved, and both rows still read ONE comment chosen once. - **C7** and the **C6-RECORD note** read the locator. C7's accept set (one token, the constant's NAME), its exactness, its refusal of a missing line and its remedy are untouched — widened in POPULATION only, in the direction its own rule text names. Its opening sentence is now gate-aware: it names a clear only where a clear rides on the record. The note's citation half stays C6's, because the act it names is C6's. - **`gather`'s `landingReads`** (was `readFiles`) buys the PR thread for every pair on the `--pair` path, where the ruling puts this reading (「清标前」); the sweep's population is unchanged, for the budget reason C5's identical split already records. **`locatedRecordUnjudged`** is that path's own #4690 half, so an unread thread is UNJUDGED and never clean. - **Consequence pinned, not left to be discovered:** with the PR thread in hand, `verdictThreadRows` hands C4 a thread it previously saw only on completed pairs, so a verdict on a non-gated or still-hung pair is now judged for the independence pair it declares. That direction only adds verdicts to a reading whose newest-governs rule already lets a later independent verdict displace an older self-review. Pinned in both directions; the sweep's blindness there is restated as the limit that survives. ## Evidence **Reproduction on the real historical pair, replayed offline.** Both PRs are merged, so `--pair` cannot form the pair from the live board; the document carries the fetched `/pulls/18157`, `/issues/17991`, both comment threads and the file list, and nothing else. - before (`origin/main` `b3b43b6`): `--pair 18157 --pair-json …` → exit **0** - after: exit **4** — C7 naming comment 5661052272, the unreadable line quoted back, and its stamp control read as NOT total (the 「回退证据」 half) **Live control**, PR #18243 / card #18229 — open, non-gated, `Clause-②: no`, record 5673963268 in the template's shape: exit **0** before and after. After, the run also prints the C6-RECORD note naming that record and saying the pair owes no clear (4 reads → 5). **The sweep is unmoved, deterministically:** the same document in sweep mode produces byte-identical `--json` output before and after. A live gated pair (#18212) reads exit 4 with the same rows on both. **Self-test:** 629 → 658 cases, `pnpm check:pm-clause2-carriers` exit 0. A new battery (`#18174: …`, 28 cases) carries the measured non-gated spelling beside the live one; the roster floor moves 22 → 23 and C7's own floor 42 → 43. Four of C7's population pins were re-triaged rather than left green for the wrong reason: each now spells a pair whose threads were READ and carry no record, instead of passing because no thread was ever fetched. **Reverse verification**, from the committed fix: `c7ServedTierBelow`'s locator call mutated back to `reviewOfRecord`. On-disk proof — injected marker grep = 1, deleted anchor grep = 0, blob hash `5a79776b` → `c4757e7a`. Self-test under the ablation: **5 of 658 red** (the measured pair, its two sentence pins, the still-hung pair and the 重挂 pair). Restored with `git checkout HEAD --`: `git diff HEAD` empty and the blob back at `5a79776b`. Direction: turns red, as predicted. **Gates**, union re-run at `7af15586` (`git rev-parse --short HEAD`), working tree clean: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths derives **35** families; all 35 ran in the foreground with exits captured by redirect, all **exit 0**; `--ran` reconciles **35 derived / 35 run / 0 NOT-MEASURED / 0 UNRUN**, every exit code recorded. Beyond the derivation: `pnpm lint` (repo-wide, `eslint . --no-inline-config`) exit 0, and the two siblings that import this module — `check-governed-queue-guard.mjs --self-test` (238 cases) and `check-half-states.mjs --self-test` (4042 cases) — exit 0. `skip-changeset`: `scripts/pm/**` is repo tooling that no package `files[]` ships. ## Acceptance notes - noted, not filed: in a SWEEP a record on a non-gated pair stays invisible, because the sweep buys no PR thread for it. That is a declared limit, written into this file's budget paragraph beside C5's identical one, not a defect — and 承接者: nobody today; it becomes a card only if a seat ever prices a per-pair sweep thread. - noted, not filed: an existing pre-fetched `--pair-json` document that omits the `comments` entry for the PR now reads UNJUDGED (exit 2) on a pair that owes no record, where it read 0 before. That is this change's own documented owing, restated in the doc-shape paragraph, not a separate finding. 承接者: the MCP-only seats that hand this file a document — the file's own refusal text names the key to add. - The C4 reach on the landing path widens as a consequence of the bought thread (see above). In scope, documented and pinned in both directions. --- _Generated by [Claude Code](https://claude.ai/code/session_01HZfg2AwVX191qCizp88gQr)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b8ec127 commit fd12471

1 file changed

Lines changed: 358 additions & 87 deletions

File tree

0 commit comments

Comments
 (0)