Repository navigation
feat(arbitration): ECH-05 fidelity evidence and belief/epi/sound verdict levels - #430
Conversation
…ratedVerdict
ECH-05 PR A. Agreement between backends says nothing about whether they
proved the same statement, so each ProverAttempt now carries
FidelityEvidence (KernelTranslation { format, checked_by, term_hash } |
DeclaredCorrespondence { consequence_tests, failures } | None) and
ArbitratedVerdict gains level (belief < epi < sound), retracted and
warranted_term.
Policy (fidelity_level): belief if the verdict needs review, rests on a
retracted backend, nothing was fused, or any attempt has no evidence;
sound only if every fused attempt is a kernel translation to the same
term_hash; epi if every fused attempt is a kernel translation or a
correspondence with >= 1 consequence test and 0 failures and the kernel
hashes agree; belief otherwise. ResultArbiter::retract marks a backend
unsound. exchange::ExchangeFormat names the six bridges and
exchange::term_hash gives a format-separated BLAKE3 term identity.
Numeric fusion is unchanged: tests/fixtures/arbitration_regression.json
was generated at 29b18ea (16 scenarios x 4 policies) and is replayed
against the new code, floats to 1e-12, with every verdict at belief.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3
…s hash equality ECH-05 PR B. `Level fused` is a closed sum (Belief | Epi | Sound) indexed by the evidence of the fused attempts; `Sound h` takes, for every fused attempt, a KernelAt h proof whose constructor carries the hash equality. A synonym collision, a declared correspondence or a missing certificate in the fused list therefore cannot be typed Sound, whatever produced the value (collisionNotSound, correspondenceNotSound, noEvidenceNotSound). `level` is the classifier, parametric in the hash type (DecEq only), with blockedIsBelief, noEvidenceIsBelief, failed/untestedCorrespondenceIsBelief, emptyFusedIsBelief, blockingNeverRaises, and evaluation controls (alignedPairIsSound, collisionPairIsBelief, mixedPairIsEpi). Total, no believe-me / postulate / admit. Epistemic-types (6a68de3) and residual-evidence-types (97244f5) are cited by pin, not consumed. Falsifier: tests/abi/accept/ArbitrationAligned.idr must type-check and tests/abi/reject/ArbitrationCollision.idr (the same file with one hash changed) must fail with a unification error; scripts/abi-fixtures.sh judges by output because `idris2 --check` exits 0 on a missing import. Wired into idris2-abi-ci.yml and `just abi-fixtures`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3
…ce and pair table ECH-05 PR C. tests/arbitration_fidelity_test.rs, under the portfolio, Bayesian and Dempster-Shafer policies: - synonym collision (Lean ℕ vs set.mm NN, aligned lexically): lexical only, kernel translations to different terms, a correspondence with a failed consequence test, and an untested correspondence all stay at belief while the numbers still say cross-checked; - MiniF2F mathd_numbertheory_3 (Lean and Isabelle statements checked against openai/miniF2F@4e433ff) with kernel translations to one term reaches sound; the same pair with an off-by-one translation does not; - retracting Lean lowers the two verdicts that rested on it, leaves the Isabelle + HOL Light verdict sound, and leaves the numbers unchanged. The exchange-layer terms are hand-written translation targets: the tests check the arbiter given certificates, not that certificates can be made. Docs: ROADMAP stage 6 acceptance is now "a KernelTranslation certificate is producible for a named backend pair" with a §3 row; the gap analysis names which backend pairs can share a term (all DESIGNED in ECHIDNA); the comparison doc and Guides describe the level; issues/README.md gains ECH-05 (not filed) and the labels it is missing; the issue body is drafted in issues/echidna-05-fidelity-evidence.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing: 20
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
CI:
Generated by Claude Code |
|
CI:
Generated by Claude Code |
…2) [stack 1/3] (#432) ## Summary Stack 1 of 3: follow-ups to #430 / ECH-05 (#431). This PR fixes the `cargo audit` failure, which is red on `main` and on every PR (both the `rust-ci / Cargo audit` and `Cargo Audit / Dependency audit` jobs). The RustSec database added five `quinn-proto` advisories after `main`'s last green audit on 2026-10-12: RUSTSEC-2026-0338, -0339, -0340, -0341 and -0342, two of them rated 7.5 high. `quinn-proto` is reached only through `reqwest` → `quinn 0.11.9`, an optional HTTP/3 path that the default build doesn't compile, but the audit scans the whole lockfile. ## Changes - `Cargo.lock` only: `quinn-proto` 0.11.15 → 0.11.19 via `cargo update -p quinn-proto`. `quinn` requires `^0.11.12`, so the bump is semver-compatible. It also pulls `rand 0.10`, `getrandom 0.4` and `rand_pcg` into `quinn-proto`'s subtree only. ## RSR Quality Checklist ### Required - [x] Tests pass (no code change; `cargo check --locked --workspace --all-targets` passes) - [x] Code is formatted (n/a, lockfile only) - [x] Linter is clean (n/a) - [x] No banned language patterns - [x] No `unsafe` blocks without `// SAFETY:` comments - [x] No banned functions - [x] SPDX license headers present on all new/modified source files (n/a) - [x] No secrets, credentials, or `.env` files included ### As Applicable - [x] New dependencies reviewed for license compatibility: `rand_pcg` is MIT/Apache-2.0, from the rust-random project like the existing `rand` - [ ] Others: n/a ## Testing ``` $ cargo audit → no vulnerabilities (490 crate dependencies), exit 0 (before: "error: 5 vulnerabilities found!" on main's lockfile) $ cargo check --locked --workspace --exclude echidna-rest --all-targets → ok $ cargo metadata --locked (full workspace, incl. echidna-rest) → ok ``` `echidna-rest` was excluded from the local `check` only because its build script downloads Swagger UI, which this sandbox blocks. CI builds it. ## Stack 1. **This PR**: lockfile bump 2. Hypatia baseline fix: delete the dead `ci-templates/mirror.yml`, baseline the echidnabot-path SD022 hits, `.hypatia-baseline.json` → JCS 3. ECH-05 follow-ups: regression fixture → JCS, stage 6 first target, issues row #431, norms in `.claude/CLAUDE.md` 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3 --- _Generated by [Claude Code](https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3)_ Co-authored-by: Claude <noreply@anthropic.com>
… filed as #431 - tests/fixtures/arbitration_regression.json is now JCS (RFC 8785) I-JSON plus a final LF, the estate format standard. Re-serialised, not regenerated: all 327 numbers and the whole document compare equal to the 29b18ea fixture (only spellings like 0.0 -> 0 change). The regenerator writes JCS, and fixture_is_jcs_canonical fails on a pretty-printed fixture (negative control run). - ROADMAP stage 6 and the gap-analysis pair table: HOL4 <-> HOL Light through OpenTheory is the first target (owner decision 2026-10-14); Lean 4 <-> Rocq through Dedukti is the next candidate. - issues/README.md: ECH-05 is #431, closed as completed by #430, the arbiter-typing slice of #429 (open). Its four labels now exist on the repo (created by filing) but not yet in the estate label source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3
…w, owner norms [stack 3/3] (#435) ## Summary Stack 3 of 3. #432 and #433 have merged, so this PR now targets `main`. It holds the ECH-05 follow-ups the owner decided after #430 merged, plus the owner's norms written down where agent sessions read them. **History rebuilt, 2026-10-14 (owner decision: force-with-lease).** The branch used to carry the pre-squash copies of #432 and #433. Rebase-merge replayed them onto `main`, which already had the squash commits, and conflicted on `.hypatia-baseline.json`. The branch is now this PR's own four commits on current `main` (5583c70), so it rebase-merges cleanly. Its tree is byte-identical to the old head (75288e7) merged with `main`. ## Changes - **`tests/fixtures/arbitration_regression.json` → JCS** (RFC 8785) I-JSON plus a final LF. - It is re-serialised, not regenerated. All 327 numbers, and the whole document, compare equal to the fixture recorded at `29b18ea`; only spellings change (`0.0` → `0`). This is the source of the large deletion count. - The regenerator now writes JCS. - A new test, `fixture_is_jcs_canonical`, keeps it canonical. A pretty-printed fixture fails it; I ran that negative control. - **ROADMAP stage 6 and the gap-analysis pair table:** HOL4 ↔ HOL Light through OpenTheory is the first target (owner decision, 2026-10-14). Lean 4 ↔ Rocq through Dedukti is the next candidate. - **`issues/README.md`:** ECH-05 is #431, closed as completed by #430, and is the arbiter-typing slice of #429, which stays open. - **`.claude/CLAUDE.md`, owner norms:** - decisions are asked with the selector tool; - work lands as stacked PRs; - findings are fixed at source. The exemption ratchet admits ledger growth only with a `Ratchet-exception:` line naming the ledger. - The format standards point at their normative source in standards: `YAML-POLICY.adoc` (KYAML, `.kyaml`; D280/D307/D293), the workflow gate in standards#1025, `JSON-POLICY.adoc` (I-JSON as JCS; D306) and ADR-008 (UUID v8; D305/D305b/D320). - The UUID rule is scoped until the `ids.rs` migration lands. `ids.rs` still mints v7 records and v8 content ids without a domain. This is the wording the owner accepted on proof-burrower#111. ## RSR Quality Checklist ### Required - [x] Tests pass (`cargo test --test arbitration_regression_test`: 2 passed, 1 ignored) - [x] Code is formatted (`cargo fmt --all -- --check`) - [x] Linter is clean - [x] No banned language patterns - [x] No `unsafe` blocks - [x] No banned functions - [x] SPDX license headers present on all new/modified source files - [x] No secrets, credentials, or `.env` files included ### As Applicable - [x] `docs/ROADMAP.adoc` updated (stage 6 first target) - [x] Documentation updated - [ ] Others: n/a ## Testing ``` $ cargo test --test arbitration_regression_test test numeric_fusion_unchanged_and_level_is_belief ... ok test fixture_is_jcs_canonical ... ok negative control: pretty-printed fixture → fixture_is_jcs_canonical FAILED ("fixture must be JCS (RFC 8785) canonical") jq: 327 numbers equal, documents equal (29b18ea fixture vs JCS fixture) ``` ## Stack 1. #432: `quinn-proto` lockfile bump (merged) 2. #433: Hypatia findings fixed at source, baseline → JCS (merged) 3. **This PR**: ECH-05 follow-ups and owner norms 4. #436: workflow checkers read KYAML (S4), stacked on this PR 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3 --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
Implements ECH-05 (drafted in
issues/echidna-05-fidelity-evidence.md; not yet filed). When backends agree, that doesn't show they proved the same statement. So the arbiter now takes per-attempt fidelity evidence and gives each fused verdict a level:belief<epi<sound. A synonym collision (statements aligned only by name) can no longer reachsound, however many backends agree. The numeric fusion is unchanged; a regression fixture taken before the change shows this.The ECH-05 plan asks for three stacked PRs. This session can push to one branch only, so the three parts are three separate commits here, and each can be reviewed on its own:
6b6f54aFidelityEvidenceonProverAttempt;level/retracted/warranted_termonArbitratedVerdict; the policy; regression fixture48e8034src/abi/EchidnaABI/Arbitration.idr, plus an accept/reject fixture falsifier wired intoidris2-abi-ci.yml33a3dc7tests/arbitration_fidelity_test.rs, ROADMAP stage 6 acceptance, backend-pair table,issues/README.mdrow and issue draftChanges
A: input and output types (
src/rust/verification/result_arbiter.rs,src/rust/exchange/mod.rs)FidelityEvidence=KernelTranslation { format, checked_by, term_hash }|DeclaredCorrespondence { consequence_tests, failures }|None. The default isNone, andProverAttempt::newkeeps its signature.EpistemicLevel { Belief, Epi, Sound }(ordered);fidelity_level()is the policy:beliefif the verdict needs review, rests on a retracted backend, fused nothing, or any attempt hasNoneevidence.soundonly if every fused attempt is aKernelTranslationto the same non-emptyterm_hash.epiif every fused attempt is a kernel translation or a correspondence with ≥ 1 consequence test and 0 failures, and the kernel hashes agree.beliefotherwise, e.g. two kernel translations to different terms.ResultArbiter::retract(prover)marks a backend unsound. Any verdict that fuses one of its attempts drops tobelief, andretractedlists the backend.exchange::ExchangeFormat(one variant per bridge) andexchange::term_hash: a BLAKE3 hash of the rendered term, separated by format, with no canonicalisation. The failure mode is a missedsound, never a false one.tests/fixtures/arbitration_regression.jsonwas generated at29b18eabefore the change (16 scenarios × 4 policies).tests/arbitration_regression_test.rsreplays it field by field (floats to 1e-12) and checks every verdict is atbelief.B: Idris2 ABI (
EchidnaABI.Arbitration)Level fusedis a closed sum indexed by the fused evidence.Sound hrequires anAll (KernelAt h) fusedproof, and eachKernelAtholds the hash-equality proof. So a collision, a correspondence or missing evidence infusedcannot be typedSound, whatever produced the value (collisionNotSound,correspondenceNotSound,noEvidenceNotSound).levelcomes withblockedIsBelief,noEvidenceIsBelief,failedCorrespondenceIsBelief,untestedCorrespondenceIsBelief,emptyFusedIsBelief,blockingNeverRaises, and evaluation controls (alignedPairIsSound,collisionPairIsBelief,mixedPairIsEpi). It is total and needs onlyDecEqon the hash type.6a68de3and residual-evidence-types97244f5are cited by pin in the module header, not imported. The cited lemma names were checked at those commits.tests/abi/accept/ArbitrationAligned.idrmust type-check, andtests/abi/reject/ArbitrationCollision.idr(identical apart from one hash) must fail withMismatch between.scripts/abi-fixtures.shjudges by output, becauseidris2 --checkexits 0 on a missing import.build/cache can silently skip the check (this bit me locally).idris2-abi-ci.yml, whose path filter now includestests/abi/and the script, and asjust abi-fixtures.C: acceptance tests and docs
ℕvs set.mmNN), under the portfolio, Bayesian and Dempster–Shafer policies. Four cases all stay atbeliefwhileverified = true/CrossChecked: lexical only; kernel translations to different terms; a correspondence with a failed consequence test; an untested correspondence.mathd_numbertheory_3positive control: the Lean and Isabelle statements were checked againstopenai/miniF2F@4e433ffand translate to one term, which reachessound. Negative control: the same pair with an off-by-one translation does not.sound, and the numbers don't change.issues/README.mdgains the ECH-05 row and lists its four labels missing on this repo.[Unreleased]entry.RSR Quality Checklist
Required
cargo test --lib(1208 passed, 3 ignored) plus both new integration tests; full--workspacerun is left to CI (see Testing)cargo fmt --all -- --check)cargo clippy --locked --workspace --exclude echidna-rest --all-targets -- -D warnings; see Testing for the exclusion)unsafeblockssrc/abiandtests/abiis empty).envfiles includedAs Applicable
(status)/(maturity)updated: not touched; nothing ships to dispatch yet (every dispatched verdict isbelief)(ecosystem)updated: n/a(meta)and/ordocs/decisions/updated: policy decisions are listed below for the ownerdocs/ROADMAP.adocupdated (stage 6 acceptance + §3 row)TOPOLOGY.mdupdated: n/aCHANGELOGupdatedblake3already a dependency)ffi/ziguntouchedTesting
Negative controls (applied, observed, then reverted):
unanimous_proven_three / bayesian(0.5): verdict.conflict.fidelity_levelfailssynonym_collision_cannot_reach_soundandminif2f_mistranslated_pair_does_not_reach_sound.Not run locally:
echidna-restbuildsutoipa-swagger-ui, whose build script downloads Swagger UI from GitHub, and the sandbox proxy blocks that. It is the only crate excluded from local clippy; CI builds the full workspace.cargo test --workspace --all-targetswas not run here; that is left to CI.Decisions for the owner
belief, notepi.needs_review(which covers inconsistent premises) isbelief.term_hashis not a certificate.area:arbitration,area:exchange,epistemic-types,residual-evidence-typesdon't exist on this repo yet. They need creating before ECH-05 is filed.🤖 Generated with Claude Code
https://claude.ai/code/session_019a95kk88TZ1iegsBK3kox3
Generated by Claude Code