RQ-60-CFOBLIG (#1057) inc 2: proof-inventory manifest — derive, don't guess theorem names (brif_correct is the 29th member of a class) - #1089
Merged
Conversation
…guess theorem names — brif_correct is the 29th member of a class, not a typo gale's fathom derives theorem names from WASM rule kinds by CamelCase->snake_case and asked us to rename brif_correct -> br_if_correct. Measured against the tree (reproduced independently), that rule FINDS 40 of the 138 wasm_instr constructors and MISSES 29 whose theorem exists under a FUSED name — every signed/unsigned div/rem/shift/comparison at both widths, plus BrIf. Renaming brif_correct alone buys consistency with 4 precedents and breaks it with 28 siblings; renaming all 29 re-establishes a hand-maintained naming convention for consumers to re-implement — the hand-written-mirror failure the North Star names. And the guess is worse than inconsistent: theorem names are not even unique (i64_shl_correct names BOTH the T1 result-correspondence theorem in CorrectnessI64.v and a T2 existence statement in CorrectnessI64Comparisons.v), and the *_correct suffix does not delimit the proof surface (the f32/f64/conversion/memory tier lives under *_executes, so a *_correct-only reading calls 69 proven-to-execute ops "absent" — my own first cut made exactly that error). So: a committed, machine-readable proof inventory manifest (artifacts/proof-inventory.json, schema synth-proof-inventory-v1) that consumers READ instead of guessing. scripts/proof_inventory.py derives it from the proof tree (the model_coverage_audit.py / #867 shape): * universe: wasm_instr constructors PARSED from WasmInstructions.v (never hand-listed), floor >= 100; * binding is SEMANTIC, never name-based: a theorem discharges a constructor when its statement applies exec_wasm_instr / compile_wasm_to_arm / singleton exec_wasm_seq to that constructor AND runs the ARM-side executor — the fused-vs-underscored split is deliberately irrelevant; * strength is SEMANTIC too: existence-only (bare `exists astate', ... = Some astate'`) vs result-correspondence — which exposes what the suffix hides (select_correct, drop_correct, nop_correct, local_tee_correct, global_{get,set}_correct are existence-only statements); * result today: 138/138 bound at Qed (absent = 0 — the "no proof at all" bucket in the briefing was an artifact of the *_correct-only reading), 63 result-correspondence, 75 existence-only. The honest frontier is strength, not absence. Drift gates (all demonstrated red-first, transcript in the PR): * proof_inventory.py --check byte-compares the committed artifact against re-derivation in the claim-check CI job — renaming brif_correct, or adding a theorem, without regenerating is RED (exit 1), not discovered downstream; * the manifest's own Qed re-count (_meta.cross_check.rocq_qed_total) is pinned EQUAL to the ledger's independent rocq_qed derivation (SYNTH-PROOF-INVENTORY-CROSSCHECK-1057, fields-equal) — the two textual readers of coq/Synth cannot silently disagree (hand-editing 630 -> 629 fails BOTH gates); * non-vacuity floors: a broken binding heuristic REFUSES to write (demonstrated: neutered ARM-side anchor -> "only 0 constructors bound (< 50) — refusing to green"). Honest residual, stated in the script and the artifact: this parser is a second reader of the proof tree and can say Qed about text the Rocq kernel would reject — the manifest is an index into `bazel test //coq:verify_proofs`, not a substitute for it. brif_correct is NOT renamed: once the manifest exists the name is not load-bearing, and the rename would churn a Qed'd proof file to satisfy a convention that holds for 40 of 138 constructors. Byte-invisible: no crate code touched; .text cannot move. Part of RQ-60-CFOBLIG (#1057); the coordinator handles the rivet status obligation serially at merge time. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
This was referenced Aug 27, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 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.
What gale asked, and what the measurement says instead
gale's
fathomderives theorem names from WASM rule kinds (CamelCase→snake_case) and asked us to renamebrif_correct→br_if_corrector document it as intentional. Reproduced independently (script committed as the generator itself), the guess against the 138wasm_instrconstructors and the tree's*_correcttheorems:i32_divs_correct,i32_shru_correct, …,brif_correct)*_correctat allbrif_correctis the 29th member of a class (every signed/unsigned div/rem/shift/comparison, both widths), not the odd one out. Renaming it alone trades one inconsistency for another; renaming all 29 re-establishes a hand-maintained naming convention for consumers to re-implement — the hand-written-mirror failure the North Star names.Two corrections to the briefing, found while building (the measurement changed the answer twice):
*_correctat all" are NOT a proof-absence frontier. Every one of them has a Qed'd*_executestheorem (the T2 existence tier: f32/f64, conversions, memory). A*_correct-only reading — mine included, in the first cut — calls 69 proven-to-execute ops "absent". Semantic result: 138/138 constructors bound at Qed; 63 result-correspondence, 75 existence-only. The honest frontier is strength, not absence.i64_shl_correctnames BOTH the T1 result-correspondence theorem (CorrectnessI64.v) and a T2 existence statement (CorrectnessI64Comparisons.v). Any name-keyed matcher is ambiguous on this tree; the (file, name) pair is the key. And the suffix lies in both directions —select_correct,drop_correct,nop_correct,local_tee_correct,global_{get,set}_correctare existence-only statements despite the_correctname.The deliverable
artifacts/proof-inventory.json(schemasynth-proof-inventory-v1, persynth-wcet-v1practice), generated byscripts/proof_inventory.py, freshness-gated in the claim-check CI job — themodel_coverage_audit.py/#867 shape, which is this repo's closest precedent (closer than the sel_dsl#[test], since the source here is.vtext, not a Rust table).Per entry: constructor, status (
qed/admitted/absent),result_correspondencebool, and every discharging theorem with file + terminator + strength.Design decisions (as briefed, decided and justified)
coq/Synth/**/*.v). Stated residual, in the script and in the artifact's_meta.honesty: the parser is a second reader — it can print Qed for text the kernel would reject, so the manifest is only meaningful alongside a greenbazel test //coq:verify_proofs. What bounds drift:_meta.cross_check.rocq_qed_totalre-countsQed.in this script's own code path and claims.yaml pins it EQUAL to the ledger's independentrocq_qedderivation (SYNTH-PROOF-INVENTORY-CROSSCHECK-1057,fields-equal) — disagreement between the two readers is RED, never hand-reconciled.artifacts/, next tomodel-coverage.json. A consumer fetchesraw.githubusercontent.com/pulseengine/synth/<tag>/artifacts/proof-inventory.json.WasmInstructions.v(floor ≥ 100, refuse-to-green on parser drift) — a hand-kept list would be one more mirror.brif_correctis NOT renamed. Once the manifest exists the name is not load-bearing, and the rename would churn a Qed'd proof file to satisfy a convention that holds for 40 of 138 constructors. No independent reason for the rename survived measurement.Binding is semantic, never name-derived: a theorem discharges a constructor when its statement applies
exec_wasm_instr/compile_wasm_to_arm/ singletonexec_wasm_seqto that constructor AND runs the ARM-side executor (exec_program/_br/_pc). WASM-side-only lemmas (WasmCertBridge refinements) and multi-instruction program examples deliberately do not bind. Strength is semantic too (bareexists astate', … = Some astate'= existence-only).Red-first transcript (all four, needle counted before/after each mutation)
brif_correct→br_if_correct(needle 3→0,br_if_correct0→3), no regeneration →--checkexit 1 (STALE or hand-edited). Restore → needle 3,ok.nop2_correctappended, needle 0→1), no regeneration →--checkexit 1. Restore →ok.rocq_qed_total630→629, needles verified) → both gates red:SYNTH-PROOF-INVENTORY-CROSSCHECK-1057fails withrocq_qed=630, proof_inventory_rocq_qed=629 — update every copy together, and--checkexits 1. Restore →52/52 claims hold.only 0 constructors bound (< 50) — refusing to green), writes nothing. Restore →ok.Gates
cargo fmt --all -- --check✅ ·cargo clippy --workspace --all-targets -- -D warnings✅ ·cargo test --workspace(running at PR-open; zero Rust files touched — will confirm before hand-off)python3 scripts/claim_check.py claims.yaml→ 52/52 (new claim included) ·--metric✅ ·test_claim_check.py✅ ·model_coverage_audit.py --check✅ ·artifact_citation_check.py✅ ·status_evidence_check.py→ 0 failures ✅.textcannot move.artifacts/status.jsonregenerated (--emit-status) for the newproof_inventory_rocq_qedcapture field — the visible-diff rule, same commit.Honest residual
//coq:verify_proofs) remains the only oracle for whether a Qed is real./\/get_reg/state_correspondence, would misclassify — none exist today); the per-entry theorem list is the audit trail.WasmOpenum — ops the model doesn't carry (memory.size, br_table, call, …) have no row. Extending the universe to the shipped enum (rows for unmodeled ops) is a named follow-up, not smuggled in here.claims.yamlwaiver- to: 18910carries a duplicatereason:key — a hand-merge swallowed the- to: 18288line of the RQ-59-I64SHIFT waiver, so under PyYAML last-wins the 18910 (VFPPRESSURE +622) waiver's effective reason is the I64SHIFT text and the 18288 waiver is invisible to the parsed ledger. Exactly the duplicate-key-strict-loader class from the v0.59 lessons; flagged to the coordinator.🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L