You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(pm): the mixed-diff diversion on PR #15284 fired and lawfully found nothing to fork — the three report-side readings that made it look like a failure (#15650)
* fix(pm): the queue guard — a CLEAR reached through a generated-artifact lift no longer reports itself as a clear that matched nothing (#15406)
The merge-queue log for PR #15284 printed, one line under its own
`LIFTED skills/objectstack-ui/references/react-blocks.md` note:
✅ CLEAR — the diff touches no governed surface, so this guard has nothing to judge.
… ⛔ ZERO review lookups were made: the path test runs first and returns
Both sentences are false for that run. The path test MATCHED (the diff's
eleventh file is on the `skills/**` surface), and the register's own recompute
ran and certified it. Read back from the log, a compliant landing under the
2026-09-01 generated-artifact ruling is indistinguishable from a guard that
never saw the file.
Report-only: `guardVerdict` now carries the paths the register lifted (default
`[]`), and the `clear` rendering picks between the zero-cost clear — kept
BYTE-FOR-BYTE on both legs, so the 2026-08-27 pull_request byte-identity
constraint is untouched — and a clear reached through a lift, which names the
lifted paths and says the recompute ran. No predicate, verdict, exit code or
API cost changes.
`liftedPathsBetween` derives what was lifted from the row lists on either side
of `liftGeneratedExceptions`, not from its prose notes, and is deliberately
conservative across rows (the #11084 fence is per-row).
Self-test: 133 → 144 cases; new battery replays #15284's real 11-path file
list, one commit, PR 15284, zero reviews of any kind.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
* fix(pm): the post-merge audit — a governed row names the register row it does not recompute, and --test stops reporting a post-lift zero as a clean read (#15406)
Two report-side readings turned a compliant landing into an incident card.
1. `renderTestVerdict`'s head counts `hitPaths`, which is the POST-lift set.
On PR #15284 it printed "0 of 11 path(s) hit the register" immediately above
the exception line naming the path that hit it. The count keeps its meaning
(what is STILL governed) and now says when the register lifted the
difference. Byte-identical when nothing was lifted.
2. The sweep classifies with `governedPathsIn` alone and never consults the
exception register — deliberately: provenance is a recompute against the
tree a commit landed on, and this sweep holds no such tree. The row it
rendered for #15284 was therefore indistinguishable from one for a
hand-authored governed merge. `registerCell` adds the missing reading: which
register row the governed path belongs to, that this sweep does NOT
recompute, and that certification is recorded in that landing's queue-guard
log. It lifts nothing and suppresses nothing — the row is still listed and
still counts as a governed merge — and it repeats the register's own
doctrine rather than softening it: a candidate earns the QUESTION, never the
answer. Membership is the register's own `generatedExceptionFor`, so no
second mechanism is authored (#11705's ruled constraint).
Self-test: 263 → 274 assertions, new battery replaying #15284's shape in both
directions (all-registered, mixed with hand-authored content, and none).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
---------
Co-authored-by: Claude <noreply@anthropic.com>
'the #11705 generator-owned rows inside `skills/**`': 23,
703
703
'#11705 end to end, against the REAL generator': 7,
704
704
"the live battery's prerequisite, and the floor it was misread as": 17,
705
+
'⭐ #15406: the sweep row names the register it does not recompute': 10,
705
706
});
706
707
707
708
// DELETING an entry silences that battery's floor exactly as effectively as
708
709
// zeroing it, so the roster's own size is pinned too.
709
-
constSELF_TEST_BATTERY_FLOOR=23;
710
+
constSELF_TEST_BATTERY_FLOOR=24;
710
711
711
712
// The key an assertion is filed under when no battery is open. It is not a
712
713
// declared battery, so it reds by the same set difference rather than silently
@@ -1172,7 +1173,18 @@ export function renderExceptionLines(verdict) {
1172
1173
1173
1174
/** The words a seat reads before flipping ready. Pure, so --self-test pins them. */
1174
1175
exportfunctionrenderTestVerdict(verdict){
1175
-
consthead=`governed-surface predicate: ${verdict.hitPaths.length} of ${verdict.checked} path(s) hit the register (${verdict.surfacesChecked} surfaces, repo-agnostic).`;
1176
+
// `hitPaths` is the POST-lift set, so on a diff whose only register hit was a
1177
+
// certified regeneration this counted 0 — printed directly above the exception
1178
+
// line naming that very path as a register hit (#15406, measured on PR #15284:
1179
+
// "0 of 11 path(s) hit the register" over one lifted hit). The count keeps its
1180
+
// meaning — what is STILL governed — and now says when the register lifted the
1181
+
// difference. ⛔ Byte-identical when nothing was lifted: the clause appears only
console.log(`✓ check-governed-merges --self-test: ${checked} assertions (the unified governed predicate + near misses, subject→PR spellings, window parsing, the #12633 landing window — the QS-7 regression pin in both directions, the topological close beyond the budget, the unproven-boundary EDGE, the listed-or-INCOMPLETE invariant over every fixture, the escalating floors, per-repo --since-ref resolution and its named fallback, and the window words — the replay fixtures, the five-repo resolution incl. absent/wrong-origin/relocated checkouts, the attribution channel chain + its proxy-transport re-arm plan and its one named fallback line, the three-way attribution column (resolved · every-channel-failed · NOT LOOKED UP, and the note pointer that belongs to the middle one alone), the --test pre-arm predicate, the generated-artifact provenance exception — the register's invariants incl. the RETIRED #9866 row staying retired (no row lifts anything under .claude/**, and the audit workflow is plainly governed again), a row with no recompute failing closed, lift/reject/absent-provenance semantics, the untouched mixed-diff rule, named-rows-not-a-class, the #11084 generator co-edit fence in both directions incl. a row with no instrument tree, and its render words — the #11705 generator-owned rows inside skills/** (a genuine generated file passes, the same path hand-edited does not, a path no generator declares is hand-authored content, per-row fences, and the enumeration read from the real generator), the exit table, the report wording pins, and the #13307 remote-reachability leg — the pure freshness verdicts in every branch (unreachable · a remote naming no commit · an unreadable local tip · a mirror behind its remote · the two-unreadable-shas degenerate case that must never read as a match), the report words in both directions (an unreachable repo never renders the tick, a reachable one still says a MEASURED zero, and a row with no remote reading never claims one), and the REAL prober on local bare-repo fixtures over the file transport — a live remote, a deleted one, the --exit-code branch, and a mirror the remote moved past — the #13423 identity leg (an origin no slug parses from refuses, pure and end-to-end, with audited reachable only through a parsed matching slug), the #13424 per-repo window resolution (a sibling-only pin resolves in its own repo, the self-only control still errors, and the end-to-end sibling-pin sweep reports instead of exiting 1), the #13307 sweep-code provenance line in all three branches, and the #13836 attribution set — every refusal carries its precondition category on the row, in the footer, and in --json; the shallow-clone path in both directions; and the run-1-vs-run-2 flip reproduced on real fixtures with zero local writes — and the live battery's own PREREQUISITE, asked before a single case runs: an uninstalled checkout refuses with the repo-wide NOT-MEASURED code end to end instead of reporting a shrunken battery, while the floor still names the battery, by itself, for a case that genuinely stopped registering).\n ${liveNote}`);
4037
+
console.log(`✓ check-governed-merges --self-test: ${checked} assertions (the unified governed predicate + near misses, subject→PR spellings, window parsing, the #12633 landing window — the QS-7 regression pin in both directions, the topological close beyond the budget, the unproven-boundary EDGE, the listed-or-INCOMPLETE invariant over every fixture, the escalating floors, per-repo --since-ref resolution and its named fallback, and the window words — the replay fixtures, the five-repo resolution incl. absent/wrong-origin/relocated checkouts, the attribution channel chain + its proxy-transport re-arm plan and its one named fallback line, the three-way attribution column (resolved · every-channel-failed · NOT LOOKED UP, and the note pointer that belongs to the middle one alone), the --test pre-arm predicate, the generated-artifact provenance exception — the register's invariants incl. the RETIRED #9866 row staying retired (no row lifts anything under .claude/**, and the audit workflow is plainly governed again), a row with no recompute failing closed, lift/reject/absent-provenance semantics, the untouched mixed-diff rule, named-rows-not-a-class, the #11084 generator co-edit fence in both directions incl. a row with no instrument tree, and its render words — the #11705 generator-owned rows inside skills/** (a genuine generated file passes, the same path hand-edited does not, a path no generator declares is hand-authored content, per-row fences, and the enumeration read from the real generator), the exit table, the report wording pins, and the #13307 remote-reachability leg — the pure freshness verdicts in every branch (unreachable · a remote naming no commit · an unreadable local tip · a mirror behind its remote · the two-unreadable-shas degenerate case that must never read as a match), the report words in both directions (an unreachable repo never renders the tick, a reachable one still says a MEASURED zero, and a row with no remote reading never claims one), and the REAL prober on local bare-repo fixtures over the file transport — a live remote, a deleted one, the --exit-code branch, and a mirror the remote moved past — the #13423 identity leg (an origin no slug parses from refuses, pure and end-to-end, with audited reachable only through a parsed matching slug), the #13424 per-repo window resolution (a sibling-only pin resolves in its own repo, the self-only control still errors, and the end-to-end sibling-pin sweep reports instead of exiting 1), the #13307 sweep-code provenance line in all three branches, and the #13836 attribution set — every refusal carries its precondition category on the row, in the footer, and in --json; the shallow-clone path in both directions; and the run-1-vs-run-2 flip reproduced on real fixtures with zero local writes — and the live battery's own PREREQUISITE, asked before a single case runs: an uninstalled checkout refuses with the repo-wide NOT-MEASURED code end to end instead of reporting a shrunken battery, while the floor still names the battery, by itself, for a case that genuinely stopped registering) — and the #15406 replay of PR #15284: the sweep still CLASSIFIES a certified regeneration as a governed merge and still lists it, its row now names the register row it does not recompute and where certification is recorded, and the --test head no longer reports a post-lift zero as if nothing had hit the register.\n ${liveNote}`);
0 commit comments