feat(selector): RQ-64-MVLOWER (#1093) — parameter-taking block types LOWER on the ARM direct selector (--relocatable), proven per shape by the #1097 oracle; every other leg stays declined with its measured reason - #1188
Merged
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
avrabe
force-pushed
the
feat/mvlower-1093
branch
2 times, most recently
from
September 7, 2026 14:10
1d06c32 to
f4ac5f6
Compare
…WERED mode, set empty (red-first) The acceptance oracle for relaxing the #1096 guard asserted `refusals == 6` unconditionally, so it structurally could not PASS for a leg whose decline is relaxed. This adds the third per-leg mode WITHOUT changing behaviour: LOWERED = {} — a (shape, backend) leg listed here must COMPILE and every vector for it must equal live wasmtime on the NEW object: the fixture's pinned silent-wrong vectors (0xC0DE0003 etc.), the pinned match vectors, extra live probes (both signs + the i32 wrap boundary), and a per-construct `_lowered.wat` sub-shape module. A lowered leg with nothing to execute FAILS. The RED half (pre-#1096 fixture bytes, pinned wrong) is untouched. Floors: refusals == 6 - len(LOWERED) and lowered legs == len(LOWERED), both in-script and BOTH pinned exactly in ci.yml (the #1112 pattern), so a leg moves between the two counts only in the PR that relaxes its guard. Measured on the unchanged compiler: PASS, refusals 6, lowered 0, identical output to the pre-change run except the header line and the new count. Negative control: declaring block/arm lowered with NO compiler change fails (`VACUOUS: lowered legs=0, want 1`, exit 1) — the mode is red-first by construction for every later relaxation. Refs #1093, #1097 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…on the ARM direct selector (--relocatable), proven by the #1097 oracle Shape 1 of the parameter-taking block-type class, on the ONE configuration the #1097 acceptance oracle executes. The guard becomes a per-construct, per-path POLICY defined once in synth-core (`ParamBlockLowering`, `arm_param_block_lowering(relocatable)`, `find_unlowered_param_block_type`) and read by both ARM guard sites, so the backend choke point and the selector-local guard derive from the same source and cannot drift. WHY THIS SHAPE IS SAFE (measured, not argued): block params are plain operand-stack entries and #509's designated-result-register landing already reconciles every forward edge (br/br_if/br_table) into the join. The pre-#1096 fixture matched wasmtime on this leg for that reason — its decline was conservative — and the LOWERED run re-proves it on the NEW object: 14/14 vectors match (fixture bpb(1)/bpb(0), extra probes bpb(2)/ bpb(-1), and the `_block_lowered.wat` sub-shapes: two params with br_if, an unconditional br to an outer param block, br_table into nested param blocks, a value below the params surviving the edge). The lowering adds ZERO selector lines. WHAT STAYS DECLINED, with the measured reason in the message: - the self-contained image path (optimized selector, or the direct selector via --no-optimize / the #509 value-carry routing): no #1097 oracle leg executes its images, so there is no evidence to relax on; - `if (param ..)` and `loop (param ..)` on every path (next increments); - RV32 (all shapes): its frame checkpoint drops the carried param on a branch edge (the pinned uninit-T2 vector) and the selector has no blocktype-arity plumbing at all. Oracle: block/arm listed LOWERED; refusals 6 -> 5 and lowered legs 0 -> 1 (14 vectors) pinned exactly in ci.yml; `emulations >= 19 -> 33`; the exact emulation floor RE-DERIVED by oracle_wiring_check.py (324847 -> 324861) and moved in ci.yml + claims.yaml together. The RED half (pre-#1096 bytes pinned wrong) is untouched. Byte-identity, base (1672180) vs this tree, scripts/repro/*.wat x 3 legs (arm-reloc, arm-self, rv32-reloc), whole-object compare: 356 identical / 0 differing / 0 newly-declined / 2 newly-ACCEPTED (the two block-param modules, arm-reloc only). Ratchet: selector_lines_code 19227 -> 19233 (+6: the guard call reading the policy — waived with reason); selector_lines_total 29873 -> 29879. Tests: fmt/clippy clean; synth-core + synth-synthesis + synth-backend suites green incl. 4 new tests (policy predicate, path-keyed policy, relocatable selector lowers block + still declines if/loop, backend lowers block on --relocatable only). Note: claims.yaml's #1096 waiver names a test `select_with_stack_declines_param_block_types` that does not exist in the tree (the pins live in issue_1093_param_block_decline.rs) — left as found, flagged in the lane report. Refs #1093, #1097 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…the ARM direct selector (--relocatable): the 0xC0DE0003 vector now returns 7 Shape 2 of the class, on the configuration the #1097 oracle executes. This is the leg the artifact exists for: pre-#1096, `ipe(0)` returned 0xC0DE0003 — an uninitialized R3 — because the #313 frame-entry checkpoint was taken with the block parameters still on the operand stack, so they sat BELOW it (the same fact that made `Else`'s `split_off(checkpoint)` PANIC on the #1093 two-param repro). THE LOWERING (keyed on `params > 0`; parameter-free ifs are byte-identical): - `If`: the checkpoint lands BELOW the params and the param entries are snapshotted (`if_params`); every param must be register-resident. - `Else`: after the then-results are split off, the snapshot is re-pushed so the else-arm starts from the same operand stack the then-arm did (on that path no then-arm code ran, so the registers still hold them). - `End` without an else: wasm's implicit identity else is lowered as an explicit empty one — `B end; else:` then `MOV R_then_i, R_param_i` via `reconcile_implicit_else`, which PLANS the moves and LOUD-declines any parallel-move hazard (a swap, an i64 lo/hi overlap) with nothing emitted; five negative-control unit tests pin that. FOUND WHILE PROVING IT — a register-alias clobber, and it is on main too: `local.get` of an R0..R3 parameter pushes the HOME register by alias, so a then-arm ending in `local.get 0` makes the join's else-path `mov` write LOCAL 0. Strengthening the oracle with such vectors went RED on this lane's first lowering (`ipa(0)` 14 want 7; `ipq(0)` 16 want 8, captured); `canonicalize_then_results` now copies an aliased then-result into a private temp on the then path (param-taking paths only) and both are green. The PARAMETER-FREE #313 join has the identical exposure on main — measured on the base binary: `(if (result i32) c (then (local.get 0)) (else (i32.const 9))) (local.get 0) (i32.add)` returns 18 for c=0, wasmtime 9 — and is deliberately NOT touched here: that fix moves bytes outside this lane's acceptance oracle and needs its own oracle-gated increment (repro in the lane report). ORACLE (red-first at every step): if/arm listed LOWERED; 16 vectors — fixture ipe(0)/ipe(1) (0xC0DE0003 -> 7), extra probes, and `_if_lowered.wat`: the #1093 panicking two-param if/else repro, a void if (param) with else, a value below the params, an in-place then-result, an if (param) nested in a block (param), a two-param/two-result else-less if, and the two alias-clobber shapes — all matching wasmtime. refusals 5 -> 4 and lowered legs 1 -> 2 (34 vectors) pinned exactly in ci.yml; `emulations >= 33 -> 53`; exact emulation floor RE-DERIVED by oracle_wiring_check.py (324861 -> 324881), ci.yml + claims.yaml together. STILL DECLINED, by name: `loop (param ..)` everywhere (next increment); every shape on the self-contained image path (no oracle leg executes it) and on RV32 (no arity plumbing in its selector; its checkpoint drops the carried param — the pinned uninit-T2 vector). A param-taking if whose inputs are not on the operand stack (spec if.wast `add64_u_saturated`: a multi-value call result) declines loudly with the reason named. REACH, measured on the spec suite's if.wast (--relocatable): base skipped 16 functions, 8 of them PARAMETER-taking declines; now 13 skipped, 0 param-taking declines — 5 of the 8 lower, 2 fall through to the pre-existing #509 "br to a result-typed if/else join" decline, 1 to the multi-value-call-result decline above. Byte-identity, base (1672180) vs this tree, scripts/repro/*.wat x 3 legs, whole-object: 356 identical / 0 differing / 0 newly-declined / 4 newly-ACCEPTED (the block + if param modules, arm-reloc only). Ratchet: selector_lines_code 19233 -> 19530 (+297: the lowering — waived with reason), selector_lines_total 29879 -> 30307, wildcard arms unchanged (55/90 — `let .. else`, no `_ =>`). fmt/clippy clean; the three crates' suites green incl. 6 new unit tests and the flipped pins. Refs #1093, #1097 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…n the ARM direct selector (--relocatable); artifact implemented with per-shape verdicts Shape 3 of the class, on the configuration the #1097 oracle executes. Pre-#1096 ARM never compiled this shape — the #509 "br to a loop header with N loop parameter(s)" refusal caught it — while RV32's back-edge mis-reconciled the header (the pinned lpb(3) = 2, want 10). THE LOWERING (keyed on `params > 0`; parameter-free loops byte-identical): - `Loop`: a parameter-taking loop gets a PRIVATE header register per parameter (`BlockLabel::param_regs`). An entry donates its own register when it is a plain temp held by no other operand-stack entry; one that aliases a register-homed local, or is shared, is copied out first (the RQ-64 alias-clobber class — `lpa`: the loop param is the aliased r0 and local 0 is read after the loop). - reservation: the header registers join the per-op `live_params` reservation for the loop's extent — the same argument as #509's `result_reg`: only a back-edge writes them, only the header reads them, so nothing in between can observe an intervening write. - `edge_value_move`: a back-edge (br / br_if / br_table) PEEKS the top `params` entries, PLANS the moves into the header registers, LOUD- declines a parallel-move hazard with nothing emitted, then emits them before the compare/branch. This RETIRES the #509 loop-param refusal arm on this path — the landing replaces it. ORACLE (red-first): loop/arm declared LOWERED on the increment-2 binary -> compile declines -> exit 1 (captured); then this lowering -> PASS. 17/17 vectors: the RV32-pinned lpb(0)/lpb(1)/lpb(3) (a lowered leg now executes every vector the fixture pinned for its SHAPE on ANY backend), extra probes, and `_loop_lowered.wat`: two loop params around the back-edge, a value below the param, an unconditional back-edge with a forward br_if out to an enclosing block (param), and the aliased-r0 loop param. refusals 4 -> 3, lowered legs 2 -> 3 (51 vectors) pinned in ci.yml; `emulations >= 53 -> 70`; exact emulation floor RE-DERIVED by oracle_wiring_check.py (324881 -> 324898), ci.yml + claims.yaml together. ARTIFACT: RQ-64-MVLOWER -> implemented, with the per-shape verdict table and every still-declined leg's MEASURED reason (self-contained ARM path: no oracle leg; RV32: no arity plumbing, checkpoint above the params, MC/DC pin; AArch64: VCR-A64-CF-001 design; multi-value-call inputs) plus the register-alias finding on main, reported for scoping. Byte-identity, base (1672180) vs this tree, scripts/repro/*.wat x 3 legs, whole-object: 356 identical / 0 differing / 0 newly-declined / 6 newly-ACCEPTED (the six param-taking modules, arm-reloc only). Ratchet: selector_lines_code 19530 -> 19663 (waived with reason); selector_lines_total 30307 -> 30440; wildcard arms UNCHANGED (55/90 — the shared-register check is a `matches!` guard, the first draft's `match .. _ => false` was caught by the pin and rewritten). fmt/clippy clean; the three crates' suites green incl. the loop acceptance tests and the #509 decline pins (non-relocatable selector still declines at frame open). `rivet validate` with the local binary: error count identical to base (40, pre-existing); every line naming this artifact is a WARN/INFO of the kind every sibling carries. Refs #1093, #1097 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…s the three param-block EXPECTED_DECLINES entries: the guard's precondition was discharged, and says so
The sweep compiles every scripts/repro/*.wat at `cortex-m4f --relocatable
--all-exports` — exactly the ARM direct-selector path RQ-64-MVLOWER
relaxed — so its ratchet arm fired on all three param_block_silent_1097_
{block,if,loop}.wat entries ("now COMPILES ... but is still on
EXPECTED_DECLINES"). The entries' guard comment forbade removing them
"by lowering the shapes without passing that oracle first"; that oracle
(param_block_silent_1097_differential.py) was strengthened first and now
asserts `lowered legs: 3 (vectors: 51)` where it asserted `refusals: 6`,
red-first per leg. The comment is REWRITTEN, not deleted: it records the
discharge, by whom, with what evidence, which assertion replaces the
entries, and which legs stay declined on paths this sweep does not
compile (self-contained ARM, RV32, AArch64).
The new-decline arm did NOT fire: the three `_lowered.wat` sub-shape
fixtures COMPILE at cortex-m4f and Phase B executes them (block 4 exports,
if 8, loop 4, x 12 vectors) against wasmtime — a second, independent
execution oracle over the same lowerings.
Measured on this tree: PHASE A fixtures=179 compiled=164 declined=15
hard-error=0 (was 15+3 entries pending removal); PHASE B modules
executed=53 vectors=2744 mismatches=0 faults=0; #973 ARM CORPUS SWEEP:
PASS.
Refs #1093, #1097, #973
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
avrabe
force-pushed
the
feat/mvlower-1093
branch
from
September 7, 2026 14:34
f4ac5f6 to
de326c6
Compare
…93 — one then-result alias-copy mechanism, counters re-derived Both lanes independently built the then-result alias copy at the if join, with different scope: #1190 for EVERY if (liveness-gated on `param_last_read` past the if's End, at `Else`), this branch for parameter-taking ifs only (`canonicalize_then_results`). Resolved ON main's mechanism, not beside it: main's inline `Else` block is lifted verbatim into `copy_live_home_then_results` (returns the emitted count so the control-flow accounting is identical) and called at both joins — `Else` (every if) and the RQ-64 implicit-else join at `End` (else-less parameter-taking if, `end_idx = idx`). This branch's helper and its unit test are deleted. The If-arm keeps the checkpoint below the params plus main's `if_start_idx.push`; the End arm keeps both pops. #1189 NOT regressed, measured on the merged binary: join_alias_1189_differential.py -> refusals: 1; silent-wrong vectors: 14 (of 14 pinned); fixture match vectors: 60; live vectors: 149 matched, 0 diverged (of 149); RESULT: PASS. The oracle was not touched. Counters RE-DERIVED on the merged tree (never a side taken): exact emulation floor: oracle_wiring_check.py -> 325121 (ci.yml + claims.yaml in lockstep; neither 324898 nor 325070 — both comment blocks kept, plus a merge note). selector_lines_code: 19740 — BOTH lanes' waivers kept (19233/19530/ 19663 here, 19355 for #1189) plus a third at the merged value explaining it is two landed growths minus the deleted duplicate (below their deltas summed); wildcard code arms unchanged. selector_lines_total: 30565. claim_check 62/62; status_evidence_check 0 failures, floor-prose 0; status.json REGENERATED, not hand-merged. Also on the merged binary: #1097 oracle PASS (refusals 3, lowered 3 / 51 vectors); #973 ARM corpus sweep PASS (183 fixtures incl. #1189's, 167 compiled, 16 declined, 2936 vectors, 0 mismatches). Byte-identity, main e96d23f vs this tree, scripts/repro/*.wat x 3 legs, whole-object: 364 identical / 0 differing / 0 newly-declined / 6 newly-accepted (the six param-taking modules, arm-reloc only) — every parameter-free module, #1190's fixtures included, carries main's bytes unchanged. Three-crate tests + fmt + clippy green. Refs #1093, #1097, #1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…kes `&mut [StackVal]` (ptr_arg), and the merge commit's gate is corrected here The merge commit (07d2e4f) shipped with `cargo clippy -D warnings` RED: `ptr_arg` on the extracted helper's `stack: &mut Vec<StackVal>` — both allocator helpers it calls already take a slice. The lane's own pre-commit gate captured CLIPPY_EXIT=101 and then did not gate on it (a `;` broke the `&&` chain before `git commit`). Same-line signature change; no codegen, no line-count movement. Re-verified on the rebuilt binary, gated end to end: fmt clean; clippy clean; join_alias_1189_differential.py refusals 1 / silent-wrong 14 of 14 / live 149 matched 0 diverged, PASS; param_block_silent_1097_differential.py refusals 3 / lowered 3 (51 vectors), PASS; three-crate tests green; claim_check 62/62; status_evidence_check 0 failures. Refs #1093, #1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Dependency bump only; counters re-derived below rather than carried.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RQ-64-MVLOWER (#1093): parameter-taking block types LOWER on the ARM direct selector (
--relocatable), proven per shape by the #1097 oracle — and every other leg stays declined with its measured reasonArtifact:
artifacts/release-v0.64/RQ-64-MVLOWER.yaml→implemented. Refs #1093, #1097.The constraint, and how it was met
No shape's decline was relaxed without
scripts/repro/param_block_silent_1097_differential.pypassing for it. The oracle assertedrefusals == 6unconditionally, so it structurally could not pass for a lowered leg; it was strengthened first (commit 1, behaviour-identical, negative control captured), never paralleled or weakened:LOWEREDmode: a listed(shape, backend)must compile and every vector must equal live wasmtime on the NEW object — the fixture's pinned silent-wrong vectors, its match vectors, extra probes (both signs + the i32 wrap boundary), and a per-construct_lowered.watsub-shape module; a lowered leg with nothing to execute FAILS;refusals:andlowered legs:pinned exactly in ci.yml (the fix(oracle): #1104 shadowed the aarch64 builder guard and left its oracle pinned to the superseded wording #1112 pattern) — a leg moves between the counts only in the PR that relaxes its guard;Every relaxation went red-first: the leg was listed LOWERED on the previous binary (compile declines → exit 1, captured), then the lowering landed, then green.
Verdict per shape (ARM direct selector,
--relocatable— the one configuration the oracle executes)block (param ..)if (param ..)ipe(0)returned0xC0DE0003(uninitialized R3); it now returns wasmtime's 7. Checkpoint below the params; params snapshotted atIf, re-pushed atElse; else-less if joined like a two-arm if (B end; else: MOV R_then, R_param), moves PLANNED first, parallel-move hazards decline loudly with nothing emitted. Includes the #1093 panicking two-paramif/elserepro.loop (param ..)result_reg, written by every back-edge (same hazard check). Retires the #509 "br to a loop header with N loop parameter(s)" refusal on this path. The RV32-pinnedlpb(3)(2, want 10) is 10 on ARM.reconcile_br_edgerecordsentryABOVE the params so a param frame'sbr_if"carries nothing" (the pinned uninit-T2 vector); the loop back-edge mis-reconciles (lpb(3)2 want 10);compile_function_with_optsis MC/DC-pinned at 10 branches. None attempted.if.wast add64_u_saturated)check_no_underflowpre-flight (both backends).The guard is now a policy, not a predicate:
synth_core::ParamBlockLowering+arm_param_block_lowering(relocatable)+find_unlowered_param_block_type, defined once and read by both ARM guard sites, keyed on--relocatable.Found while proving it — a register-alias clobber, and it is on
mainlocal.getof an R0–R3 parameter pushes the HOME register by alias, so a then-arm ending inlocal.get 0makes the join's else-pathmovwrite local 0. Adding such vectors to the oracle went RED on this lane's first if-lowering (ipa(0)14 want 7;ipq(0)16 want 8);canonicalize_then_resultscopies an aliased then-result into a private temp on the then path and both are green.The parameter-free #313 join has the identical exposure on
main— measured on the base binary (16721807), relocatable ARM:al(0)→ 18, wasmtime 9; exit 0, silent. Deliberately NOT fixed here — it moves bytes outside this lane's acceptance oracle and needs its own red-first oracle and byte accounting. Filed by the coordinator as #1189, owned by a separate lane; this PR leaves it alone.Measured, not argued
16721807) vs this tree,scripts/repro/*.wat× 3 legs (arm-reloc, arm-self, rv32-reloc), whole-object compare: 356 identical / 0 differing / 0 newly-declined / 6 newly-ACCEPTED (the six param-taking modules, arm-reloc only). Every parameter-free construct is byte-identical (lowerings keyed onparams > 0).if.waston--relocatable: base skipped 16 functions (8 param-taking declines); now 13 skipped, 0 param-taking declines — 5 of the 8 lower, 2 fall through to the pre-existing Direct selector miscompiles value-returning br_table — carried value dropped (affects --relocatable/shipped path) #509 "br to a result-typed if/else join" decline, 1 to the multi-value-call decline.oracle_wiring_check.pyon the lane tree and moved in ci.yml + claims.yaml together.selector_lines_codegrew in three waived steps (each reason names what the lines are and that nothing could be deleted in exchange — the class had no lowering to retire); wildcard arms unchanged (55/90 —let .. else/matches!, no_ =>).#973 ARM corpus sweep — the retired guard says so
The sweep compiles every
scripts/repro/*.watatcortex-m4f --relocatable --all-exports— the path this PR relaxed — so its ratchet arm fired on the threeparam_block_silent_1097_{block,if,loop}.watEXPECTED_DECLINESentries. Their guard comment forbade removal "by lowering the shapes without passing that oracle first"; that precondition was discharged (the oracle now assertslowered legs: 3where it assertedrefusals: 6), and the comment is rewritten to record the discharge — by whom, with what evidence, which assertion replaces the entries, and which legs stay declined on paths the sweep does not compile. Its new-decline arm did NOT fire: the three_lowered.watfixtures compile there and Phase B executes them (block 4 exports, if 8, loop 4, ×12 vectors) — a second, independent execution oracle over the same lowerings. Measured: PHASE A fixtures=180 compiled=164 declined=16 hard-error=0; PHASE B 53 modules, 2744 vectors, 0 mismatches, 0 faults; PASS.Earlier: rebased onto
f4780608(#1184 MACHO, #1187 CFOBLIG) — re-derived, not carriedClean replay of all five commits. On the merged tree:
oracle_wiring_check.pyderives the emulation floor to exactly the pinned value (MACHO's oracle iscompiles-mode and does not move it);claim_check.py62/62 with the selector ratchets unchanged (maindid not touch the selector);status_evidence_check.py0 failures, floor-prose 0 restatements; the #1097 oracle and the #973 sweep re-run PASS on a binary built from the merged tree; three-crate tests + fmt + clippy green.Merged with
mainate96d23ff(#1190, the #1189 fix) — one mechanism, not twoBoth lanes independently built the then-result alias copy at the if join. The merge keeps #1190's liveness-gated copy as the single mechanism and deletes this PR's
canonicalize_then_results(and its unit test): main's inlineElseblock is lifted verbatim intocopy_live_home_then_results(returns the emitted count socfaccounting is identical) and called at both joins —Else(every if, #1190) and the RQ-64 implicit-else join atEndwithend_idx = idx. What this PR still adds on top of it for parameter-taking ifs: the checkpoint landing below the params, the param snapshot/re-push, and the else-less join as an empty explicit else with the planned-move hazard check.git checkout --ourswould have dropped #1190's general fix; it was resolved hunk by hunk instead.#1189 not regressed, measured on the merged binary:
join_alias_1189_differential.py→refusals: 1;silent-wrong vectors: 14 (of 14 pinned); fixture match vectors: 60;live vectors: 149 matched, 0 diverged (of 149); PASS. The oracle was not touched.Counters derived on the merged tree, never carried: exact emulation floor
oracle_wiring_check.py→ 325121 (ci.yml + claims.yaml in lockstep; neither side's number);selector_lines_code→ 19740 with BOTH lanes' waivers kept and a third waiver at the merged value explaining it is the sum of two landed growths minus the deleted duplicate (19663 mine, 19355 main's: the merged value is below their deltas summed);selector_lines_total→ 30565; wildcard code arms unchanged (55);claim_check62/62;status_evidence_check0 failures, floor-prose 0;status.jsonregenerated, not hand-merged. #1097 oracle on the merged binary: refusals 3, lowered 3 (51 vectors), PASS. #973 sweep on the merged corpus (now 183 fixtures incl. #1189's): 167 compiled, 16 declined, 2936 vectors, 0 mismatches, PASS. Three-crate tests + fmt + clippy green on the merged tree. Byte-identity, maine96d23ff(with #1190) vs the merged tree,scripts/repro/*.wat× 3 legs, whole-object: 364 identical / 0 differing / 0 newly-declined / 6 newly-accepted (the six param-taking modules, arm-reloc only) — every parameter-free module, #1190's own fixture modules included, carries main's bytes unchanged.Also noticed, left as found (logged, not fixed here; neither is this PR's)
select_with_stack_declines_param_block_typesthat does not exist in the tree (the pins live inissue_1093_param_block_decline.rs).tests/spec-testsuiteis a submodule not initialized in worktrees; the reach probe read the root checkout's copy.Commits (all signed): oracle mode (behaviour-identical, negative control) → block → if (+ alias finding, oracle strengthened red-first) → loop → #973 sweep guard retired with its discharge recorded.
🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L