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
Conversation
…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 Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
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
selector_lines_code(must FALL)selector_lines_total(track)selector_wildcard_arms_code(must FALL)selector_wildcard_arms_total(track)sel_dsl_rules(must RISE)All movements banked in
claims.yamlin the commits that caused them (thelines waiver re-derived at 18,278, carrying forward the two waived v0.59
soundness growths #989/#990 minus this fall).
Per commit
rule_i32_extend8_s/rule_i32_extend16_s(newSXTB/SXTHmodelconstructors; semantics are Definitions via I32 shifts, not axioms —
axiom count unchanged at 93) and
rule_i64_extend{8,16,32}_s(newI64Extend{8,16,32}SPseudoconstructors,rd_hi <> rd_loOk-or-Err).Selector untouched; model coverage re-banked (simplified-only 68 → 73,
uncovered stays 4: B/BL/BX/VMOV).
the RETIRE one-op-or-group rule; per-op commits would each carry a
wrong-way waiver the next commit obsoletes). Deleted: sws
I32Extend8S/I32Extend16SArmOp::Sxtb/Sxthpushes; the swsI64Extend{8,16,32}Sconstruction 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.watwas 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
.textsha256 + 67 declinespinned with exit code and reason) identical to the pre-deletion baseline,
704/704; 10/10 frozen anchors green.
I64ExtendI32S/I32WrapI64delegated to theirexisting increment-5 rules (structurally identical ArmOp values; rules'
delegation →
Both). Corpus manifest 704/704 again — with the honest notethat these sd arms are production-unreachable via compile paths (live via
the pub
select()API), so the structural identity plus the pinnedgenerated-rule fixpoint carry the evidence there.
rule_i64_const(80th rule). First rule over a dynamic i64immediate (new imm64 DSL concept:
value: i64/(v : I64.int)binder).Both selectors' hand-written
ArmOp::I64Constconstructions deleted.Corpus manifest 704/704 — and this one is a discriminating result:
i64.const fires across the corpus's many i64 fixtures.
(
Integers.mlwas 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 thesigned-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.
Attempted and REFUSED (the rule working, not an omission)
I64ExtendI32Udelegation — its rule lowers to the two-instructionMOV + MOVW form select_with_stack ships, while the sd path emits the single
I64ExtendI32Upseudo. Different bytes, no execution oracle on that path →refused; the hand-written arm stays, refusal documented at the arm.
i64.extend32_s→rule_i64_extend_i32_sreuse (considered beforebuilding the pseudo rule): the encoders' ASR source registers differ
(
rnlovsrdlo) — same value, different bytes whenrdlo != rnlo→refused; the family got its own pseudo-tier rules emitting the exact
shipped ArmOps instead.
Execution evidence beyond byte-identity
#973ARM 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 floor2,335 still cleared.
EXPECTED_DECLINESuntouched (declines byte-for-byteidentical 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.yaml50/50 (+--metrictable above,--emit-statussurfaces regenerated) ·python3 scripts/model_coverage_audit.py --checkok ·bazel test //coq:verify_proofsgreen (80-rule coverage gate included).
Refs #242
🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L