Skip to content

RQ-58-RETIRE (#242): delete the hand-written arms the 50 Rocq-proved DSL rules replaced (-1,312 lines, byte-identical) - #999

Merged
avrabe merged 35 commits into
mainfrom
feat/retire-dsl-covered-arms-242
Aug 19, 2026
Merged

RQ-58-RETIRE (#242): delete the hand-written arms the 50 Rocq-proved DSL rules replaced (-1,312 lines, byte-identical)#999
avrabe merged 35 commits into
mainfrom
feat/retire-dsl-covered-arms-242

Conversation

@avrabe

@avrabe avrabe commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

RQ-58-RETIRE (#242) — delete the hand-written arms the 50 Rocq-proved DSL rules replaced

The headline deletion, and it was byte-identical throughout — no finding of the
"flip does not cover what it claims" class surfaced.
All 36 flag-guarded sites
(21 select_default + 15 select_with_stack) collapsed to their Rocq-proved
sel_dsl rule call, one op/group per commit so a bisect lands on a single op;
then the SYNTH_SEL_DSL/SYNTH_NO_SEL_DSL lever and the four mirror-pin tests
retired as vacuous (the VcrSelRulesGenCheck precedent — a byte-equality gate
with one implementation left proves reflexivity).

The ratchet moves DOWN for the first time

metric main this PR Δ
selector_lines_code (ceiling) 18,582 17,897 −685
selector_wildcard_arms_code (ceiling) 63 56 −7
selector_lines_total (track) 29,839 28,495 −1,344
selector_wildcard_arms_total (track) 106 91 −15
sel_dsl_rules (floor) 50 50 0

claims.yaml carries the live values, both improvements banked into
baseline:, and the two former #992 waivers are deleted with the re-bank (a
surviving waiver above the new baseline is a standing licence to grow back to
it). status.json regenerated via --emit-status. claim_check 49/49.

Byte-identity evidence, per commit

Every commit was gated on:

  • a 688-row corpus manifest — all 156 scripts/repro/*.wat + the 4 frozen
    .wasm anchors × 4 configs (cortex-m4f/cortex-m4 relocatable,
    cortex-m4f self-contained, cortex-r5 relocatable), sha256 of the full
    output ELF, declines pinned as rows too — diff-identical against the
    origin/main baseline binary on every one of the 35 commits;
  • the 10 frozen anchors (frozen_codegen_bytes, 10 passed; 0 failed
    asserted non-vacuously per commit).

The 7 wildcard arms deleted from the code region were all _ => unreachable!()
arms inside deleted hand-written bodies (condition maps and group dispatches);
the other 8 total-count wildcards were assertion helpers inside the retired
mirror-pin tests.

Ops retired (lines deleted per commit, selector file only)

select_default (all 30 DSL-wired sd ops): i32 add −18/+8 (incl. the block-comment
rewrite), sub −11, mul −7, and −11, or −11, xor −11, shl −23/+6, shr_s −19/+2,
shr_u −19/+2, rotl −17/+6, rotr −7, clz −12/+4, ctz −8, popcnt −10; i64 and −26/+9,
or −26/+9, xor −26/+9, comparisons×10 (group arm) −41/+12.

Both selectors in one commit (same op): i64 add −68/+24, sub −58/+17,
eqz −31/+7.

select_with_stack group/single arms: i64 {or,and,xor} −68/+13,
{shl,shr_u,shr_s} −44/+12, comparisons×10 −40/+7, mul −24/+12, {rotl,rotr} −29/+8,
{clz,ctz,popcnt} −32/+11; i32 comparisons×10 (flag conditioning only, see
residual) −11/+8, eqz −32/+8, {shl,shr_s,shr_u,rotr} −62/+8, clz −19/+6,
ctz −24/+7, popcnt −18/+6.

Final functional commit (lever + mirror-pins): −753/+44. Whole PR:
+345/−1,657 (net −1,312).

The not-yet-deletable residual (RQ-58-SPLIT input) — measured, complete

Covered ops whose per-path arm was never DSL-wired, so nothing there was
superseded (deleting them would change bytes, which this lane refuses):

  • select_with_stack (the direct/--relocatable path — live in production):
    • I32Add/Sub/Mul/And/Or/Xor — large hand-written arms carrying the
      foldable_addsub_imm/foldable_bitwise_imm immediate folds; the DSL's
      reg-reg rules don't express the imm shapes, so no hook was ever wired.
    • I32Rotl — hand-written RSB+ROR with an allocated scratch; rule_i32_rotl
      exists (it is the sd lowering) but was never wired here.
    • the i32-comparison imm-fold fallback (selector: emit cmp/cmn immediates for compare bounds instead of materializing — flat_flight clamps (lever #3) #258 cmp a,#C / cmn a,#-C +
      SetCond) — the reg-reg case of the shared arm now takes i32_cmp_rule
      unconditionally, but no CmpImm-shaped rule exists, so the fold's emission
      stays hand-written; re-pinned by the rewritten
      cmp_imm_fold_residual_path_stays_handwritten_258 (fold fires, reg-reg
      rule path provably not taken).
  • select_default (production-unreachable for these ops — select_with_stack
    matches all 50 covered ops before its _ => fallthrough, so they can only be
    reached via the pub select() API used by tests/benchmarks):
    • blind bare-Cmp I32Eq..I32GeU and I32Eqz arms (never materialize the
      0/1 result — the documented increment-2 holdout; a rule byte-matching them
      would be unprovable as T1);
    • fixed-pair I64Mul/Shl/ShrU/ShrS/Rotl/Rotr/Clz/Ctz/Popcnt pseudo-op arms.

Note the direction: --relocatable forces the direct selector
(select_with_stack, #197) — direct ≠ default; the residual above is stated
against the correct path assignment.

Step 5 — witness MC/DC (#978): checked, not assumed

The harness links synth-synthesis (via synth-backend-riscv), so the wasm
binary DOES change — the counts were measured, not waved off. Ran the real gate
(scripts/mcdc_run.sh + scripts/mcdc_gate.py, witness-mcdc, rustc 1.96.1
— the pinned measurement compiler) on this branch AND on a pristine
git archive origin/main export, same host:

  • TOTAL identical in both runs: 26 dec · 9 full · 122 cond · 50 proved ·
    21 gap · 51 dead.
    The only diff between the two gate outputs is witness's
    internal row indices (wasm layout shifted); every scored count, every
    per-function row and every gap row (read, per the loop's rule) is
    identical. No decision moved: the deleted decisions live in
    synth_synthesis::instruction_selector, which mcdc_gate.py names as
    explicitly out of scope (its SCORED_PREFIXES).
  • The local absolutes differ from the CI floors (130/57/50) on both main
    and branch equally — the documented darwin-vs-CI platform delta the gate's
    own doc anticipates ("read the DELTA locally; the floors are the CI
    platform's baseline"). Delta = zero; the CI job scores the same tree-state
    inputs it scores on main.

Step 6 — sigil: not applicable, with the reason stated

This lane lands no new build artifact and no new build stage — it deletes
code inside an existing crate and proves the shipped binaries byte-identical to
baseline across the 688-row corpus. There is nothing new to sign and the
attestation surface is unchanged. Stated per the loop's rule rather than marked
N/A silently; if this reason recurs a third lane running, file it.

Gates (all run without pipes, rc captured)

  • cargo test --workspace — rc=0, 2,826 tests / 142 suites, 0 failures
  • cargo clippy --workspace --all-targets -- -D warnings — rc=0
  • cargo fmt --check — rc=0
  • python3 scripts/claim_check.py claims.yaml — rc=0, 49/49
  • No CHANGELOG edit, no version bump, no hand-edited generated files
    (status.json via --emit-status; sel_dsl/generated.rs and the emitted
    Rocq model untouched — the RULES table, including its Delegation metadata
    the generation consumes, is unchanged). No new .watfix(#973): ARM select on an i64-comparison returns the then-arm — and an ARM leg for the corpus CI never compiled #992's
    EXPECTED_DECLINES exact set unaffected.

rivet: RQ-58-RETIREimplemented with evidence + the residual set;
verified-codegen-roadmap.yaml VCR-SEL-001 entry carries the dated landing
paragraph.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

avrabe and others added 30 commits August 19, 2026 05:53
The Rocq-proved rule_i32_add is the shipped lowering since the default-on
flip; the superseded arm is deleted. Byte-identity: 688-row corpus manifest
(156 fixtures x 4 configs incl. declines) identical to origin/main baseline;
all 10 frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Same evidence as i32.add: 688-row corpus manifest identical to the
origin/main baseline; all 10 frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
The Rocq-proved rule carries the #682 mod-32 R12 mask. 688-row corpus
manifest identical to the origin/main baseline; all 10 frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
One op, both selectors: the select_default fixed-pair arm and the
select_with_stack allocated-pair arm each collapse to the Rocq-proved
rule_i64_add call that has been the shipped path since the flip. 688-row
corpus manifest identical to the origin/main baseline; all 10 frozen
anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…tor arm

One grouped select_with_stack arm serves the three i64 bitwise ops via the
shared i64_pair_rule dispatch, so the deletion unit is the group (its
select_default counterparts were retired per-op in the three previous
commits). Also removes the group's '_ => unreachable!()' wildcard arm.
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…fault arm

One grouped arm serves the ten binary i64 comparisons via the shared
i64_setcond_rule dispatch, so the deletion unit is the group. Also removes
the group's '_ => unreachable!()' condition-map wildcard arm. 688-row
corpus manifest identical to the origin/main baseline; all 10 frozen
anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…selector arm

One grouped select_with_stack arm serves the three i64 variable shifts via
the shared i64_pair_bin_rule dispatch; the deletion unit is the group. Also
removes the group's '_ => unreachable!()' wildcard arm. 688-row corpus
manifest identical to the origin/main baseline; all 10 frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…he direct selector

PARTIAL by design, and named as residual: this grouped arm is dual-use.
The reg-reg case now takes the Rocq-proved i32_cmp_rule unconditionally;
the #258 cmp/cmn imm-fold case has no DSL rule (no CmpImm-shaped rule
exists), so its hand-written Cmp+SetCond fallback emission STAYS and is
enumerated in the RQ-58-SPLIT residual set rather than deleted. 688-row
corpus manifest identical to the origin/main baseline; all 10 frozen
anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…rect-selector arm

One grouped select_with_stack arm serves the four register shifts/rotates
via the shared i32_shift_rule dispatch; the deletion unit is the group.
The generated rules carry the #682 mod-32 R12 mask themselves. Also
removes the group's '_ => unreachable!()' wildcard arm. 688-row corpus
manifest identical to the origin/main baseline; all 10 frozen anchors
green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…lector arm

One grouped select_with_stack arm serves the ten binary i64 comparisons
via the shared i64_setcond_rule dispatch; the deletion unit is the group.
Also removes the group's '_ => unreachable!()' condition-map wildcard arm.
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
avrabe and others added 5 commits August 19, 2026 06:09
688-row corpus manifest identical to the origin/main baseline; all 10
frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…or arm

One grouped select_with_stack arm serves both rotates via the shared
i64_rot_rule dispatch; the deletion unit is the group. Also removes the
group's '_ => unreachable!()' wildcard arm. 688-row corpus manifest
identical to the origin/main baseline; all 10 frozen anchors green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…elector arm

One grouped select_with_stack arm serves the three i64 bit-counts via the
shared i64_unary_count_rule dispatch; the deletion unit is the group. Also
removes the group's '_ => unreachable!()' wildcard arm. 688-row corpus
manifest identical to the origin/main baseline; all 10 frozen anchors
green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…-pin gates

With every superseded arm deleted there is no second implementation for the
flag to select: the sel_dsl field, sel_dsl_from_env (SYNTH_SEL_DSL /
SYNTH_NO_SEL_DSL), and set_sel_dsl are dead code and go. The four
mirror-pin tests (sd + sws + i64-pair + defaults-on) compared the two paths
byte-for-byte; with one path left they are vacuous — retired on the same
grounds as the VcrSelRulesGenCheck reflexivity gate (see coq/STATUS.md).
The #258 imm-fold holdout test is REWRITTEN, not deleted: the residual
hand-written Cmp/Cmn+SetCond emission it pins survived the retirement
(cmp_imm_fold_residual_path_stays_handwritten_258). The RULES table —
including its Delegation wiring metadata that the Rocq generation and the
manifest gates consume — is untouched.

Byte-identity: 688-row corpus manifest identical to the origin/main
baseline; all 10 frozen anchors green; synth-synthesis suite 732+ green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
claims.yaml: selector_lines_code 18582 -> 17897 (banked), wildcard_arms_code
63 -> 56 (banked), totals tracked 29839 -> 28495 / 106 -> 91; the two former
#992 waivers deleted with the re-bank (a waiver above the new baseline is a
standing licence to grow back). status.json regenerated via --emit-status.
CLAUDE.md / coq/STATUS.md / verified-codegen-roadmap.yaml no longer claim
the SYNTH_NO_SEL_DSL opt-out exists; rivet RQ-58-RETIRE -> implemented with
evidence + the measured residual set. claim_check 49/49.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe
avrabe merged commit 37457ac into main Aug 19, 2026
109 of 114 checks passed
@avrabe
avrabe deleted the feat/retire-dsl-covered-arms-242 branch August 19, 2026 06:38
avrabe added a commit that referenced this pull request Aug 19, 2026
…m folds, width conversions, select family — each deleting the hand-written emission it supersedes (#1004)

* feat(vcr-sel-001): increment-5 DSL shapes — dynamic-imm operand class, mov/movw, wrap/extend pseudos, SelectMove (#242)

Infrastructure only: new TemplateOp shapes + RegVar::Rc + the derived
imm-param concept (a rule whose sequence reads the dynamic immediate gets a
trailing `imm: i32` parameter in the generated Rust and a universally
quantified `(imm : I32.int)` binder in the generated Rocq definition).
No rules use the shapes yet — generated.rs and VcrSelRulesGenerated.v are
byte-unchanged.

SelectMove is modeled by the flat model's existing MOV<cc> constructors (the
same family SetCond expands to) — no ARM-model extension needed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: rule_i32_add_imm — the ADDW-fold emission moves to a Rocq-proved rule; hand-written ArmOp::Add construction deleted (#242)

51st rule (increment 5): `i32.add` folded-const form `ADD rd, rn, #imm`,
universally quantified over the immediate. select_with_stack's I32Add arm now
emits BOTH forms through rules (rule_i32_add_imm / rule_i32_add — delegation
Both); the fold guard stays selector-owned. Value-level T1 theorem
rule_i32_add_imm_correct (Qed) in VcrSelRules.v, definition re-exported from
the generated model per #667.

Byte-identity: frozen_codegen_bytes 10/10 green; synthesis lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: rule_i32_sub_imm — SUBW-fold emission to a Rocq-proved rule, hand-written ArmOp::Sub construction deleted (#242)

52nd rule. Same shape as rule_i32_add_imm: value-level T1 Qed, both
select_with_stack emission paths through rules, delegation Both.
frozen_codegen_bytes 10/10; synthesis lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: rule_i32_and_imm — bitwise-byte fold emission to a Rocq-proved rule, hand-written ArmOp::And construction deleted (#242)

53rd rule. Value-level T1 Qed; delegation Both; frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: rule_i32_or_imm — bitwise-byte fold emission to a Rocq-proved rule, hand-written ArmOp::Orr construction deleted (#242)

54th rule. Value-level T1 Qed; delegation Both; frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: rule_i32_xor_imm — bitwise-byte fold emission to a Rocq-proved rule, hand-written ArmOp::Eor construction deleted (#242)

55th rule. Value-level T1 Qed; delegation Both; frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* refactor(vcr-sel-001): wire rule_i32_mul in select_with_stack — hand-written ArmOp::Mul construction deleted (#242)

No new rule; the existing Rocq-proved rule becomes the only i32.mul
emission on the direct path too (delegation Both). Byte-identical:
frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* refactor(vcr-sel-001): wire rule_i32_rotl in select_with_stack — hand-written RSB+ROR emission deleted (#242, #999 residual)

No new rule; closes the 'unwired I32Rotl' item from RQ-58-RETIRE's residual
list. Delegation Both. Byte-identical: frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: 10 comparison-immediate rules (rule_i32_eq_imm..ge_u_imm) — the #258 fold's positive half moves to Rocq-proved rules (#242)

Rules 56-65. cmp rn,#C; SetCond over the dynamic immediate, one rule per
relation, same flag lemmas as the reg-reg family (eval_operand2 (Imm imm) =
imm, so every compute_*_flag lemma instantiates with v2 := imm). The
hand-written Cmp-imm emission in the shared comparison arm is deleted; the
NEGATIVE (cmn) half stays as the named residual — its add-derived NZCV needs
a sub/add flag-correspondence lemma family the model does not carry.
The #258 pin test is reworked per its own doc: positive probe asserts the
imm-Cmp rule shape, negative probe pins the cmn residual.

frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: width-conversion rules — i32.wrap_i64, i64.extend_i32_s/_u (+ in-place variant); hand-written emissions deleted (#242)

Rules 66-69. wrap and extend_i32_s at the pseudo-op tier
(I32WrapI64Pseudo / I64ExtendI32SPseudo — the sign-extended high half pinned
to the concrete I32.shrs rn 31 via i64_extend_s_hi_spec); extend_i32_u is the
real two-instruction MOV lo + MOVW hi,#0 shape. The selector's
register-coincidence elision (val == dst_lo skips the MOV) becomes DISPATCH
between two proven rules — the in-place theorem pins the low half under the
rd_hi <> rn hypothesis the elision relies on, so the hazard the hand-written
comment described is now a machine-checked side condition.

frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* feat(vcr-sel-001)!: 5 select rules — every CMP+IT;MOV select emission in BOTH selectors moves to Rocq-proved rules (#242)

Rules 70-74: rule_i32_select (fresh dst), rule_i32_select_inplace,
rule_i64_select (pair, 4 moves), rule_i64_select_inplace (pair, NE-only —
the f64 bit-pattern shape), rule_i32_select_default (MOV + EQ-override, the
select_default shape). ArmOp::SelectMove is modeled by the flat model's
MOV<cc> family (the constructors SetCond's expansion already uses): one CMP
latches NZCV and no conditional move writes flags, so a single compare
governs the whole sequence — the property the hand-written arm argued in a
comment after the gale br_table flag-clobber bug is now the theorem.

Five emission sites deleted: select_default's Select arm,
select_with_stack's integer fresh/in-place forms, the wide i64 pair form,
and the f32/f64 bit-pattern cores. The in-place/fresh and width choices
stay selector-owned as dispatch between proven rules; the pair aliasing
constraints the old comments argued by construction are now machine-checked
side conditions (Ok-or-Err).

frozen 10/10; cmp-select census + two-move coverage green; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* refactor(vcr-sel-001): wire the 9 select_default fixed-pair i64 arms to their existing rules; generator made a rustfmt fixpoint again (#242)

No new rules. I64Mul/Shl/ShrU/ShrS, I64Rotl/Rotr and I64Clz/Ctz/Popcnt in
select_default hand-constructed the same pseudo-ops their Rocq-proved rules
emit — now the rules are the only path there too (fixed R0..R3 pairs,
delegation Both; the in-place R0:R1 shape satisfies the pair side
conditions, Err stays loud).

Generator fixpoint repair: two increment-5 renders drifted from rustfmt
(the short I32WrapI64 literal collapses under struct_lit_width; a
side-condition Err message crossing max_width wraps) — the two prior
commits carried that transient generated-file drift, closed here by making
the generator mirror rustfmt for both shapes.

frozen 10/10; lib 732/732.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* proof(vcr-sel-001): select-rule discharge — iterative conditional-chain reduction + flags_set_reg lemma; //coq:verify_proofs green (#242)

The select rules are the first multi-conditional sequences in the table: a
MOV<cc>'s exec sits under the PREVIOUS instruction's match binder, so its
flag read only becomes concrete after the previous conditional resolves —
one pre-pass (the increment-2 style) cannot rewrite it. Discharge is now a
progress-guarded iteration (select_step: restricted cbn + flag-projection
rewrites + the destructed compare equation), plus the missing
ArmState.flags_set_reg projection lemma (set_reg never touches flags — the
machine-checked form of the "IT;MOV preserves the CMP flags" argument).

bazel test //coq:verify_proofs PASSED — all 74 rule theorems Qed, coverage
gate green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* chore(ledger): bank increment 5 — sel_dsl_rules floor 50 -> 74, selector ceiling 17,991 -> 17,912; docs + status regen (#242)

Ratchets (claim_check 49/49):
- sel_dsl_rules (floor, up): 50 -> 74, banked (baseline 74).
- selector_lines_code (ceiling, down): 17,991 -> 17,912 (-79); the #946
  waiver shrinks to the new value with an amended reason (24 rules took
  back 79 of its +94; residual 15 above the 17,897 baseline is the
  justified wasm_stack_effect enumeration).
- selector_lines_total (track): 28,599 -> 28,533.

Docs moved with the ledger: CLAUDE.md (617 Qed / 2 Admitted; 74 rules /
74 Qed / 54 covered ops; increments 1-5), coq/STATUS.md (headline + the
per-file rows summing exactly to 617; per-op-family table: i64
wrap/extend and select now DSL-served, totals 54 (35%) / 82 (53%) /
19 (12%); simplified-basis 74 of 74 — the honest #682-class debt GROWS
with the rule count and is counted, not hidden), status.json +
FEATURE_MATRIX regenerated via --emit-status.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* docs(sel-dsl): module + generated-file headers name increment 5 (#242)

Regenerated outputs carry the increment-5 provenance line; no functional
change (generated function bodies untouched).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

* chore(#867): re-bank model-coverage census — 24 new DSL rules add VcrSelRulesGenerated.v as a proof source for 3 ops

The Claim Check job's freshness step (model_coverage_audit.py --check) is
separate from claim_check.py; the lane ran the latter green and missed this.

Purely additive provenance: no op changes tier. uncovered stays 4
(B/BL/BX/VMOV), simplified-only stays 68, so the counted trusted base is
unchanged. Refs #242.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant