Skip to content

RQ-59-SUBTRACT (#242): increment 6 — six Rocq-proved rules (74 -> 80), every superseded arm DELETED; selector 18,291 -> 18,278, wildcards 56 -> 55 - #1029

Merged
avrabe merged 7 commits into
mainfrom
feat/subtract-v59-242
Aug 21, 2026
Merged

RQ-59-SUBTRACT (#242): increment 6 — six Rocq-proved rules (74 -> 80), every superseded arm DELETED; selector 18,291 -> 18,278, wildcards 56 -> 55#1029
avrabe merged 7 commits into
mainfrom
feat/subtract-v59-242

Conversation

@avrabe

@avrabe avrabe commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

VCR-SEL-001 increment 6. Six new Rocq-proved rules (74 → 80, all Qed, stated
directly about the generated model per #667), each landing WITH the deletion
of the hand-written emission it supersedes
— never alongside. One delegation
attempt was REFUSED on the byte-identity rule and is documented below.

Ratchet, before → after

metric before (this lane's base) after Δ
selector_lines_code (must FALL) 18,291 18,278 −13
selector_lines_total (track) 28,912 28,899 −13
selector_wildcard_arms_code (must FALL) 56 55 −1 (back at baseline)
selector_wildcard_arms_total (track) 91 90 −1
sel_dsl_rules (must RISE) 74 80 +6

All movements banked in claims.yaml in the commits that caused them (the
lines waiver re-derived at 18,278, carrying forward the two waived v0.59
soundness growths #989/#990 minus this fall).

Per commit

  1. db7e0e2 — increment-6 rules, byte-neutral. 5 new rules + 5 Qed:
    rule_i32_extend8_s / rule_i32_extend16_s (new SXTB/SXTH model
    constructors; semantics are Definitions via I32 shifts, not axioms
    axiom count unchanged at 93) and rule_i64_extend{8,16,32}_s (new
    I64Extend{8,16,32}SPseudo constructors, rd_hi <> rd_lo Ok-or-Err).
    Selector untouched; model coverage re-banked (simplified-only 68 → 73,
    uncovered stays 4: B/BL/BX/VMOV).
  2. f16724d — delete the family's hand-written arms (one group commit per
    the RETIRE one-op-or-group rule; per-op commits would each carry a
    wrong-way waiver the next commit obsoletes). Deleted: sws
    I32Extend8S/I32Extend16S ArmOp::Sxtb/Sxth pushes; the sws
    I64Extend{8,16,32}S construction match including its
    _ => unreachable!() wildcard
    ; sd's five fixed-register vec arms.
    Byte-identity: the prior corpus had zero extendN_s coverage — the
    manifest could not have discriminated exactly these arms — so
    sign_extend_family.wat was added first (every converted arm fires,
    both selector paths, baseline rows captured at the pre-deletion binary).
    Then: 704-row corpus manifest (176 fixtures × 4 configs — m4f/m4/r5
    relocatable + m4f self-contained; 633 OK .text sha256 + 67 declines
    pinned with exit code and reason) identical to the pre-deletion baseline,
    704/704; 10/10 frozen anchors green.
  3. fe19fd2 — sd I64ExtendI32S / I32WrapI64 delegated to their
    existing increment-5 rules (structurally identical ArmOp values; rules'
    delegation → Both). Corpus manifest 704/704 again — with the honest note
    that these sd arms are production-unreachable via compile paths (live via
    the pub select() API), so the structural identity plus the pinned
    generated-rule fixpoint carry the evidence there.
  4. 3af9e50rule_i64_const (80th rule). First rule over a dynamic i64
    immediate (new imm64 DSL concept: value: i64 / (v : I64.int) binder).
    Both selectors' hand-written ArmOp::I64Const constructions deleted.
    Corpus manifest 704/704 — and this one is a discriminating result:
    i64.const fires across the corpus's many i64 fixtures.
  5. 33278d2 — extraction snapshots refreshed. Found stale since feat(coq): flat-executor upgrade — SBCS, CMPcc, branching BCondOffset; I64SetCond expansion-tier T1; first #73 admit discharged (#242) #697
    (Integers.ml was missing the coq: i32_const_correct is Admitted (false as stated) — and BIN-VERIFY defers Const to it, so nothing covers i32.const #933 I32Const normalization and the
    signed-divs guard): regenerated with the same nix rocq CI uses, now
    carrying increment 6. No consumer, no freshness gate — wiring one is a
    policy call left to the hub.
  6. 4ede08a — rivet: RQ-59-SUBTRACT implemented.

Attempted and REFUSED (the rule working, not an omission)

  • sd I64ExtendI32U delegation — its rule lowers to the two-instruction
    MOV + MOVW form select_with_stack ships, while the sd path emits the single
    I64ExtendI32U pseudo. Different bytes, no execution oracle on that path →
    refused; the hand-written arm stays, refusal documented at the arm.
  • i64.extend32_srule_i64_extend_i32_s reuse (considered before
    building the pseudo rule): the encoders' ASR source registers differ
    (rnlo vs rdlo) — same value, different bytes when rdlo != rnlo
    refused; the family got its own pseudo-tier rules emitting the exact
    shipped ArmOps instead.

Execution evidence beyond byte-identity

#973 ARM corpus sweep run locally on the branch head: PASS
compiled 148/160, 2,502 emulated vectors (unicorn vs wasmtime), 0 mismatches,
0 faults, including sign_extend_family.wat's all-i32 export. Emulation floor
2,335 still cleared. EXPECTED_DECLINES untouched (declines byte-for-byte
identical in the manifest).

Gates (run before every push)

cargo fmt --check · cargo clippy --workspace --all-targets -- -D warnings
· cargo test --workspace (true exit 0; includes the 10 frozen anchors) ·
python3 scripts/claim_check.py claims.yaml 50/50 (+ --metric table above,
--emit-status surfaces regenerated) · python3 scripts/model_coverage_audit.py --check ok · bazel test //coq:verify_proofs
green (80-rule coverage gate included).

Refs #242

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

avrabe and others added 7 commits August 21, 2026 19:42
…q-proved rules (74 -> 79), byte-neutral (#242)

Rules + proofs only; the selector is untouched in this commit (the arm
deletions each follow one-per-commit so a bisect lands on one op):

  rule_i32_extend8_s / rule_i32_extend16_s — single REAL instructions
  (new SXTB/SXTH model constructors);
  rule_i64_extend8_s / rule_i64_extend16_s / rule_i64_extend32_s —
  single narrow pseudo-ops (new I64Extend{8,16,32}SPseudo constructors,
  same modeling tier as the increment-3 pair pseudo-ops), each carrying
  the rd_hi <> rd_lo side condition Ok-or-Err.

Semantics are DEFINITIONS, not axioms: sxtb_val/sxth_val are expressed
with the I32 shift primitives (shl then shrs — the WASM-spec shape of
extendN_s), and the pseudo high fill is the concrete I32.shrs _ 31. The
axiom count is unchanged (93; arm_semantics_axioms still 72). Theorems
are value-level T1, stated CONCRETELY via the shifts, 5/5 Qed on the
generated model per #667 (rule_X := Gen.rule_X).

Byte-neutral: no selector emission changes; generated.rs gains 5
functions nothing calls yet. bazel test //coq:verify_proofs green
(incl. the 79-rule coverage gate); model coverage re-banked
(simplified-only 68 -> 73, uncovered stays 4: B/BL/BX/VMOV);
claim_check 50/50; cargo test --workspace exit 0.

Refs #242

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…n arms — the 5 new rules are the only path, byte-identical

The deleted unit is the FAMILY (RETIRE's one-op-or-group-per-commit rule;
per-op commits would each carry a wrong-way waiver the next commit
obsoletes — the family shares one oracle run and the fixture's per-op
exports discriminate a bisect):

  select_with_stack: the I32Extend8S / I32Extend16S ArmOp::Sxtb/Sxth
  pushes and the I64Extend{8,16,32}S construction match INCLUDING its
  '_ => unreachable!()' wildcard (the same class as RETIRE's seven);
  select_default: the five fixed-register vec arms (Sxtb/Sxth +
  the three (R0,R1,R0) narrow pseudos, rd_hi<>rd_lo satisfied).

Emission now flows through i32_extend_rule / i64_extend_narrow_rule
(Ok-or-Err on the rd_hi <> rd_lo side condition, never silent).

BYTE-IDENTITY EVIDENCE:
  - the prior corpus had ZERO extendN_s coverage — the manifest could not
    have discriminated exactly these arms — so sign_extend_family.wat is
    ADDED FIRST (every converted arm fires on both selector paths; its
    baseline rows were captured at the pre-deletion binary);
  - 704-row corpus manifest (176 scripts/repro fixtures x 4 configs:
    m4f/m4/r5 relocatable + m4f self-contained; 633 OK .text sha256 +
    67 declines pinned with exit code and reason) identical to the
    pre-deletion baseline, 704/704 rows;
  - all 10 frozen anchors green (cargo test).

Ratchet: selector code region 18,291 -> 18,279 (-12: -33 deleted vs +21
rule-delegation scaffolding), wildcards 56 -> 55 (back at baseline),
whole file 28,912 -> 28,900. Banked in claims.yaml (waiver re-derived at
18,279 carrying forward the two waived v0.59 soundness growths).

Gates: fmt, clippy -D warnings, cargo test --workspace exit 0,
claim_check 50/50 (+ --metric), model_coverage_audit --check ok.

Refs #242

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…rapI64 to their increment-5 rules; I64ExtendI32U delegation REFUSED

Deletes the last two hand-written width-conversion constructions in
select_default: both arms built the exact single pseudo ArmOp their
existing Rocq-proved rules return (rule_i64_extend_i32_s(R0,R1,R0) —
rd_hi <> rd_lo satisfied — and rule_i32_wrap_i64(R0,R0)), so the
delegation is STRUCTURALLY identical ArmOp-for-ArmOp, and the rules'
delegation field moves SelectWithStack -> Both.

REFUSED, on the byte-identity rule: I64ExtendI32U. Its rule lowers to
the two-instruction MOV + MOVW form select_with_stack ships, while this
path emits the single I64ExtendI32U pseudo — different bytes without an
execution oracle proving them, so the hand-written arm STAYS and the
refusal is documented at the arm.

Byte-identity: 704-row corpus manifest identical to the pre-deletion
baseline (704/704; these sd arms are production-unreachable via compile
paths — live via the pub select() API — so the manifest cannot
discriminate them and the structural argument above plus the pinned
generated-rule fixpoint carry the evidence); 10/10 frozen anchors green.

Ratchet: code region 18,279 -> 18,278, whole file 28,900 -> 28,899;
banked. Gates: fmt, clippy -D warnings, cargo test --workspace exit 0,
claim_check 50/50, model_coverage_audit --check ok.

Refs #242

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…and-written I64Const constructions deleted, byte-identical

The first rule over a dynamic i64 immediate parameter: the DSL gains the
imm64 concept (trailing 'value: i64' in the generated Rust, universally
quantified '(v : I64.int)' binder in the generated Rocq — the 64-bit
sibling of increment 5's imm concept). One pseudo-op; the encoder owns
the MOVW/MOVT half expansion, the rule owns the selector's emission
decision, with the rd_hi <> rd_lo side condition Ok-or-Err.

rule_i64_const_correct (Qed, 80/80): results pinned to the WASM-spec
halves via the i64_const_lo/hi result-correspondence spec axioms
(lo_of_i64/hi_of_i64) — the same tier as the other i64 pseudo theorems,
no new axiom.

DELETED: select_with_stack's ArmOp::I64Const construction (the
consecutive-pair emission) and select_default's fixed (R0,R1) vec arm.

Byte-identity: 704-row corpus manifest identical to the pre-deletion
baseline 704/704 — and unlike the sd-only c3, this one is a
DISCRIMINATING result: i64.const fires across the corpus's many i64
fixtures on the relocatable path. 10/10 frozen anchors green.

Ratchet: code region unchanged at 18,278 (sws scaffolding +5 vs sd -5),
rules floor 79 -> 80, banked. Gates: fmt, clippy -D warnings,
cargo test --workspace exit 0, claim_check 50/50 (+ --emit-status),
model_coverage_audit re-banked and --check ok,
bazel test //coq:verify_proofs green.

Refs #242

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…nce #697, now carrying increment 6

Regenerated CompilerExtract.v's Separate Extraction output with the SAME
nix rocq toolchain //coq:verify_proofs uses. The snapshots were last
extracted 2026-07-10 (#697) and had silently gone stale against the
sources CI proves: Integers.ml was missing the #933 I32Const
model-boundary normalization AND the signed-divs overflow-guard fix
(the .v files changed, the extraction never followed — no consumer, no
gate, exactly the drift class the claim gate exists for; noted in the
PR as a residual since wiring a freshness gate for an unconsumed
artifact is a policy call, not this lane's).

Now current: SXTB/SXTH + sxtb_val/sxth_val, the three
I64Extend{8,16,32}SPseudo arms, and the catch-up from the intervening
proof work. Byte-invisible to the compiler (nothing builds these .ml
files); cargo/claim gates untouched and green.

Refs #242

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

Refs #242

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…rule_i64_const landed after the header was written)

Refs #242

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

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.78313% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
crates/synth-synthesis/src/sel_dsl/generated.rs 91.30% 4 Missing ⚠️
crates/synth-synthesis/src/sel_dsl/mod.rs 95.83% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@avrabe
avrabe merged commit 16b135b into main Aug 21, 2026
61 checks passed
@avrabe
avrabe deleted the feat/subtract-v59-242 branch August 21, 2026 19:10
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