diff --git a/.claude/README.adoc b/.claude/README.adoc new file mode 100644 index 0000000..21d0a46 --- /dev/null +++ b/.claude/README.adoc @@ -0,0 +1,53 @@ +== `+.claude/+` — Claude Code project configuration + +Checked-in, team-shared configuration for Claude Code sessions on +typed-wasm. + +=== Contents + +[width="100%",cols="40%,60%",options="header",] +|=== +|Path |Purpose +|`+CLAUDE.md+` |Project instructions (overview, architecture, +build/test, the 10 levels). + +|`+settings.json+` |Permissions allowlist + hooks (see below). + +|`+hooks/governance-precheck.sh+` |Local mirror of two CI governance +gates. +|=== + +=== `+settings.json+` + +==== Permissions (`+permissions.allow+`) + +A *read-only* allowlist that cuts permission prompts for the inspection +commands used routinely in this repo: +`+git status/log/diff/fetch/show/ls-files/ls-tree/branch/rev-parse/ merge-base/for-each-ref/check-attr+`, +`+git bundle verify+`/`+list-heads+`, `+diff -rq+`, and `+curl+` +*restricted to `+https://raw.githubusercontent.com/+`* (used to compare +sibling-estate repos without a full clone). No write, push, or +destructive commands are granted — those still prompt. + +==== Hooks (`+hooks.SessionStart+`) + +Runs `+hooks/governance-precheck.sh+` at session start. *Advisory only — +never blocks, always exits 0.* It surfaces, before you push, the two CI +gates most easily tripped by docs changes: + +[arabic] +. *Empty-linter* — invisible/zero-width Unicode (NBSP, ZWSP, BOM, bidi +marks, NUL) in source files, using the exact byte patterns from +`+.github/workflows/dogfood-gate.yml+`. +. *SPDX headers* — `+SPDX-License-Identifier+` presence on any `+.md+` / +`+.sh+` / `+.adoc+` *changed vs `+origin/main+`* (the push delta — not +the whole tree, to avoid the pre-existing unlicensed-doc backlog and +stay accurate to "`catch before push`"). + +Review or disable hooks anytime via the `+/hooks+` menu. + +____ +Note: the settings watcher only picks up `+.claude/settings.json+` if it +existed when the session started. On the session that first adds this +file, open `+/hooks+` once (or restart) to load the hook. +____ diff --git a/.claude/README.md b/.claude/README.md deleted file mode 100644 index dd09e8b..0000000 --- a/.claude/README.md +++ /dev/null @@ -1,42 +0,0 @@ - - - -# `.claude/` — Claude Code project configuration - -Checked-in, team-shared configuration for Claude Code sessions on typed-wasm. - -## Contents - -| Path | Purpose | -|------|---------| -| `CLAUDE.md` | Project instructions (overview, architecture, build/test, the 10 levels). | -| `settings.json` | Permissions allowlist + hooks (see below). | -| `hooks/governance-precheck.sh` | Local mirror of two CI governance gates. | - -## `settings.json` - -### Permissions (`permissions.allow`) - -A **read-only** allowlist that cuts permission prompts for the inspection commands used -routinely in this repo: `git status/log/diff/fetch/show/ls-files/ls-tree/branch/rev-parse/ -merge-base/for-each-ref/check-attr`, `git bundle verify`/`list-heads`, `diff -rq`, and -`curl` **restricted to `https://raw.githubusercontent.com/`** (used to compare sibling-estate -repos without a full clone). No write, push, or destructive commands are granted — those still -prompt. - -### Hooks (`hooks.SessionStart`) - -Runs `hooks/governance-precheck.sh` at session start. **Advisory only — never blocks, always -exits 0.** It surfaces, before you push, the two CI gates most easily tripped by docs changes: - -1. **Empty-linter** — invisible/zero-width Unicode (NBSP, ZWSP, BOM, bidi marks, NUL) in source - files, using the exact byte patterns from `.github/workflows/dogfood-gate.yml`. -2. **SPDX headers** — `SPDX-License-Identifier` presence on any `.md` / `.sh` / `.adoc` - **changed vs `origin/main`** (the push delta — not the whole tree, to avoid the pre-existing - unlicensed-doc backlog and stay accurate to "catch before push"). - -Review or disable hooks anytime via the `/hooks` menu. - -> Note: the settings watcher only picks up `.claude/settings.json` if it existed when the -> session started. On the session that first adds this file, open `/hooks` once (or restart) -> to load the hook. diff --git a/ARCHITECTURE.adoc b/ARCHITECTURE.adoc new file mode 100644 index 0000000..1c0a7a6 --- /dev/null +++ b/ARCHITECTURE.adoc @@ -0,0 +1,48 @@ +== Architecture + +=== Overview + +This repository follows a modular, maintainable architecture designed +for clarity, scalability, and long-term sustainability. + +=== Directory Structure + +.... +. +├── src/ # Source code +├── tests/ # Test suites +├── docs/ # Documentation +├── scripts/ # Utility scripts +├── config/ # Configuration files +├── LICENSE # License file +├── LICENSES/ # Full license texts +└── README.adoc # Project documentation +.... + +=== Design Principles + +* *Separation of Concerns*: Each module has a single responsibility +* *Testability*: Code is written to be easily testable +* *Documentation*: All public APIs are documented +* *Configuration*: Environment-specific settings are externalized + +=== Dependencies + +* External dependencies are minimized and clearly declared +* Version pinning is used for reproducibility + +=== Security Considerations + +* Sensitive data is never committed to the repository +* Secrets are managed through environment variables or secure vaults +* Regular dependency audits are performed + +=== Maintainability + +* Code follows consistent style guidelines +* Pull requests require review and CI checks +* Issues and discussions are tracked transparently + +''''' + +_Last updated: 2026-07-18_ diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index 607e3d8..0000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,47 +0,0 @@ -# Architecture - -## Overview - -This repository follows a modular, maintainable architecture designed for clarity, scalability, and long-term sustainability. - -## Directory Structure - -``` -. -├── src/ # Source code -├── tests/ # Test suites -├── docs/ # Documentation -├── scripts/ # Utility scripts -├── config/ # Configuration files -├── LICENSE # License file -├── LICENSES/ # Full license texts -└── README.adoc # Project documentation -``` - -## Design Principles - -- **Separation of Concerns**: Each module has a single responsibility -- **Testability**: Code is written to be easily testable -- **Documentation**: All public APIs are documented -- **Configuration**: Environment-specific settings are externalized - -## Dependencies - -- External dependencies are minimized and clearly declared -- Version pinning is used for reproducibility - -## Security Considerations - -- Sensitive data is never committed to the repository -- Secrets are managed through environment variables or secure vaults -- Regular dependency audits are performed - -## Maintainability - -- Code follows consistent style guidelines -- Pull requests require review and CI checks -- Issues and discussions are tracked transparently - ---- - -*Last updated: 2026-07-18* diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc new file mode 100644 index 0000000..8861320 --- /dev/null +++ b/CHANGELOG.adoc @@ -0,0 +1,456 @@ +== Changelog + +All notable changes to this project will be documented in this file. + +The format is based on https://keepachangelog.com/en/1.1.0/[Keep a +Changelog], and this project adheres to +https://semver.org/spec/v2.0.0.html[Semantic Versioning]. + +=== [Unreleased] + +==== Multi-producer carrier ABI: proposals 0001 + 0002 accepted, promoted to ADRs (2026-05-30) + +Closes typed-wasm#34 (proposal 0001), typed-wasm#78 (proposal 0002), +typed-wasm#106 (roadmap from `+[review]+` to `+[accepted]+`), +typed-wasm#94 (WBool wire width), typed-wasm#95 (proposal 0003 +tracking), typed-wasm#96 (proposal 0004 tracking), and typed-wasm#97 +(producer-readiness checklist + canonical emit ordering). + +*Acceptance arc (PRs #110–#116):* + +* *#110* — pre-acceptance gates: cross-reference between proposals. +* *#111* — proposal 0004 `+[draft]+` (`+typedwasm.capability-grants+` / +L15-C per-call-site enforcement, wire format defined). +* *#112* — proposal 0003 `+[draft]+` (`+typedwasm.region-imports+` / L13 +cross-module schema agreement, wire format defined). +* *#113* — pinned WBool wire width at 4 bytes in `+Region.idr+` +(`+sizeOf WBool = 4+`) matching both shipping producers; reserves +`+WBoolPacked+` as a separate `+WasmType+` for a future 1-byte variant. +* *#114* — added Appendix B "`Producer-readiness checklist`" to proposal +0001 + cross-reference subsection in proposal 0002 + canonical emit +ordering in proposal 0001 §"`Producer obligations`". +* *#115* — flipped proposals 0001 + 0002 from `+[review]+` to +`+[accepted]+` (owner decision 2026-05-30); rewrote `+LEVEL-STATUS.md+` +L2 / L3-L6 / L13 single-module / L15 rows from "`proposal-stage`" to +*YES (carrier-backed)* via the PR #107 / #109 verifier passes. +* *#116* — promoted proposals 0001 + 0002 to ADR-0002 / ADR-0003: +** `+docs/decisions/0002-multi-producer-carrier-sections.adoc+` +** `+docs/decisions/0003-access-site-carrier.adoc+` +** Proposal files retained as canonical wire-format references with +cross-links in both directions (`+Promoted to+` / `+Promoted from+`). + +*Status of carrier-format Cargo features:* + +* `+unstable-l2+` — codec + `+verify_regions_from_module+` + +`+verify_access_sites_from_module+` (post-acceptance; feature gate +retained while Phase 3 stabilisation is open). +* `+unstable-l15+` — codec + `+verify_capabilities_from_module+` +(post-acceptance; feature gate retained while Phase 3 stabilisation is +open). + +*Producer-side codegen remains gated downstream:* AffineScript +access-site emission at affinescript#462 (open); Ephapax counterpart at +ephapax#251 (filed 2026-05-30 with full scoping). Ephapax proposal-0001 +Appendix B dead-code item (`+Codegen.region_stack+` + +`+Codegen.bump_ptr+` + `+RegionInfo+`) closed via ephapax#250. + +*Handoff brief for new sessions* at +`+docs/developer/handoff-typed-access-sites-codegen.adoc+` — +self-contained brief covering both producers, the shared typecheck → +codegen threading blocker, three resolution options (IR annotation / +side-table / re-resolve at codegen), and the sequencing recommendation. +Cross-linked from affinescript#462 and ephapax#251. + +==== Proof-debt closure pass (2026-05-27) + +Post-Phase-0 sweep of the long-tail items the 2026-05-18 PROOF-NEEDS +reconciliation banner deferred. Closes the named obligations against +post-A10 audit items 7 + 8 (verifier ↔ spec, source ↔ verifier agreement +records) and the standards#130 "`LevelAttestation reindexed by witness`" +long-tail. All work additive (no existing definitions touched, no prior +proofs can regress) and all changes preserve `+%default total+` with +zero new `+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+` / +`+assert_smaller+`. + +*3 PRs landed/in flight, all auto-merge SQUASH armed*: + +* *#79* — `+TypedWasm.ABI.VerifierSpec+`: total bodies for +`+VerifierSpecAgreement+` and `+SourceVerifierAgreement+` (post-A10 +audit items 7 + 8). New module (~620 LOC) defining the shared +spec-of-record surface (`+ModuleSummary+` / `+FunctionSummary+` / +`+OwnershipIntent+`), structural acceptance predicates (`+TokenFresh+` / +`+IntentsLinearAcceptable+` / `+FunctionsAccepted+`), three acceptance +predicates (`+SpecAccepts+`, `+VerifierAccepts+`, `+SourceAccepts+`), +the two agreement records with totally-proven bodies, and concrete +inhabitants `+verifierSpecAgreement+` / `+sourceVerifierAgreement+` (the +first total no-`+believe_me+` agreement values in the codebase). Design +choice that unblocked the bodies: `+VADifferential+` / +`+SADifferential+` carry an inline `+TrustedFixture+` so the structural +witness travels with the fixture metadata — trust-injection moment moves +to `+MkTrustedFixture+` (single audit grep). End-to-end demo through +`+fixtureCleanLinearConsumerModule+` (cross_compat row 1). +Discrimination proofs across both ctors show L10 has teeth and the +differential escape hatch can’t smuggle a bad module past the verifier. +*+33 Layer 1 regression assertions.* Side-fix: latent +`+idris2 --check typed-wasm.ipkg+` bug in `+regression.mjs+` Layer 2 +corrected to `+--build+` (Idris2 0.8.0 `+--check+` rejects ipkg paths; +CI was unaffected because Layer 2 skips when idris2 not on PATH, but +local strict runs failed). +* *#74* — closed as superseded by #79 (competing `+Maybe+`-returning +bridge design; the witness-carrying ctor design in #79 closes the full +bodies that #74’s design explicitly framed as "`multi-week residual`"). +* *#80* — `+Proofs.idr+` `+LevelAttestationW+` + `+WitnessCertificate+`: +closes the standards#130 long-tail flagged in PROOF-NEEDS 2026-05-18 +reconciliation banner ("`Stronger '`attestation entails the level’s +semantic property`' (needs `+LevelAttestation+` reindexed by witness) +remains tracked future work under standards#130`"). Two stacked slices +(PR #83 instant-merged into #80’s branch because the stacked base wasn’t +protected; the squashed commit carries both): +** *`+LevelAttestationW : (n : Nat) -> Type+`* — witness-indexed +attestation GADT, one constructor per level (15 total). Each packages +the level-specific witness. 15 `+attestLNW_*+` smart ctors. 15 +`+attestLNW_Entails+` extractors (the +"`entails-semantic-property`" lemmas). `+toLegacy+` bridge. 15 +round-trip `+Refl+`s. Uniform `+attestLW_AchievedIn+` subsuming the A9 +`+attestLN_Sound+` family. +** *`+WitnessCertificate+`* — `+ProofCertificate+` lifted to +witness-carrying form via existential `+SomeAttestationW+`. Mirror +record. `+witnessToLegacy+` bridge. `+composeWitness+` mirror of +`+composeCertificates+`. `+composeWitnessLegacyAgree+` +composition-compat lemma. `+WitnessAchieved+` predicate lifted. Empty + +singleton smart ctors. *+49 Layer 1 regression assertions.* + +*Test surface after this pass*: 627+ assertions (up from 545+). +Per-surface delta: proof regression 25 → 107 (33 from #79 + 49 from #80, +plus the existing 25). + +*What this does NOT close*: + +* WasmCert-Isabelle tie-back (requires external Isabelle install) +* Emitted-wasm byte-equality, P3.1(a) (blocked on `+.twasm+`→`+.wasm+` +emitter) +* Parser round-trip in Idris2 (blocked on AffineScript parser port) +* Verifier L1–L6 + L13–L16 coverage (in progress on PRs #76 / #77 in a +parallel session — wire-format proposal + L2 codec pre-staging) + +==== 2026-05-27 — Phase 2 carrier-ABI design + C5.1 corpus + +Multi-PR session opening the L2–L6 / L15 enforcement path on emitted +wasm. The verifier today covers L7+L10 (PR #21) + L13 (PR #37); proposal +0001 below addresses why L2–L6 / L15 cannot follow without a +carrier-format ABI, and lands the codec pre-stage + the long-deferred +real-AffineScript fixture corpus. + +*3 PRs filed, auto-merge SQUASH armed:* + +* *#76* — `+docs/proposals/0001-multi-producer-carrier-section.adoc+`. +Proposes two new producer-neutral custom sections (`+typedwasm.regions+` +for L2–L6, `+typedwasm.capabilities+` for L15) alongside the existing +`+typedwasm.ownership+`. Versioned, lenient-readable, field-by-field +mapping to `+Region.idr+` / `+Pointer.idr+` / +`+ResourceCapabilities.idr+`. Status `+[draft]+` — blocked on cross-repo +review by affinescript and ephapax (both producers of +`+typedwasm.ownership+`). Includes an amendment commit (`+7520f00+`) +recording the resolved Open Question #6 (access-site carrier — option +A). +* *#77* — `+cargo feature = "unstable-l2"+` codec pre-stage: +`+typedwasm.regions+` parse + build (`+section.rs+`), 9 round-trip +tests, no `+verify_region_binding+` pass (deliberately omitted — see +issue #78). Default surface unchanged; opt-in build for the unstable +feature. +* *#81* — C5.1 real-AffineScript fixture corpus: 4 `+.affine+` sources + +paired `+.wasm+` bytes + `+tests/cross_compat_real.rs+` (5 verdict +tests) + `+.github/workflows/c5-regenerate.yml+` drift- detection +workflow pinning `+affinescript+` HEAD +`+21edc159caee06a930cb7339b3e729ed5627b823+`. Closes typed-wasm#35 part +2. + +*1 issue resolved on the spot:* + +* *#78* — access-site carrier gap (discovered while writing the L2 +codec; proposal 0001 names regions but does not say how the verifier +maps a wasm-level `+i32.load offset=N+` back to +`+(region_id, field_id)+`). Owner-resolved as option A (per-instruction +`+typedwasm.access-sites+` carrier). Size-measurement comment posted to +the issue: across the 6 spec examples, Encoding B (LEB128 per field) is +the v1 recommendation — ~5 B per access, ~1.1% module overhead. + +*2 cross-repo review issues filed* (gating proposal 0001 promotion to +`+[review]+`): + +* affinescript#402 — review request, AffineScript-specific producer +touchpoints called out (`+lib/tw_verify.ml+`, `+lib/tw_interface.ml+`, +codegen path). +* ephapax#165 — review request with the disambiguation note, +ephapax-wasm-specific touchpoints (`+src/ephapax-wasm/+`, +`+src/ephapax-cli/+`). + +*Test surface deltas:* + +* `+typed-wasm-verify+` Rust crate: 42 → 47 default tests (+5 C5.1 +real-fixture verdict tests). +* With `+--features unstable-l2+`: 47 → 52 (+5 with the regions codec +round-trip tests; 9 codec tests minus 4 overlap with the base set). + +==== Proof-debt pass A13 (2026-05-26, same-day continuation) + +Per coordinator pre-clearance for items 5 + 7 + 8, this round closes the +last of the post-A10 audit items at the *statement level* (same PR +https://github.com/hyperpolymath/typed-wasm/pull/72[#72]). No items +remain from that audit; items 7 + 8 are stated as typed obligations +(full proofs are multi-week and out of one-session scope). + +* *Item 5a closed* (L13 × L10 cross-level). `+ModuleIsolation.idr+` +imports `+Linear+` and gains +`+LinearAcrossBoundary from to regName bs token+` (an L13 +`+AccessWitness+` paired with an L10 `+LinHandle+`) plus three theorems: +`+linearTransferRequiresBoundary+` (no-bypass — any non-local handle +move requires a concrete boundary in `+bs+`), `+linearTransferLocal+` +(local-case constructor), and projections `+acrossWitness+` / +`+acrossHandle+`. +* *Item 5b closed* (L14 × L13 cross-level). `+SessionProtocol.idr+` +imports `+ModuleIsolation+` and gains `+SessionAcrossBoundary+` with +`+sessionAcrossPreservesState+` (the state index survives transfer), +`+sessionTransferRequiresBoundary+` (no-bypass), +`+sessionTransferLocal+` (local-case), and projections. Together they +prove a session handle cannot silently change state or escape its module +without an L13 witness. +* *A12 leave-behind closed.* `+Region.idr+` gains `+RegionsOverlap+` (an +address inside both region footprints) and `+disjointImpliesNoOverlap+`, +the L7/L10-flavour cross-level lemma that `+RegionDisjoint+` implies +byte-level non-overlap. Closes the link the A12 disjointness section +header explicitly deferred. +* *Items 7 + 8 stated as obligations.* New module +`+TypedWasm.ABI.VerifierSpec+` introduces three predicates — +`+SpecAccepts m+` (Idris2 L7+L10 structural acceptance on +`+ModuleSummary+`), `+VerifierAccepts m+` (opaque; witnessed only by the +Rust differential harness via `+differentialAccepted+`), and +`+SourceAccepts m+` (opaque; witnessed by the source-side harness) — +plus two agreement records: `+VerifierSpecAgreement+` (item 7, Rust +verifier ↔ Idris2 spec) and `+SourceVerifierAgreement+` (item 8, +source-checker ↔ verifier coverage). Each record bundles soundness + +completeness so partial proofs can land one face at a time. +`+sourceImpliesSpec+` / `+specImpliesSource+` are the composition lemmas +under both agreements. The opaque acceptance predicates make the trust +boundary inspectable: every `+VerifierAccepts+` / `+SourceAccepts+` use +traces back to a named fixture id. + +*15 new named items added* (`+LinearAcrossBoundary+`, +`+linearTransferRequiresBoundary+`, `+linearTransferLocal+`, +`+SessionAcrossBoundary+`, `+sessionAcrossPreservesState+`, +`+sessionTransferRequiresBoundary+`, `+sessionTransferLocal+`, +`+RegionsOverlap+`, `+disjointImpliesNoOverlap+`, `+regionsOverlapSym+`, +`+SpecAccepts+`, `+VerifierAccepts+`, `+SourceAccepts+`, +`+IntentsLinearAcceptable+`, `+VerifierSpecAgreement+` / +`+SourceVerifierAgreement+` / `+sourceImpliesSpec+` / +`+specImpliesSource+`). Regression: *68/68* under Idris2 0.8.0 (both +layers: source grep + `+idris2 --build+`). Package now 22 modules (was +21 — `+VerifierSpec+` is the only addition). + +*Closed after A13* (post-A10 audit complete): items 5a, 5b, 6 +leave-behind, 7-statement, 8-statement. Long-tail: full proofs of the +two agreement records; `+LevelAttestation+` reindexed-by-witness +redesign (standards#130 / epic standards#124); WasmCert-Isabelle +tie-back; emitted-wasm byte-equality. + +==== Proof-debt pass A12 (2026-05-26, same-day continuation) + +Per coordinator clearance, three more untracked items from the post-A10 +audit are closed in the same PR +(https://github.com/hyperpolymath/typed-wasm/pull/72[#72]): + +* *Item 4 closed IN FULL.* A11’s partial `+composeAssocLists+` +(list-side only) is superseded by `+composeAssoc+`, which proves +three-way associativity of `+composeCertificates+` across all three +fields. Enabled by switching `+composeCertificates+` from +`+Prelude.min+` to `+Data.Nat.minimum+` (structural Nat), making +`+minimumAssociative+` apply directly. `+composeHighProvenComm+` adds +Nat-side commutativity via `+minimumCommutative+`. The old +`+composeAssocLists+` kept as a back-compat corollary. +* *Item 6 closed.* `+Region.idr+` gains `+RegionDisjoint r1 r2+` (two +constructors for byte-footprint non-overlap, both orderings) plus +`+regionDisjointSym+` proving symmetry. Cross-level theorem linking +disjointness to L7 + L10 deferred to a future pass — the predicate +itself was the missing primitive. +* *Item 3 closed.* `+ResourceCapabilities.idr+` gains +`+containedConcat+` (proving `+ContainedIn+` distributes over `++++`) +plus `+jointBudgetCompose+`, the L8 ↔ L15 joint composition theorem. +Composing two functions with individual `+EffectSubsumes+` and +`+FunctionCaps+` witnesses yields a single function whose combined +effects subsume combined actuals (via L8 `+subsumeCompose+`) AND whose +combined required caps are contained in the owner module’s declared caps +(via the new `+containedConcat+` + the existing `+l15bSoundness+`). + +*6 new theorems added* (`+composeAssoc+`, `+composeHighProvenComm+`, +`+RegionDisjoint+`, `+regionDisjointSym+`, `+containedConcat+`, +`+jointBudgetCompose+`). Regression: *50/50* under Idris2 0.8.0 (both +layers: source grep + `+idris2 --build+`). + +Open after A12 (→ A13): post-A10 audit items 5 (L13×L10, L14×L13 +cross-level), 7 (Rust verifier ↔ Idris2 spec equivalence), 8 +(source-checker ↔ verifier coverage agreement). + +==== Proof-debt pass A10 + A11 (2026-05-26) + +Two same-day rounds attacking proof debt against `+PROOF-NEEDS.md+`. PR +https://github.com/hyperpolymath/typed-wasm/pull/72[#72]. + +*A10 (named, deferred)* — closes the last two items the 2026-05-18 +reconciliation banner still called "`deferred`": + +* *L12 freshness propagation under concurrent writes* (Epistemic.idr). 8 +new theorems headlined by +`+freshnessPropagatesUnderWrites : Fresh mod field v v -> LT v cur -> Sync mod field v cur -> Fresh mod field cur cur+`. +Supporting: `+concurrentWriteStales+`, `+resyncRecoversFresh+`, +`+freshNotStale+`, `+freshImpliesEqual+`, `+staleImpliesLT+`, +`+syncChainEndsFresh+`, and the +`+epistemicFreshness : (p : Level12Proof) -> Fresh …+` projector that +closes PROOF-NEEDS §P1.2 directly. +* *`+compatCommute+` mutual-subschema case* (MultiModule.idr). +`+compatCommute : ModuleCompat from to imp exp -> SchemaSub exp imp -> ModuleCompat to from exp imp+` ++ `+noSpoofingBidir+` corollary. Second worked example +(`+serviceA+`/`+serviceB+` with permuted schemas) exercises the theorem +on a non-trivial input. +* *`+tests/proof/regression.mjs+` Layer 2 fixed* from a silent no-op +(`+--check typed-wasm.ipkg+` tried to parse the ipkg as `+.idr+`) to an +actual `+idris2 --build+`. + +*A11 (untracked, audit-driven)* — closes 3 of 8 untracked gaps the A10 +post-mortem surfaced (full inventory: +`+project_typed_wasm_proof_debt_post_a10.md+`): + +* *Item 1* — `+Sync.WriteSync+` no longer admits fake writers. The +constructor now requires a `+FieldVersion+` witness with three +projection equalities (`+fv.field = field+`, +`+fv.version = newVersion+`, `+fv.lastWriter = mod+`). Adversarial +constructions like +`+WriteSync (MkFieldVersion otherField …) Refl Refl Refl+` are now +ill-typed unless the witness coincides with the indexed +field/version/writer. Corollary `+writeSyncIdentifiesWriter+` extracts +the witness. +* *Item 2* — `+Knowledge.Observed+` is grounded in a `+Sync+` event. +Constructor now takes `+(sync : Sync mod field oldVer ver)+`, so +`+Observed mod field ver+` cannot be inhabited without a causally-prior +write. Corollary `+observedHasProvenance+` reads the prior version + +Sync witness back out. +* *Item 4 (partial)* — first algebraic laws for `+composeCertificates+`. +`+achievedAppendSplit+` proves +`+LevelAchievedIn n (xs ++ ys) -> Either (LevelAchievedIn n xs) (LevelAchievedIn n ys)+`; +`+composeAssocLists+` proves list-level associativity of three-way +composition; `+composeAchievedSym+` is the symmetric counterpart of +`+composeAchievedL+`/`+R+`. The `+Nat+`-min commutativity on +`+highestProven+` is *deferred to A12*: +`+Prelude.min Nat = if x < y then x else y+` is non-structural and does +not reduce to `+Refl+` on symbolic inputs. + +*Test surface:* 13 named theorems added (8 in A10, 5 in A11), all +guarded by both `+tests/proof/regression.mjs+` layers (Layer 1 source +grep + Layer 2 `+idris2 --build+`). Total: *44/44 passing* under Idris2 +0.8.0. + +*Open after A11* (→ A12): post-A10-audit items 3 (L8↔L15 joint budget), +5 (L13×L10, L14×L13 cross-level), 6 (region disjointness in linear +memory), 7 (Rust verifier ↔ Idris2 spec equivalence), 8 (source-checker +↔ verifier coverage agreement), plus the Nat-min half of item 4. + +==== Phase 0 closure pass (2026-05-24 / 2026-05-25) + +Two sessions of focused engineering-surface stabilisation, closing the +foundation gates of `+docs/PRODUCTION-PATH.adoc+` §Phase 0. Gates 1 (CI +green-or-advisory) and 3 (ROADMAP truthful + drift-detected) met; gate 2 +(codegen v0 round-trips through verifier) remains as the terminal +Phase-1-handoff item. + +*11 PRs landed*: + +* *#46* — CI triage round 1 (3 of 6 reds fixed: cargo install, +structural E2E, hypatia exemption) +* *#47* — `+docs/PRODUCTION-PATH.adoc+` canonical 6-phase plan + ROADMAP +version↔phase mapping + README pointer +* *#55* — `+cargo audit+` workflow (RustSec advisories, weekly cron) +* *#57* — Track C complete: `+tests/property/property_test.mjs+` (29 +assertions), `+tests/aspect/security-envelope.mjs+` (10), +`+tests/proof/regression.mjs+` (25 + optional idris2 layer). Caught + +fixed 2 real bugs (`+.well-known/security.txt+` template residue, +missing SPDX on `+ffi/zig/src/main.zig+` and +`+.machine_readable/scripts/forge/git-cleanup.sh+`). +* *#58* — `+tools/tree-sitter-twasm/+` scaffold (Track A kickoff): +region-decls grammar v0 +* *#59* — A2ML / K9 / Build+E2E persistent-red jobs marked non-blocking +with documented removal preconditions +* *#60* — ROADMAP truthfulness audit (3 real path drifts fixed: +`+spec/10-levels-for-wasm.adoc+` rename → +`+type-safety-levels-for-wasm.adoc+` in 5 callers; EXPLAINME.adoc +pre-restructure file table; stray `+src/abi/Foreign.idr+` reference) + +`+claim-envelope.mjs+` §8 drift-detection aspect +* *#61* — Wiki source-of-truth at `+docs/wiki/+` (`+Home.md+`, +`+Production-Path.md+`, `+Phase-0-Status.md+`, `+Comparison.md+`, sync +workflow) + comprehensive `+.machine_readable/6a2/STATE.a2ml+` update +* *#62* — tree-sitter v1 grammar — parses +`+examples/01-single-module.twasm+` end-to-end with 0 ERROR nodes (~270 +lines covering memory decls, functions, parameters, statements, +expressions, nested field paths) +* *#63* — Repo tidy: RSR-template taxonomy alignment (added +`+AUDIT.adoc+`, `+docs/onboarding/+`, `+docs/status/+`, +`+docs/proposals/+`, `+docs/architecture/ABI-PIPELINE.adoc+`); deleted 8 +worthless files (3 template-residue QUICKSTARTs, 2 heuristic +`+.invariants.md+` artefacts, empty `+docs/wikis/+`, stray +`+generated/abi/README.adoc+`); README Quick Tour rebuilt; smoke job +made graceful for the in-flight parser migration; `+claim-envelope.mjs+` +§4 tolerates build outputs whose source exists; stale ReScript +references scrubbed from `+.hypatia-ignore+`, `+README.adoc+`, +`+AUDIT.adoc+` + +*Test surface after Phase 0 pass*: 545+ assertions across 11 surfaces +(88 parser + 53 verify + 56 per-level + 53+10 aspect + 29 property + 25 +proof + 40 smoke + 53 structural + 14 integration + 124 ECHIDNA). Up +from ~430 pre-session. + +*Out of scope for this pass* (multi-week / cross-repo): Track A’s full +`+spec/grammar.ebnf+` parity + Idris2 parser at 188-test parity + +codegen v0; Track B’s cross-repo AffineScript verifier migration +(requires separate session pointed at `+hyperpolymath/affinescript+`). + +*Tracking*: GitHub issue #48 carries the live ledger; phases 1–6 at +#49–#54. + +==== Added + +* *typed-wasm-verify* Rust crate (`+crates/typed-wasm-verify/+`) — +post-codegen verifier for L7 (aliasing) + L10 (linearity) on emitted +wasm modules. Rust port of +`+hyperpolymath/affinescript:lib/{tw_verify,tw_interface}.ml+`. 50/50 +tests pass (40 unit + 10 cross-compat integration). Replaces the +AffineScript verifier path which is on its way out. +** C1 (#19) — Scaffold: crate skeleton, public types (`+OwnershipKind+`, +`+OwnershipError+`, `+CrossError+`, `+FuncInterface+`, `+VerifyError+`), +`+OWNERSHIP_SECTION_NAME+` constant, stubbed entry points. +** C2 (#20) — `+affinescript.ownership+` custom-section codec (parse + +encode), 11 unit tests covering wire-format round-trip and OCaml-parity +leniency. +** C3 (#21) — Per-path `+(min, max)+` use-range analysis with a +control-flow frame stack over wasmparser’s operator stream. +`+verify_function+` + `+verify_from_module+` implement the intra-fn +L7+L10 rules. 9 algorithmic + 9 end-to-end tests. +** C4 (#22) — Cross-module boundary verifier (`+extract_exports+`, +`+verify_cross_module+`). 3 + 8 tests. Reuses C3’s frame stack via a +`+CallOf(import_idx)+` counter. +** C5 (#23) — Cross-compat integration suite +(`+tests/cross_compat.rs+`), 10 fixtures modelling realistic +affinescript-shaped modules. Each fixture documents the conceptual +AffineScript source and the expected OCaml verdict — divergence on +either side is a parity bug. +* ECHIDNA prover oracle JS harness (tests/echidna/echidna-harness.mjs) — +random .twasm generator, 4 property tests, optional ECHIDNA submission +* arXiv-ready LaTeX paper (docs/arxiv/typed-wasm.tex) — ACM sigplan +format, 851 lines +* BibTeX bibliography (docs/arxiv/typed-wasm.bib) — 15 references +* TypedQLiser plugin exists at typedqliser/src/plugins/wasm.rs (541 +lines, 9 tests) + +==== Changed + +* Repo is now polyglot Idris2 + Zig + Rust (added a Cargo workspace at +the root, `+crates/typed-wasm-verify/+` is its first member). +AffineScript files in `+src/parser/*.affine+` remain in tree as the v1.1 +surface parser, but the post-codegen verifier no longer depends on them. diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index efded5e..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,407 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - - - -## [Unreleased] - -### Multi-producer carrier ABI: proposals 0001 + 0002 accepted, promoted to ADRs (2026-05-30) - -Closes typed-wasm#34 (proposal 0001), typed-wasm#78 (proposal 0002), -typed-wasm#106 (roadmap from `[review]` to `[accepted]`), typed-wasm#94 -(WBool wire width), typed-wasm#95 (proposal 0003 tracking), typed-wasm#96 -(proposal 0004 tracking), and typed-wasm#97 (producer-readiness -checklist + canonical emit ordering). - -**Acceptance arc (PRs #110–#116):** - -- **#110** — pre-acceptance gates: cross-reference between proposals. -- **#111** — proposal 0004 `[draft]` (`typedwasm.capability-grants` / - L15-C per-call-site enforcement, wire format defined). -- **#112** — proposal 0003 `[draft]` (`typedwasm.region-imports` / - L13 cross-module schema agreement, wire format defined). -- **#113** — pinned WBool wire width at 4 bytes in `Region.idr` - (`sizeOf WBool = 4`) matching both shipping producers; reserves - `WBoolPacked` as a separate `WasmType` for a future 1-byte variant. -- **#114** — added Appendix B "Producer-readiness checklist" to - proposal 0001 + cross-reference subsection in proposal 0002 + - canonical emit ordering in proposal 0001 §"Producer obligations". -- **#115** — flipped proposals 0001 + 0002 from `[review]` to - `[accepted]` (owner decision 2026-05-30); rewrote `LEVEL-STATUS.md` - L2 / L3-L6 / L13 single-module / L15 rows from "proposal-stage" to - **YES (carrier-backed)** via the PR #107 / #109 verifier passes. -- **#116** — promoted proposals 0001 + 0002 to ADR-0002 / ADR-0003: - - `docs/decisions/0002-multi-producer-carrier-sections.adoc` - - `docs/decisions/0003-access-site-carrier.adoc` - - Proposal files retained as canonical wire-format references with - cross-links in both directions (`Promoted to` / `Promoted from`). - -**Status of carrier-format Cargo features:** - -- `unstable-l2` — codec + `verify_regions_from_module` + - `verify_access_sites_from_module` (post-acceptance; feature gate - retained while Phase 3 stabilisation is open). -- `unstable-l15` — codec + `verify_capabilities_from_module` - (post-acceptance; feature gate retained while Phase 3 stabilisation - is open). - -**Producer-side codegen remains gated downstream:** AffineScript -access-site emission at affinescript#462 (open); Ephapax counterpart -at ephapax#251 (filed 2026-05-30 with full scoping). Ephapax -proposal-0001 Appendix B dead-code item (`Codegen.region_stack` + -`Codegen.bump_ptr` + `RegionInfo`) closed via ephapax#250. - -**Handoff brief for new sessions** at -`docs/developer/handoff-typed-access-sites-codegen.adoc` — -self-contained brief covering both producers, the shared -typecheck → codegen threading blocker, three resolution options -(IR annotation / side-table / re-resolve at codegen), and the -sequencing recommendation. Cross-linked from affinescript#462 and -ephapax#251. - -### Proof-debt closure pass (2026-05-27) - -Post-Phase-0 sweep of the long-tail items the 2026-05-18 PROOF-NEEDS -reconciliation banner deferred. Closes the named obligations against -post-A10 audit items 7 + 8 (verifier ↔ spec, source ↔ verifier -agreement records) and the standards#130 "LevelAttestation reindexed -by witness" long-tail. All work additive (no existing definitions -touched, no prior proofs can regress) and all changes preserve -`%default total` with zero new `believe_me` / `assert_total` / -`postulate` / `sorry` / `assert_smaller`. - -**3 PRs landed/in flight, all auto-merge SQUASH armed**: - -- **#79** — `TypedWasm.ABI.VerifierSpec`: total bodies for - `VerifierSpecAgreement` and `SourceVerifierAgreement` (post-A10 - audit items 7 + 8). New module (~620 LOC) defining the shared - spec-of-record surface (`ModuleSummary` / `FunctionSummary` / - `OwnershipIntent`), structural acceptance predicates - (`TokenFresh` / `IntentsLinearAcceptable` / `FunctionsAccepted`), - three acceptance predicates (`SpecAccepts`, `VerifierAccepts`, - `SourceAccepts`), the two agreement records with totally-proven - bodies, and concrete inhabitants `verifierSpecAgreement` / - `sourceVerifierAgreement` (the first total no-`believe_me` - agreement values in the codebase). Design choice that unblocked - the bodies: `VADifferential` / `SADifferential` carry an inline - `TrustedFixture` so the structural witness travels with the - fixture metadata — trust-injection moment moves to - `MkTrustedFixture` (single audit grep). End-to-end demo through - `fixtureCleanLinearConsumerModule` (cross_compat row 1). - Discrimination proofs across both ctors show L10 has teeth and - the differential escape hatch can't smuggle a bad module past - the verifier. **+33 Layer 1 regression assertions.** - Side-fix: latent `idris2 --check typed-wasm.ipkg` bug in - `regression.mjs` Layer 2 corrected to `--build` (Idris2 0.8.0 - `--check` rejects ipkg paths; CI was unaffected because Layer 2 - skips when idris2 not on PATH, but local strict runs failed). -- **#74** — closed as superseded by #79 (competing `Maybe`-returning - bridge design; the witness-carrying ctor design in #79 closes the - full bodies that #74's design explicitly framed as "multi-week - residual"). -- **#80** — `Proofs.idr` `LevelAttestationW` + `WitnessCertificate`: - closes the standards#130 long-tail flagged in PROOF-NEEDS - 2026-05-18 reconciliation banner ("Stronger 'attestation entails - the level's semantic property' (needs `LevelAttestation` reindexed - by witness) remains tracked future work under standards#130"). - Two stacked slices (PR #83 instant-merged into #80's branch - because the stacked base wasn't protected; the squashed commit - carries both): - - **`LevelAttestationW : (n : Nat) -> Type`** — witness-indexed - attestation GADT, one constructor per level (15 total). Each - packages the level-specific witness. 15 `attestLNW_*` smart - ctors. 15 `attestLNW_Entails` extractors (the - "entails-semantic-property" lemmas). `toLegacy` bridge. 15 - round-trip `Refl`s. Uniform `attestLW_AchievedIn` subsuming - the A9 `attestLN_Sound` family. - - **`WitnessCertificate`** — `ProofCertificate` lifted to - witness-carrying form via existential `SomeAttestationW`. - Mirror record. `witnessToLegacy` bridge. `composeWitness` - mirror of `composeCertificates`. `composeWitnessLegacyAgree` - composition-compat lemma. `WitnessAchieved` predicate lifted. - Empty + singleton smart ctors. - **+49 Layer 1 regression assertions.** - -**Test surface after this pass**: 627+ assertions (up from 545+). -Per-surface delta: proof regression 25 → 107 (33 from #79 + 49 from -#80, plus the existing 25). - -**What this does NOT close**: - -- WasmCert-Isabelle tie-back (requires external Isabelle install) -- Emitted-wasm byte-equality, P3.1(a) (blocked on `.twasm`→`.wasm` - emitter) -- Parser round-trip in Idris2 (blocked on AffineScript parser port) -- Verifier L1–L6 + L13–L16 coverage (in progress on PRs #76 / #77 in - a parallel session — wire-format proposal + L2 codec pre-staging) - -### 2026-05-27 — Phase 2 carrier-ABI design + C5.1 corpus - -Multi-PR session opening the L2–L6 / L15 enforcement path on emitted -wasm. The verifier today covers L7+L10 (PR #21) + L13 (PR #37); -proposal 0001 below addresses why L2–L6 / L15 cannot follow without -a carrier-format ABI, and lands the codec pre-stage + the long-deferred -real-AffineScript fixture corpus. - -**3 PRs filed, auto-merge SQUASH armed:** - -- **#76** — `docs/proposals/0001-multi-producer-carrier-section.adoc`. - Proposes two new producer-neutral custom sections - (`typedwasm.regions` for L2–L6, `typedwasm.capabilities` for L15) - alongside the existing `typedwasm.ownership`. Versioned, - lenient-readable, field-by-field mapping to `Region.idr` / - `Pointer.idr` / `ResourceCapabilities.idr`. Status `[draft]` — - blocked on cross-repo review by affinescript and ephapax (both - producers of `typedwasm.ownership`). Includes an amendment commit - (`7520f00`) recording the resolved Open Question #6 (access-site - carrier — option A). -- **#77** — `cargo feature = "unstable-l2"` codec pre-stage: - `typedwasm.regions` parse + build (`section.rs`), 9 round-trip - tests, no `verify_region_binding` pass (deliberately omitted — - see issue #78). Default surface unchanged; opt-in build for the - unstable feature. -- **#81** — C5.1 real-AffineScript fixture corpus: 4 `.affine` - sources + paired `.wasm` bytes + `tests/cross_compat_real.rs` - (5 verdict tests) + `.github/workflows/c5-regenerate.yml` drift- - detection workflow pinning `affinescript` HEAD - `21edc159caee06a930cb7339b3e729ed5627b823`. Closes typed-wasm#35 - part 2. - -**1 issue resolved on the spot:** - -- **#78** — access-site carrier gap (discovered while writing the - L2 codec; proposal 0001 names regions but does not say how the - verifier maps a wasm-level `i32.load offset=N` back to - `(region_id, field_id)`). Owner-resolved as option A - (per-instruction `typedwasm.access-sites` carrier). - Size-measurement comment posted to the issue: across the 6 - spec examples, Encoding B (LEB128 per field) is the v1 - recommendation — ~5 B per access, ~1.1% module overhead. - -**2 cross-repo review issues filed** (gating proposal 0001 -promotion to `[review]`): - -- affinescript#402 — review request, AffineScript-specific - producer touchpoints called out (`lib/tw_verify.ml`, - `lib/tw_interface.ml`, codegen path). -- ephapax#165 — review request with the disambiguation note, - ephapax-wasm-specific touchpoints (`src/ephapax-wasm/`, - `src/ephapax-cli/`). - -**Test surface deltas:** - -- `typed-wasm-verify` Rust crate: 42 → 47 default tests - (+5 C5.1 real-fixture verdict tests). -- With `--features unstable-l2`: 47 → 52 (+5 with the regions - codec round-trip tests; 9 codec tests minus 4 overlap with the - base set). - -### Proof-debt pass A13 (2026-05-26, same-day continuation) - -Per coordinator pre-clearance for items 5 + 7 + 8, this round closes -the last of the post-A10 audit items at the **statement level** -(same PR [#72](https://github.com/hyperpolymath/typed-wasm/pull/72)). -No items remain from that audit; items 7 + 8 are stated as typed -obligations (full proofs are multi-week and out of one-session -scope). - -- **Item 5a closed** (L13 × L10 cross-level). - `ModuleIsolation.idr` imports `Linear` and gains - `LinearAcrossBoundary from to regName bs token` (an L13 - `AccessWitness` paired with an L10 `LinHandle`) plus three - theorems: `linearTransferRequiresBoundary` (no-bypass — any - non-local handle move requires a concrete boundary in `bs`), - `linearTransferLocal` (local-case constructor), and projections - `acrossWitness` / `acrossHandle`. -- **Item 5b closed** (L14 × L13 cross-level). - `SessionProtocol.idr` imports `ModuleIsolation` and gains - `SessionAcrossBoundary` with `sessionAcrossPreservesState` (the - state index survives transfer), `sessionTransferRequiresBoundary` - (no-bypass), `sessionTransferLocal` (local-case), and projections. - Together they prove a session handle cannot silently change state - or escape its module without an L13 witness. -- **A12 leave-behind closed.** `Region.idr` gains `RegionsOverlap` - (an address inside both region footprints) and - `disjointImpliesNoOverlap`, the L7/L10-flavour cross-level lemma - that `RegionDisjoint` implies byte-level non-overlap. Closes the - link the A12 disjointness section header explicitly deferred. -- **Items 7 + 8 stated as obligations.** New module - `TypedWasm.ABI.VerifierSpec` introduces three predicates — - `SpecAccepts m` (Idris2 L7+L10 structural acceptance on - `ModuleSummary`), `VerifierAccepts m` (opaque; witnessed only by - the Rust differential harness via `differentialAccepted`), and - `SourceAccepts m` (opaque; witnessed by the source-side harness) - — plus two agreement records: `VerifierSpecAgreement` (item 7, - Rust verifier ↔ Idris2 spec) and `SourceVerifierAgreement` (item - 8, source-checker ↔ verifier coverage). Each record bundles - soundness + completeness so partial proofs can land one face at - a time. `sourceImpliesSpec` / `specImpliesSource` are the - composition lemmas under both agreements. The opaque acceptance - predicates make the trust boundary inspectable: every - `VerifierAccepts` / `SourceAccepts` use traces back to a named - fixture id. - -**15 new named items added** (`LinearAcrossBoundary`, -`linearTransferRequiresBoundary`, `linearTransferLocal`, -`SessionAcrossBoundary`, `sessionAcrossPreservesState`, -`sessionTransferRequiresBoundary`, `sessionTransferLocal`, -`RegionsOverlap`, `disjointImpliesNoOverlap`, `regionsOverlapSym`, -`SpecAccepts`, `VerifierAccepts`, `SourceAccepts`, -`IntentsLinearAcceptable`, `VerifierSpecAgreement` / -`SourceVerifierAgreement` / `sourceImpliesSpec` / -`specImpliesSource`). Regression: **68/68** under Idris2 0.8.0 -(both layers: source grep + `idris2 --build`). Package now 22 -modules (was 21 — `VerifierSpec` is the only addition). - -**Closed after A13** (post-A10 audit complete): items 5a, 5b, 6 -leave-behind, 7-statement, 8-statement. Long-tail: full proofs of -the two agreement records; `LevelAttestation` reindexed-by-witness -redesign (standards#130 / epic standards#124); WasmCert-Isabelle -tie-back; emitted-wasm byte-equality. - -### Proof-debt pass A12 (2026-05-26, same-day continuation) - -Per coordinator clearance, three more untracked items from the post-A10 -audit are closed in the same PR ([#72](https://github.com/hyperpolymath/typed-wasm/pull/72)): - -- **Item 4 closed IN FULL.** A11's partial `composeAssocLists` - (list-side only) is superseded by `composeAssoc`, which proves - three-way associativity of `composeCertificates` across all three - fields. Enabled by switching `composeCertificates` from - `Prelude.min` to `Data.Nat.minimum` (structural Nat), making - `minimumAssociative` apply directly. `composeHighProvenComm` adds - Nat-side commutativity via `minimumCommutative`. The old - `composeAssocLists` kept as a back-compat corollary. -- **Item 6 closed.** `Region.idr` gains `RegionDisjoint r1 r2` (two - constructors for byte-footprint non-overlap, both orderings) plus - `regionDisjointSym` proving symmetry. Cross-level theorem linking - disjointness to L7 + L10 deferred to a future pass — the predicate - itself was the missing primitive. -- **Item 3 closed.** `ResourceCapabilities.idr` gains `containedConcat` - (proving `ContainedIn` distributes over `++`) plus - `jointBudgetCompose`, the L8 ↔ L15 joint composition theorem. - Composing two functions with individual `EffectSubsumes` and - `FunctionCaps` witnesses yields a single function whose combined - effects subsume combined actuals (via L8 `subsumeCompose`) AND - whose combined required caps are contained in the owner module's - declared caps (via the new `containedConcat` + the existing - `l15bSoundness`). - -**6 new theorems added** (`composeAssoc`, `composeHighProvenComm`, -`RegionDisjoint`, `regionDisjointSym`, `containedConcat`, -`jointBudgetCompose`). Regression: **50/50** under Idris2 0.8.0 -(both layers: source grep + `idris2 --build`). - -Open after A12 (→ A13): post-A10 audit items 5 (L13×L10, L14×L13 -cross-level), 7 (Rust verifier ↔ Idris2 spec equivalence), 8 -(source-checker ↔ verifier coverage agreement). - -### Proof-debt pass A10 + A11 (2026-05-26) - -Two same-day rounds attacking proof debt against `PROOF-NEEDS.md`. PR -[#72](https://github.com/hyperpolymath/typed-wasm/pull/72). - -**A10 (named, deferred)** — closes the last two items the 2026-05-18 -reconciliation banner still called "deferred": - -- **L12 freshness propagation under concurrent writes** (Epistemic.idr). - 8 new theorems headlined by `freshnessPropagatesUnderWrites : - Fresh mod field v v -> LT v cur -> Sync mod field v cur -> - Fresh mod field cur cur`. Supporting: `concurrentWriteStales`, - `resyncRecoversFresh`, `freshNotStale`, `freshImpliesEqual`, - `staleImpliesLT`, `syncChainEndsFresh`, and the - `epistemicFreshness : (p : Level12Proof) -> Fresh …` projector that - closes PROOF-NEEDS §P1.2 directly. -- **`compatCommute` mutual-subschema case** (MultiModule.idr). - `compatCommute : ModuleCompat from to imp exp -> SchemaSub exp imp -> - ModuleCompat to from exp imp` + `noSpoofingBidir` corollary. - Second worked example (`serviceA`/`serviceB` with permuted schemas) - exercises the theorem on a non-trivial input. -- **`tests/proof/regression.mjs` Layer 2 fixed** from a silent no-op - (`--check typed-wasm.ipkg` tried to parse the ipkg as `.idr`) to an - actual `idris2 --build`. - -**A11 (untracked, audit-driven)** — closes 3 of 8 untracked gaps the -A10 post-mortem surfaced (full inventory: -`project_typed_wasm_proof_debt_post_a10.md`): - -- **Item 1** — `Sync.WriteSync` no longer admits fake writers. The - constructor now requires a `FieldVersion` witness with three - projection equalities (`fv.field = field`, `fv.version = newVersion`, - `fv.lastWriter = mod`). Adversarial constructions like - `WriteSync (MkFieldVersion otherField …) Refl Refl Refl` are now - ill-typed unless the witness coincides with the indexed - field/version/writer. Corollary `writeSyncIdentifiesWriter` - extracts the witness. -- **Item 2** — `Knowledge.Observed` is grounded in a `Sync` event. - Constructor now takes `(sync : Sync mod field oldVer ver)`, so - `Observed mod field ver` cannot be inhabited without a - causally-prior write. Corollary `observedHasProvenance` reads the - prior version + Sync witness back out. -- **Item 4 (partial)** — first algebraic laws for - `composeCertificates`. `achievedAppendSplit` proves - `LevelAchievedIn n (xs ++ ys) -> Either (LevelAchievedIn n xs) - (LevelAchievedIn n ys)`; `composeAssocLists` proves list-level - associativity of three-way composition; `composeAchievedSym` is the - symmetric counterpart of `composeAchievedL`/`R`. The `Nat`-min - commutativity on `highestProven` is **deferred to A12**: - `Prelude.min Nat = if x < y then x else y` is non-structural and - does not reduce to `Refl` on symbolic inputs. - -**Test surface:** 13 named theorems added (8 in A10, 5 in A11), all -guarded by both `tests/proof/regression.mjs` layers (Layer 1 source -grep + Layer 2 `idris2 --build`). Total: **44/44 passing** under -Idris2 0.8.0. - -**Open after A11** (→ A12): post-A10-audit items 3 (L8↔L15 joint -budget), 5 (L13×L10, L14×L13 cross-level), 6 (region disjointness in -linear memory), 7 (Rust verifier ↔ Idris2 spec equivalence), 8 -(source-checker ↔ verifier coverage agreement), plus the Nat-min half -of item 4. - -### Phase 0 closure pass (2026-05-24 / 2026-05-25) - -Two sessions of focused engineering-surface stabilisation, closing the -foundation gates of `docs/PRODUCTION-PATH.adoc` §Phase 0. Gates 1 -(CI green-or-advisory) and 3 (ROADMAP truthful + drift-detected) met; -gate 2 (codegen v0 round-trips through verifier) remains as the -terminal Phase-1-handoff item. - -**11 PRs landed**: - -- **#46** — CI triage round 1 (3 of 6 reds fixed: cargo install, structural E2E, hypatia exemption) -- **#47** — `docs/PRODUCTION-PATH.adoc` canonical 6-phase plan + ROADMAP version↔phase mapping + README pointer -- **#55** — `cargo audit` workflow (RustSec advisories, weekly cron) -- **#57** — Track C complete: `tests/property/property_test.mjs` (29 assertions), `tests/aspect/security-envelope.mjs` (10), `tests/proof/regression.mjs` (25 + optional idris2 layer). Caught + fixed 2 real bugs (`.well-known/security.txt` template residue, missing SPDX on `ffi/zig/src/main.zig` and `.machine_readable/scripts/forge/git-cleanup.sh`). -- **#58** — `tools/tree-sitter-twasm/` scaffold (Track A kickoff): region-decls grammar v0 -- **#59** — A2ML / K9 / Build+E2E persistent-red jobs marked non-blocking with documented removal preconditions -- **#60** — ROADMAP truthfulness audit (3 real path drifts fixed: `spec/10-levels-for-wasm.adoc` rename → `type-safety-levels-for-wasm.adoc` in 5 callers; EXPLAINME.adoc pre-restructure file table; stray `src/abi/Foreign.idr` reference) + `claim-envelope.mjs` §8 drift-detection aspect -- **#61** — Wiki source-of-truth at `docs/wiki/` (`Home.md`, `Production-Path.md`, `Phase-0-Status.md`, `Comparison.md`, sync workflow) + comprehensive `.machine_readable/6a2/STATE.a2ml` update -- **#62** — tree-sitter v1 grammar — parses `examples/01-single-module.twasm` end-to-end with 0 ERROR nodes (~270 lines covering memory decls, functions, parameters, statements, expressions, nested field paths) -- **#63** — Repo tidy: RSR-template taxonomy alignment (added `AUDIT.adoc`, `docs/onboarding/`, `docs/status/`, `docs/proposals/`, `docs/architecture/ABI-PIPELINE.adoc`); deleted 8 worthless files (3 template-residue QUICKSTARTs, 2 heuristic `.invariants.md` artefacts, empty `docs/wikis/`, stray `generated/abi/README.adoc`); README Quick Tour rebuilt; smoke job made graceful for the in-flight parser migration; `claim-envelope.mjs` §4 tolerates build outputs whose source exists; stale ReScript references scrubbed from `.hypatia-ignore`, `README.adoc`, `AUDIT.adoc` - -**Test surface after Phase 0 pass**: 545+ assertions across 11 surfaces (88 parser + 53 verify + 56 per-level + 53+10 aspect + 29 property + 25 proof + 40 smoke + 53 structural + 14 integration + 124 ECHIDNA). Up from ~430 pre-session. - -**Out of scope for this pass** (multi-week / cross-repo): Track A's full `spec/grammar.ebnf` parity + Idris2 parser at 188-test parity + codegen v0; Track B's cross-repo AffineScript verifier migration (requires separate session pointed at `hyperpolymath/affinescript`). - -**Tracking**: GitHub issue #48 carries the live ledger; phases 1–6 at #49–#54. - -### Added -- **typed-wasm-verify** Rust crate (`crates/typed-wasm-verify/`) — post-codegen verifier for L7 (aliasing) + L10 (linearity) on emitted wasm modules. Rust port of `hyperpolymath/affinescript:lib/{tw_verify,tw_interface}.ml`. 50/50 tests pass (40 unit + 10 cross-compat integration). Replaces the AffineScript verifier path which is on its way out. - - C1 (#19) — Scaffold: crate skeleton, public types (`OwnershipKind`, `OwnershipError`, `CrossError`, `FuncInterface`, `VerifyError`), `OWNERSHIP_SECTION_NAME` constant, stubbed entry points. - - C2 (#20) — `affinescript.ownership` custom-section codec (parse + encode), 11 unit tests covering wire-format round-trip and OCaml-parity leniency. - - C3 (#21) — Per-path `(min, max)` use-range analysis with a control-flow frame stack over wasmparser's operator stream. `verify_function` + `verify_from_module` implement the intra-fn L7+L10 rules. 9 algorithmic + 9 end-to-end tests. - - C4 (#22) — Cross-module boundary verifier (`extract_exports`, `verify_cross_module`). 3 + 8 tests. Reuses C3's frame stack via a `CallOf(import_idx)` counter. - - C5 (#23) — Cross-compat integration suite (`tests/cross_compat.rs`), 10 fixtures modelling realistic affinescript-shaped modules. Each fixture documents the conceptual AffineScript source and the expected OCaml verdict — divergence on either side is a parity bug. -- ECHIDNA prover oracle JS harness (tests/echidna/echidna-harness.mjs) — random .twasm generator, 4 property tests, optional ECHIDNA submission -- arXiv-ready LaTeX paper (docs/arxiv/typed-wasm.tex) — ACM sigplan format, 851 lines -- BibTeX bibliography (docs/arxiv/typed-wasm.bib) — 15 references -- TypedQLiser plugin exists at typedqliser/src/plugins/wasm.rs (541 lines, 9 tests) - -### Changed -- Repo is now polyglot Idris2 + Zig + Rust (added a Cargo workspace at the root, `crates/typed-wasm-verify/` is its first member). AffineScript files in `src/parser/*.affine` remain in tree as the v1.1 surface parser, but the post-codegen verifier no longer depends on them. diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc new file mode 100644 index 0000000..bd2a83c --- /dev/null +++ b/CODE_OF_CONDUCT.adoc @@ -0,0 +1,24 @@ +== Contributor Covenant Code of Conduct + +=== Our Pledge + +We pledge to make participation a harassment-free experience for +everyone. + +=== Our Standards + +*Positive behavior:* * Using welcoming language * Being respectful of +differing viewpoints * Accepting constructive criticism * Focusing on +what is best for the community + +*Unacceptable behavior:* * Harassment, trolling, or personal attacks * +Publishing private information without permission + +=== Enforcement + +Report issues to the maintainers. All complaints will be reviewed. + +=== Attribution + +Adapted from https://www.contributor-covenant.org/[Contributor Covenant] +v2.1. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index caeda1c..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,27 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -We pledge to make participation a harassment-free experience for everyone. - -## Our Standards - -**Positive behavior:** -* Using welcoming language -* Being respectful of differing viewpoints -* Accepting constructive criticism -* Focusing on what is best for the community - -**Unacceptable behavior:** -* Harassment, trolling, or personal attacks -* Publishing private information without permission - -## Enforcement - -Report issues to the maintainers. All complaints will be reviewed. - -## Attribution - -Adapted from [Contributor Covenant](https://www.contributor-covenant.org/) v2.1. - diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc new file mode 100644 index 0000000..858f44f --- /dev/null +++ b/CONTRIBUTING.adoc @@ -0,0 +1,71 @@ +== Contributing + +Thank you for your interest in contributing! We follow a "`Dual-Track`" +architecture where human-readable documentation lives in the root and +machine-readable policies live in `+.machine_readable/+`. + +=== How to Contribute + +We welcome contributions in many forms: + +* *Code:* Improving the core stack or extensions +* *Documentation:* Enhancing docs or AI manifests +* *Testing:* Adding property-based tests or formal proofs +* *Bug reports:* Filing clear, reproducible issues + +=== Getting Started + +[arabic] +. *Read the AI Manifest:* Start with `+0-AI-MANIFEST.a2ml+` (if present) +to understand the repository structure. +. *Environment:* Use `+nix develop+` or `+direnv allow+` to set up your +tools. +. *Task Runner:* Use `+just+` to see available commands +(`+just --list+`). + +=== Development Workflow + +==== Branch Naming + +.... +docs/short-description # Documentation +test/what-added # Test additions +feat/short-description # New features +fix/issue-number-description # Bug fixes +refactor/what-changed # Code improvements +security/what-fixed # Security fixes +.... + +==== Commit Messages + +We follow https://www.conventionalcommits.org/[Conventional Commits]: + +.... +(): + +[optional body] + +[optional footer] +.... + +Types: `+feat+`, `+fix+`, `+docs+`, `+test+`, `+refactor+`, `+ci+`, +`+chore+`, `+security+` + +=== Reporting Bugs + +Before reporting: 1. Search existing issues 2. Check if it’s already +fixed in `+main+` + +When reporting, include: - Clear, descriptive title - Environment +details (OS, versions, toolchain) - Steps to reproduce - Expected vs +actual behaviour + +=== Code of Conduct + +All contributors are expected to adhere to our +link:CODE_OF_CONDUCT.md[Code of Conduct]. + +=== License + +By contributing, you agree that your contributions will be licensed +under the same license as the project (see LICENSE). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 80ecdac..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,66 +0,0 @@ - -# Contributing - -Thank you for your interest in contributing! We follow a "Dual-Track" architecture where human-readable documentation lives in the root and machine-readable policies live in `.machine_readable/`. - -## How to Contribute - -We welcome contributions in many forms: - -- **Code:** Improving the core stack or extensions -- **Documentation:** Enhancing docs or AI manifests -- **Testing:** Adding property-based tests or formal proofs -- **Bug reports:** Filing clear, reproducible issues - -## Getting Started - -1. **Read the AI Manifest:** Start with `0-AI-MANIFEST.a2ml` (if present) to understand the repository structure. -2. **Environment:** Use `nix develop` or `direnv allow` to set up your tools. -3. **Task Runner:** Use `just` to see available commands (`just --list`). - -## Development Workflow - -### Branch Naming - -``` -docs/short-description # Documentation -test/what-added # Test additions -feat/short-description # New features -fix/issue-number-description # Bug fixes -refactor/what-changed # Code improvements -security/what-fixed # Security fixes -``` - -### Commit Messages - -We follow [Conventional Commits](https://www.conventionalcommits.org/): - -``` -(): - -[optional body] - -[optional footer] -``` - -Types: `feat`, `fix`, `docs`, `test`, `refactor`, `ci`, `chore`, `security` - -## Reporting Bugs - -Before reporting: -1. Search existing issues -2. Check if it's already fixed in `main` - -When reporting, include: -- Clear, descriptive title -- Environment details (OS, versions, toolchain) -- Steps to reproduce -- Expected vs actual behaviour - -## Code of Conduct - -All contributors are expected to adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). - -## License - -By contributing, you agree that your contributions will be licensed under the same license as the project (see [LICENSE](LICENSE)). diff --git a/GOVERNANCE.adoc b/GOVERNANCE.adoc new file mode 100644 index 0000000..9b836fb --- /dev/null +++ b/GOVERNANCE.adoc @@ -0,0 +1,60 @@ +== Governance + +=== Overview + +This project is governed by the following principles and structures to +ensure transparent, inclusive, and effective decision-making. + +=== Roles and Responsibilities + +==== Maintainers + +Maintainers are responsible for: - Reviewing and merging pull requests - +Managing releases and versioning - Ensuring code quality and standards - +Triaging issues and bug reports - Community engagement and support + +==== Contributors + +Contributors are expected to: - Follow the code of conduct - Submit +well-documented pull requests - Write tests for new functionality - +Maintain existing tests - Update documentation as needed + +=== Decision Making + +==== Minor Changes + +* Can be made by any maintainer +* Include bug fixes, documentation updates, dependency updates + +==== Major Changes + +* Require discussion in issues or pull requests +* Include new features, architectural changes, API changes +* Need approval from at least 2 maintainers + +==== Breaking Changes + +* Require RFC (Request for Comments) process +* Need approval from majority of maintainers +* Must include migration guide + +=== Code of Conduct + +All participants are expected to follow our Code of Conduct. Violations +can be reported to the maintainers. + +=== Communication + +* *Issues*: For bug reports and feature requests +* *Discussions*: For questions and general discussion +* *Pull Requests*: For code contributions + +=== Licensing + +All contributions are made under the terms of the repository’s LICENSE +file. By submitting a pull request, you agree to license your +contributions accordingly. + +''''' + +_Last updated: 2026-07-18_ diff --git a/GOVERNANCE.md b/GOVERNANCE.md deleted file mode 100644 index e27364c..0000000 --- a/GOVERNANCE.md +++ /dev/null @@ -1,60 +0,0 @@ -# Governance - -## Overview - -This project is governed by the following principles and structures to ensure transparent, inclusive, and effective decision-making. - -## Roles and Responsibilities - -### Maintainers - -Maintainers are responsible for: -- Reviewing and merging pull requests -- Managing releases and versioning -- Ensuring code quality and standards -- Triaging issues and bug reports -- Community engagement and support - -### Contributors - -Contributors are expected to: -- Follow the code of conduct -- Submit well-documented pull requests -- Write tests for new functionality -- Maintain existing tests -- Update documentation as needed - -## Decision Making - -### Minor Changes -- Can be made by any maintainer -- Include bug fixes, documentation updates, dependency updates - -### Major Changes -- Require discussion in issues or pull requests -- Include new features, architectural changes, API changes -- Need approval from at least 2 maintainers - -### Breaking Changes -- Require RFC (Request for Comments) process -- Need approval from majority of maintainers -- Must include migration guide - -## Code of Conduct - -All participants are expected to follow our Code of Conduct. Violations can be reported to the maintainers. - -## Communication - -- **Issues**: For bug reports and feature requests -- **Discussions**: For questions and general discussion -- **Pull Requests**: For code contributions - -## Licensing - -All contributions are made under the terms of the repository's LICENSE file. -By submitting a pull request, you agree to license your contributions accordingly. - ---- - -*Last updated: 2026-07-18* diff --git a/LEVEL-STATUS.adoc b/LEVEL-STATUS.adoc new file mode 100644 index 0000000..c57cc7d --- /dev/null +++ b/LEVEL-STATUS.adoc @@ -0,0 +1,563 @@ +== SPDX-License-Identifier: CC-BY-SA-4.0 + +== typed-wasm Level Achievement Status + +=== Versioning Scheme (revised 2026-04-13 — typed-wasm-first rollout) + +typed-wasm versions track BOTH the highest fully-achieved level tier and +the surface-syntax sugar additions. The rollout now interleaves level +work with consumer-language enablement — see +`+spec/L13-L16-reserved-syntax.adoc+` for the full trajectory and +keyword reservations. + +[width="99%",cols="28%,22%,25%,25%",options="header",] +|=== +|Version |Levels |Surface |Meaning +|v0.1 |L1-10 |v0.1 grammar |Checked proof core (proofs + runtime L1-6, +compile-time L7-10) + +|v1.0 |L1-10 |v0.1 grammar |Audited release of the checked core + +|v1.1 |L1-10 |v0.2 sugar |`+const+`, `+match+` on unions, block-expr +`+if+`, split effects `+{memory:, caps:}+`, `+striated+` regions. +L11-L12 remain draft. + +|v1.2 |L1-10, L13 |v0.3 sugar |+L13 Module isolation: +`+module Name isolated { ... }+`, `+private_memory+`, `+boundary+`. +Idris2 proof: ModuleIsolation.idr. Surface enforcement: +Checker.checkIsolatedModule. + +|v1.3 |L1-10, L13, L14 |v0.4 sugar |+L14 Session protocols: +`+session Name { state ...; transition consume X -> yield Y; dual : ...; }+`. +Idris2 proof: SessionProtocol.idr (SessionHandle parameterised by state +index, step soundness, DualPair symmetry). Surface enforcement: +Checker.checkSession. 63/63 parser tests. + +|*v1.4* |*L1-10, L13, L14, L15* |*v0.5 sugar* |*+L15 Resource +capabilities: `+capability NAME;+` top-level and isolated-module-body +declarations; v1.1 `+caps: { ... }+` sub-clause becomes load-bearing. +Idris2 proof: ResourceCapabilities.idr (DistinctCaps L15-A, ContainedIn ++ containedTrans L15-B, CallCompatible + callCompose L15-C, +FullEffectBudget orthogonality with L8). Surface enforcement: +Checker.checkCapabilities + scope-threaded checkDeclaration. L15-A +(distinct) + L15-B (well-scoped) live at v1.4; L15-C (call-graph +monotone) deferred to v1.4.x (proof already carries the theorem). 76/76 +parser tests pass.* + +|*v1.5* |*L1-10, L13, L14, L15, L16* |*v0.6 sugar* |*+L16 Agent +choreography: +`+choreography { agent_role ...; message ...; composes: L13 + L14 + L15; }+`. +Idris2 proof: Choreography.idr (composition-only theorem citing lower +levels). Surface enforcement: Checker.checkChoreography (L16-A..L16-D). +88/88 parser tests pass.* + +|L17 (reserved) |L1-L16, *L17* |future |"`Layout-proof striation`" with +`+strided_ptr+` — removes the projection-only restriction on striated +regions +|=== + +*L11 (Tropical)* and *L12 (Epistemic)* remain draft-only at v1.1. They +are orthogonal to the L13-L16 rollout and can promote to +checked-in-package at any intermediate version without blocking the main +trajectory. L11 is the natural home for "`striation is cheaper`" proofs +once it lands. + +=== v1.1 surface sugar — status + +[width="100%",cols="21%,16%,9%,12%,14%,16%,12%",options="header",] +|=== +|Feature |Grammar |AST |Lexer |Parser |Checker |Tests +|`+const+` top-level |spec/grammar.ebnf |Ast.ConstDecl |Const |*DONE* +parseConstDecl (Parser.affine:2088) |Checker.constValueIsLiteral |*DONE* + +|`+match+` on union |spec/grammar.ebnf |Ast.MatchStmt |Match |*DONE* +(Parser.affine:1191) |Checker.matchIsExhaustive |*DONE* + +|Block-expr `+if+` |spec/grammar.ebnf |Ast.BlockIfExpr |Yield |*DONE* +(Parser.affine:529) |Checker.blockIfBranchesAgree |*DONE* + +|Split `+effects+` |spec/grammar.ebnf |functionDecl.caps |(contextual) +|*DONE* parseEffectsClause (Parser.affine:1554) |(opaque until L15) +|*DONE* + +|`+striated+` regions |spec/grammar.ebnf |regionDecl.layout |Striated +|*DONE* |Checker.striatedLayoutIsWellFormed |*DONE* + +|Reserved keywords (L13-L16) |spec/L13-L16-reserved-syntax.adoc |— +|contextual (per-block) |*DONE* (Parser.affine:2685-2718) |— |*DONE* +(v1.4/v1.5 rejection tests) +|=== + +*v1.1 surface sugar fully landed: parser, checker, tests all live. 88/88 +parser tests pass (verified 2026-04-18). LEVEL-STATUS table was stale +between 2026-04-13 (AST landed) and 2026-04-18 (verification).* + +=== Current: checked core = L1-10 + L13-L16, L11-L12 = draft + +[width="100%",cols="14%,12%,26%,18%,14%,16%",options="header",] +|=== +|Level |Name |Idris2 Proof |Zig FFI |Tests |Status +|1 |Instruction validity |Region.idr |Parser |ECHIDNA 10^5 |*E2E +complete* + +|2 |Region-binding |Region.idr + TypedAccess.idr |Schema lookup |ECHIDNA +10^5 |*E2E complete* + +|3 |Type-compatible access |TypedAccess.idr |Typed load/store |ECHIDNA +10^5 |*E2E complete* + +|4 |Null safety |Pointer.idr |Pointer kinds |ECHIDNA 10^5 |*E2E +complete* + +|5 |Bounds-proof |TypedAccess.idr + Levels.idr |Bounds check |ECHIDNA +10^5 |*E2E complete* + +|6 |Result-type |TypedAccess.idr |Type flow |ECHIDNA 10^5 |*E2E +complete* + +|7 |Aliasing safety |Pointer.idr (Unique) |Erased (QTT) |ECHIDNA 10^4 +|*Proven [sfap], erased* + +|8 |Effect-tracking |Effects.idr |Erased (QTT) |ECHIDNA 10^4 |*Proven +[sfap], erased. Preorder + composition theorems added A5 (2026-04-18): +`+subsumeRefl+` (alias of `+effectSubsumesRefl+`), `+hasEffectTrans+`, +`+subsumeTrans+`, `+hasEffectCombineL+`/`+CombineR+`, +`+subsumePrepend+`/`+Append+`, and the flagship `+subsumeCompose+` +giving +`+EffectSubsumes d1 a1 -> EffectSubsumes d2 a2 -> EffectSubsumes (d1++d2) (a1++a2)+` +so L8 attestations compose.* + +|9 |Lifetime safety |Lifetime.idr |Erased (QTT) |ECHIDNA 10^4 |*Proven +[sfap], erased. Preorder + load-safety theorems added A4 (2026-04-18): +`+outlivesRefl+`, `+outlivesTrans+` (alias of pre-existing +`+outlivesTransitive+` with 7-constructor case analysis), `+loadSafe+` +proof-term, behavioural lemmas `+loadSafeOffset+` and +`+loadSafeIrrelevant+` (proof irrelevance at the value level).* + +|10 |Linearity |Linear.idr (QTT q=1) |Erased (QTT) |ECHIDNA 10^4 +|*Proven [sfap], erased. Propositional state-machine theorems added A3 +(2026-04-18): distinctUsage, consumePreservesData, noReuse, noReuseEcho +— usage-indexed handle `+LinHandleU Fresh/Consumed tok+` with +`+consume+` state transition, alongside the QTT structural layer.* + +|11 |Tropical cost-tracking |Tropical.idr |Not yet |None |*In package +(A1, 2026-04-18). Commutative-semiring closure PROVEN (A2, 2026-04-18): +all 12 axioms. Uses structural `+tropMin+` (007-lang template). Zero +dangerous patterns. A16 (2026-06-16) estate accommodation: added the +canonical dioid ORDER layer (`+tropLe+` refl/trans + add/mul +monotonicity, mirrors `+tropical-resource-typing+` +`+Resource.Algebra.Ordered+`), the MinMax BOTTLENECK layer (`+tropMax+` ++ `+hubCeiling+`, mirrors `+Resource.Instances.MinMax+` + +`+Bridge.hub_ceiling_le+`), `+ResidueMeasure+` (E→R, mirrors +`+Resource.EchoBridge+`), and `+Level11BottleneckProof+` + +`+bottleneckCeilsEdges+` wired into +`+Proofs.attestL11_Bottleneck+`/`+_Sound+`.* + +|12 |Epistemic safety |Epistemic.idr |Not yet |None |*In package (A1, +2026-04-18); A10 (2026-05-26) closes the "`freshness propagation under +concurrent writes`" gap with `+freshnessPropagatesUnderWrites+` + +supporting theorems (11 total; closes PROOF-NEEDS §P1.2). A15 +(2026-06-16) estate accommodation: ADDITIVE `+syncGrade+` layer reusing +sibling `+Tropical.TropCost+` (∞ = never-synced) + +`+neverSyncedInfeasible+`/`+observedFeasible+`/`+observedNotInfeasible+` +— extant Nat-indexed proofs untouched. Header IS-NOT note: this +read-consistency model is a DIFFERENT problem from canonical +`+epistemic-types+`’ standpoint-indexed modality.* + +|13 |Module isolation |ModuleIsolation.idr |(per-module handles, future) +|12 parser/Checker tests |*v1.2 — Idris2 proof + surface checker live; +007 lowering DONE (task #5)* + +|14 |Session protocols |SessionProtocol.idr |(typed-state handles, +future) |13 parser/Checker tests |*v1.3 — Idris2 proof + surface checker +live; 007 send/receive lowering DONE (task #7)* + +|15 |Resource capabilities |ResourceCapabilities.idr |(future) |13 +parser/Checker tests |*v1.4 — Idris2 proof + surface checker (L15-A + +L15-B) live; L15-C call-graph check deferred to v1.4.x; 007 lowering +DONE (task #9)* + +|16 |Agent choreography |Choreography.idr |(future) |12 parser/Checker +tests |*v1.5 — composition proof over L13+L14+L15 live; surface checker +enforces L16-A (role targets exist), L16-B (message endpoints declared), +L16-C (payload primitive/declared region ref), L16-D (exact +`+L13 + L14 + L15+` composition spec).* +|=== + +*[sfap]* = "`so far as possible`" — proofs are machine-checked in Idris2 +with zero dangerous patterns. They are as complete as the Idris2 type +checker can verify. Full mechanical verification against a formal Wasm +operational semantics (e.g. WasmCert-Isabelle) remains future work. + +=== What "`proven, erased`" means + +Levels 7-10 are verified by the Idris2 type checker at compile time, +then erased before code generation via QTT (Quantitative Type Theory). +The emitted Wasm is identical to hand-written code — zero runtime +overhead. This is by design, not a gap. The proofs exist to catch bugs +at compile time; they are not needed at runtime. + +=== What "`draft`" means + +Levels 11-12 are draft for surface semantics, not for ipkg membership. +As of 2026-04-18 (commit A1) both `+Tropical.idr+` and `+Epistemic.idr+` +are in `+typed-wasm.ipkg+` and build clean under Idris2 0.8.0 — see the +2026-05-18 reconciliation in `+PROOF-NEEDS.md+`. The "`draft`" label +applies to the level semantics themselves (Tropical cost-tracking and +Epistemic freshness propagation under concurrent writes remain +research-grade): theorems live, but the surface language and Zig FFI do +not yet expose them. Wiring these levels through the rest of the +toolchain remains future work. + +=== Proof inventory + +[width="100%",cols="13%,18%,18%,24%,27%",options="header",] +|=== +|File |believe_me |postulate |assert_total |Checked status +|Region.idr |0 |0 |0 |In package. Structural injectivity added A8 +(2026-04-18): `+fieldNameInj+` / `+fieldTypeInj+` / `+fieldInj+` +(MkField constructor injectivity), `+schemaEqSym+` / `+schemaEqTrans+` +(making SchemaEq a full equivalence relation with the pre-existing +`+schemaEqRefl+`), `+lookupFieldName+` (L2 soundness — +`+FieldIn name schema+` implies `+fieldName (lookupField prf) = name+`). +A12 (2026-05-26): byte-disjointness layer added — +`+RegionDisjoint r1 r2+` (two constructors covering both orderings of +footprint endpoints) plus `+regionDisjointSym+` proving symmetry. Closes +post-A10 audit item 6. A13 (2026-05-26): byte-separation cross-level +layer added — `+RegionsOverlap r1 r2+` (an address inside both region +footprints), `+disjointImpliesNoOverlap+` proving +`+RegionDisjoint r1 r2 -> Not (RegionsOverlap r1 r2)+`, plus +`+regionsOverlapSym+`. Closes the L7/L10 cross-level link explicitly +deferred at A12. + +|TypedAccess.idr |0 |0 |0 |In package + +|Levels.idr |0 |0 |0 |In package + +|Pointer.idr |0 |0 |0 |In package + +|Effects.idr |0 |0 |0 |In package + +|Lifetime.idr |0 |0 |0 |In package + +|Linear.idr |0 |0 |0 |In package + +|MultiModule.idr |0 |0 |0 |In package. Flagship no-spoofing theorem +proven A6 (2026-04-18): `+FieldMatches+`, `+SchemaSub+` preorder +(`+schemaSubRefl+`, `+schemaSubTrans+`), `+ModuleCompat+` indexed on +modules + schemas (`+compatRefl+`, `+compatTrans+`), and the flagship +`+noSpoofing : ModuleCompat from to imp exp -> FieldMatches f imp -> FieldMatches f exp+`. +Worked Rust-exports / AffineScript-imports example (4-field export, +2-field import subset) constructs a live certificate and applies the +theorem. A10 (2026-05-26) closes the deferred `+compatCommute+` item: +mutual-subschema commutativity +`+compatCommute : ModuleCompat from to imp exp -> SchemaSub exp imp -> ModuleCompat to from exp imp+`, +plus the `+noSpoofingBidir+` corollary returning a pair of +field-transport functions. Second worked example +(`+serviceA+`/`+serviceB+` with permuted schemas) demonstrates +`+compatCommute+` on a case where both `+SchemaSub+` directions hold. + +|ModuleIsolation.idr |0 |0 |0 |In package (v1.2 / L13). A13 +(2026-05-26): L13×L10 cross-level layer added — imports `+Linear+`, +exposes `+LinearAcrossBoundary from to regName bs token+` (an L13 +`+AccessWitness+` paired with an L10 `+LinHandle+`) plus accessors +`+acrossWitness+` / `+acrossHandle+`, the no-bypass theorem +`+linearTransferRequiresBoundary+` (any non-local linear-handle transfer +requires a concrete boundary in `+bs+`, proved by reusing +`+crossAccessImpliesBoundary+`), and `+linearTransferLocal+` (local-case +constructor). Closes post-A10 audit item 5a. + +|SessionProtocol.idr |0 |0 |0 |In package (v1.3 / L14). A13 +(2026-05-26): L14×L13 cross-level layer added — imports +`+ModuleIsolation+`, exposes +`+SessionAcrossBoundary from to proto state regName bs+` plus accessors, +`+sessionAcrossPreservesState+` (the state index survives the transfer), +`+sessionTransferRequiresBoundary+` (no-bypass, same shape as the L10 +version one level up), and `+sessionTransferLocal+`. Closes post-A10 +audit item 5b. + +|ResourceCapabilities.idr |0 |0 |0 |In package (v1.4 / L15). A12 +(2026-05-26): `+containedConcat+` proves `+ContainedIn+` distributes +over `++++`; `+jointBudgetCompose+` proves the L8 ↔ L15 *joint* budget +composition theorem — given individual `+EffectSubsumes+` witnesses and +individual `+FunctionCaps+` witnesses for two functions sharing an owner +module, the compound function still satisfies both the combined L8 +envelope (via `+subsumeCompose+`) AND the combined L15 module envelope +(via `+containedConcat+` + `+l15bSoundness+`). Closes post-A10 audit +item 3. + +|Choreography.idr |0 |0 |0 |In package (v1.5 / L16) + +|Proofs.idr |0 |0 |0 |In package. Attestation API hardened A7 +(2026-04-18): every L1-L10 attestation now requires a witness from its +level module (Schema / FieldIn / WasmTypeCompat / Ptr-NonNull / InBounds +/ AccessResult / ExclusiveWitness / EffectSubsumes / Lifetime.Outlives / +CompletedProtocol). `+simpleReadCert+` / `+fullCert12+` / `+fullCert15+` +thread witnesses per level; the certificate cannot be constructed +without real proof artefacts. Level-achievement layer added A8 +(2026-04-18): `+LevelAchievedIn+` predicate, `+achievedAppendL+` / +`+achievedAppendR+` list-append preservation, `+LevelAchieved n cert+` +lifted to certificates, `+composeAchievedL+` / `+composeAchievedR+` +proving any level achieved in either component of +`+composeCertificates+` is still achieved in the composition. +Attestation soundness A9 (2026-05-18): per-level `+attestLN_Sound+` +family proving `+LevelAchievedIn N [attestLN_X w]+` — the weak +"`certificate claims level N`" face. A11 (2026-05-26): partial laws for +`+composeCertificates+` — `+achievedAppendSplit+`, +`+composeAssocLists+`, `+composeAchievedSym+`. A12 (2026-05-26): +switched `+composeCertificates+` from Ord-derived `+Prelude.min+` to +structural `+Data.Nat.minimum+`; *full* `+composeAssoc+`; +`+composeHighProvenComm+`. Closes post-A10 audit item 4 in full. +*Witness-indexed redesign 2026-05-27 (PR #80, closes standards#130 +long-tail)*: `+LevelAttestationW : (n : Nat) -> Type+` GADT with one +ctor per level packaging the actual witness; 15 `+attestLNW_*+` smart +ctors; 15 `+attestLNW_Entails+` extractors (a consumer holding +`+LevelAttestationW 7+` can now discharge L7 alias-freeness via +`+ExclusiveWitness s+`, not just the weak claim-predicate); `+toLegacy+` +bridge; 15 round-trip `+Refl+`s; uniform `+attestLW_AchievedIn+` +subsuming the A9 family. *`+WitnessCertificate+` lift 2026-05-27 (PR +#80, folded from #83)*: existential `+SomeAttestationW+` wrapper, +`+record WitnessCertificate+` mirror of `+ProofCertificate+` with +witness-carrying levels, `+witnessToLegacy+` bridge, `+composeWitness+` +mirror, `+composeWitnessLegacyAgree+` compat lemma, `+WitnessAchieved+` +predicate. + +|Tropical.idr |0 |0 |0 |In package (A1, 2026-04-18) + +|Epistemic.idr |0 |0 |0 |In package (A1, 2026-04-18). A10 (2026-05-26): +propagation theorems added — `+freshImpliesEqual+`, `+staleImpliesLT+`, +`+freshNotStale+` (mutual exclusion via local `+ltIrreflexive+`), +`+concurrentWriteStales+`, `+resyncRecoversFresh+`, the flagship +`+freshnessPropagatesUnderWrites+`, `+syncChainEndsFresh+`, and the +`+epistemicFreshness+` projector on `+Level12Proof+` (closes PROOF-NEEDS +§P1.2). A11 (2026-05-26): constructor-tightening pass — `+WriteSync+` +now demands a `+FieldVersion+` witness with three equality components +(`+field+`/`+version+`/`+lastWriter+`), and `+Knowledge.Observed+` is +grounded in a `+Sync+` event (no more unfounded versions). Corollaries: +`+writeSyncIdentifiesWriter+` returns the `+FieldVersion+` (+ the three +projections) for an explicit-or-implicit Sync; `+observedHasProvenance+` +extracts the witnessing prior-version and `+Sync+` from any `+Observed+` +value. + +|Echo.idr |0 |0 |0 |In package (A0, 2026-04-18). A16 (2026-06-16) estate +accommodation: header re-characterised to the accurate echo-types +definition — a *tropically-graded modality of structured information +loss* (grade = min-plus = `+Tropical.TropCost+` = irrecoverability), +exact-on-a-fiber recoverability; monad/comonad/adjunction VARIANCE +explicitly deferred to upstream `+--safe+` Agda (cf echo-types +RETRACTION R-2026-05-18 + experimental R0–R4). Added `+EchoR+` + +`+echoToResidue+` (mirrors `+echo-types+` `+EchoResidue.agda+`; an +attestation = a retained residue). Categorical base remains the settled +fiber/slice structure. + +|VerifierSpec.idr |0 |0 |0 |Introduced A13 (2026-05-26, PR #72) as +statement-level spec-of-record for post-A10 items 7+8. *Promoted to +total bodies 2026-05-27 (PR #79)*: same `+ModuleSummary+` / +`+FunctionSummary+` / `+OwnershipIntent+` shapes, plus structural +acceptance predicates `+TokenFresh+` / `+IntentsLinearAcceptable+` / +`+FunctionsAccepted+`, the three acceptance predicates `+SpecAccepts+` / +`+VerifierAccepts+` / `+SourceAccepts+` (the latter two carry a +`+TrustedFixture+` inline so the differential ctor still terminates in a +structural witness), the two *agreement records +`+VerifierSpecAgreement+` (item 7) and `+SourceVerifierAgreement+` (item +8)* with totally-proven bodies, concrete inhabitants +`+verifierSpecAgreement+` / `+sourceVerifierAgreement+` (the first total +no-`+believe_me+` agreement values in the codebase), end-to-end +composition lemmas `+sourceImpliesSpec+` / `+specImpliesSource+` and +`+*Concrete+` specialisations, demo modules (empty / `+allocFreeModule+` +/ `+allocFreeWithBorrowModule+` / `+fixtureCleanLinearConsumerModule+` +mirrored from cross_compat row 1), and four discrimination proofs +(`+notSpecAcceptsBadDoubleConsume+`, +`+notVerifierAcceptsBadDoubleConsume+` ruling out BOTH ctors, +`+notSourceAcceptsBadDoubleConsume+` ruling out BOTH ctors, +`+notSpecAcceptsBadDoubleProduce+`) showing L10 has teeth and the +differential escape hatch cannot smuggle a bad module past the verifier. +|=== + +=== Post-codegen verifier (Rust) + +The Idris2 proofs above establish that *the type discipline is sound* — +L1-L10 (and L13-L16) are mechanically verified at the spec level. They +say nothing about whether a particular wasm module out of a particular +codegen actually obeys the discipline. + +`+crates/typed-wasm-verify/+` (added 2026-05-15) closes that loop on the +*post-codegen* side. Given a wasm module plus an `+typedwasm.ownership+` +custom section, the crate runs a per-path `+(min, max)+` use-range +analysis over every function body and reports L7 (aliasing) + L10 +(linearity) violations. It’s a second line of defence: the source-level +checker enforces the rules during compilation; this crate re-checks them +on the emitted IR to catch codegen bugs. + +[width="100%",cols="24%,53%,23%",options="header",] +|=== +|Layer |What it proves |Where +|Idris2 proofs |Type discipline is sound (spec-level) +|`+src/abi/TypedWasm/ABI/*.idr+` + +|Source checker |Source program respects discipline +|`+hyperpolymath/affinescript:lib/codegen.ml+` (QTT pass), upcoming +`+.twasm+` parser/checker + +|*Post-codegen verifier* |*Emitted wasm respects discipline* +|*`+crates/typed-wasm-verify/+` (Rust)* + +`+hyperpolymath/affinescript:lib/{tw_verify,tw_interface}.ml+` (OCaml, +reference impl) +|=== + +The Rust crate + Idris2 `+VerifierSpec.idr+` are the *spec of record* +(ADR-0008, 2026-07-07); the OCaml files are a conforming implementation. +The synthetic-fixture cross-compat suite at +`+crates/typed-wasm-verify/tests/cross_compat.rs+` is the parity oracle; +*C5.1* (`+tests/cross_compat_real.rs+`, landed 2026-05-27 via PR #81) +cross-checks it against real `+affinescript+`-emitted bytes (4-fixture +corpus, regenerate workflow pins affinescript SHA for drift detection). + +*Coverage* (2026-05-27): + +[width="100%",cols="18%,65%,17%",options="header",] +|=== +|Level |Enforced on emitted wasm? |Where +|L7 (aliasing) |*YES* |`+verify_function+` per-path use-range + +|L10 (linearity) |*YES* |`+verify_function+` per-path use-range + +|L13 (module isolation, negative form) |*YES* |`+verify_from_module+`, +gated on ownership-section presence (PR #37, 2026-05-19) + +|L13 (cross-module schema agreement, positive form) |*YES (import-bound, +carrier-backed)* |`+typedwasm.region-imports+` carrier — proposal 0003 +`+[accepted]+` 2026-07-07 → ADR-0007; +`+verify_region_imports_from_module+` (module-local) + +`+verify_link_graph+` (cross-module `+SchemaSub+` → +`+CompatCertificate+`s); gated +`+cargo feature = "unstable-l13-imports"+`; in-tree producer emits from +`+import region … from "…" { … }+` source (`+tests/example02.rs+`) + +|L2 (region binding) |*YES* (carrier-backed) +|`+verify_access_sites_from_module+` PR #109; reads +`+typedwasm.regions+` + `+typedwasm.access-sites+` (proposals 0001 + +0002 `+[accepted]+` 2026-05-30; codec PR #107; gated +`+cargo feature = "unstable-l2"+`) + +|L3–L6 (type-compat, null, bounds, result-type) |*YES* (carrier-backed, +schema half) |`+typedwasm.regions+` codec PR #107; cross-checks against +`+Region.idr::WasmType+`, `+Pointer.idr::Nullability+`, cardinality. +Per-access enforcement gated on producer codegen of access-sites +(`+affinescript#462+`, `+ephapax#251+`). + +|L15 (resource capabilities, L15-A/B) |*YES* (carrier-backed) +|`+verify_capabilities_from_module+` PR #109; reads +`+typedwasm.capabilities+` (proposal 0001 `+[accepted]+`; codec PR #107; +gated `+cargo feature = "unstable-l15"+`). L15-C deferred to proposal +0004 `+[draft]+`. + +|L14, L16 |*out of scope* |Gated on AffineScript surface work (no +`+session+`/`+choreography+` producer emission yet) +|=== + +*Open gating items* (post proposals 0001 + 0002 acceptance, 2026-05-30): + +[arabic] +. *Producer codegen* — verifier passes ship; producer-side emission +lags. See proposal 0001 §"`Appendix B — Producer-readiness checklist`" +for IR prerequisites of each carrier. Tracking: `+affinescript#444+` +(Tw_section dedup, ✅ merged), `+affinescript#462+` (access-sites +codegen, open), `+ephapax#221+` (Ty::Borrow surfacing, open), +`+ephapax#251+` (access-sites codegen, filed 2026-05-30), +`+ephapax#250+` (Codegen dead-fields cleanup, ✅ merged 2026-05-30). +. *L13 cross-module (positive form)* — DONE in-tree (2026-07-07): +proposal 0003 `+[accepted]+` → ADR-0007; codec + `+verify_link_graph+` +behind `+unstable-l13-imports+`; in-tree producer emits from source. +Sibling-producer adoption (AffineScript Roadmap C3 / Ephapax) tracked by +cross-repo issues. +. *L15-C (call-graph monotonicity)* — proposal 0004 `+[draft]+` +(`+docs/proposals/0004+`). Gated on producer-side L15-A emission +(Roadmap C2 not started in either producer). +. *ADR promotion* — DONE (2026-05-30): proposals 0001 + 0002 promoted to +`+docs/decisions/0002-multi-producer-carrier-sections.adoc+` (ADR-0002) +and `+docs/decisions/0003-access-site-carrier.adoc+` (ADR-0003). +Proposal files retained as canonical wire-format references. + +*Spec-of-record alignment (2026-05-27, PR #79).* The +`+TypedWasm.ABI.VerifierSpec+` Idris2 module now states the *verifier ↔ +spec ↔ source* agreement as totally-proven inhabitants of two records +(`+VerifierSpecAgreement+`, `+SourceVerifierAgreement+`). Closes the +multi-week residual flagged by PR #74 ("`Items 7 + 8 stated as +obligations`" from PR #72). The Rust verifier’s accept-verdicts on +differential-harness fixtures are modelled via `+TrustedFixture m+` +values that package the structural witness inline — the trust-injection +moment is `+MkTrustedFixture+` construction (single grep point for +audit). A drift between this module and the Rust verifier’s behaviour +now shows up as either a failing differential-harness fixture or as an +absent `+TrustedFixture+` registration. + +*Consumers* (live as of 2026-05-15): + +* `+hyperpolymath/ephapax:src/ephapax-wasm/+` — emits the +`+typedwasm.ownership+` section on every compile +* `+hyperpolymath/ephapax:src/ephapax-cli/+` — exposes the verifier via +`+ephapax compile --verify-ownership+` + +=== Estate-axis accommodation (A15/A16 — 2026-06-16) + +An adversarially-verified audit (idris2 ground-truth) found that L11/L12 +and the Echo module were internally sound and compiling but *not +accommodated* to the canonical estate repos — each had been +sourced/ported from somewhere _other_ than the canonical repo (Tropical +from `+007-lang+`, Echo from a dead `+~/Desktop/EchoFibers.agda+`, +Epistemic independently reinvented), with stale or absent +cross-references. This is the estate boundary-erosion pattern. The +following accommodation work landed *local, unpushed, all type-checking +under idris2 0.8.0* (`+%default total+`, no `+believe_me+`); the full +`+typed-wasm.ipkg+` package builds green (22 modules): + +[width="100%",cols="17%,43%,40%",options="header",] +|=== +|Axis |Canonical repo |Accommodation +|L11 Tropical |`+tropical-resource-typing+` (Lean4 `+Resource.*+`) @ +`+2e35229+` |cross-doc fixed (was stale `+f6c5a6f+`, Isabelle-only); +added `+tropLe+` dioid order (refl/trans/monotonicity ~ +`+Resource.Algebra.Ordered+`), `+tropMax+` MinMax bottleneck + +`+hubCeiling+` (~ `+Resource.Instances.MinMax+` + +`+Bridge.hub_ceiling_le+`), `+ResidueMeasure+` (~ +`+Resource.EchoBridge+`), `+Level11BottleneckProof+` + +`+bottleneckCeilsEdges+` wired into +`+Proofs.attestL11_Bottleneck+`/`+_Sound+` + +|Echo |`+echo-types+` (Agda) @ `+2bbdb49+` |header re-characterised to +the accurate definition — a *tropically-graded modality of structured +information loss* (grade = min-plus = `+Tropical.TropCost+`), +exact-on-a-fiber recoverability, variance (monad/comonad/adjunction) +*deferred to upstream `+--safe+` Agda* (cf RETRACTION R-2026-05-18 + +experimental R0–R4); added `+EchoR+` + `+echoToResidue+` (~ +`+EchoResidue.agda+`) + +|L12 Epistemic |`+epistemic-types+` (Agda) @ `+87ff8b4+` |cross-doc + +IS-NOT note (read-consistency is a _different_ problem from canonical +standpoint-indexed modality); *additive* `+syncGrade+` reusing sibling +`+Tropical.TropCost+` (∞ = never-synced) — extant A10–A14 proofs +untouched +|=== + +The min-plus grade is the *same object* across all three axes +(`+echo-types+` loss grade ≡ `+Resource.Instances.MinPlus+` ≡ +`+epistemic-types+` `+EchoBridge.Grade+` ≡ `+Tropical.TropCost+`) — +echo/tropical/epistemic are one graded structure. + +*Upstream drafts prepped (local, unpushed, await owner review)* — three +extend-upstream candidates, each verified by its own prover: + +* `+tropical-resource-typing/Resource/Closure.lean+` — +Kleene/Floyd-Warshall all-pairs closure functor over +`+[ResourceAlgebra R]+` (order/monotonicity/bound half proved; +star-equation algebra deferred). `+lake build+` green, no axioms. +* `+epistemic-types/src/EpistemicTypes/ReadConsistency.agda+` — +version-monotone re-sync liveness as a concrete `+AccessibleModality+` +instance. `+--safe+`, closed. +* `+echo-types/proofs/agda/EchoDisplayed.agda+` — +`+Displayed+`/`+DispHom+`/ `+fromHomOver+` fibration packaging (no +comonad claims). `+--safe+`, closed. + +Nothing pushed or PR’d — drafts are for owner review per the stop-first +rule. diff --git a/LEVEL-STATUS.md b/LEVEL-STATUS.md deleted file mode 100644 index 11db417..0000000 --- a/LEVEL-STATUS.md +++ /dev/null @@ -1,232 +0,0 @@ -# SPDX-License-Identifier: CC-BY-SA-4.0 - -# typed-wasm Level Achievement Status - -## Versioning Scheme (revised 2026-04-13 — typed-wasm-first rollout) - -typed-wasm versions track BOTH the highest fully-achieved level tier and the -surface-syntax sugar additions. The rollout now interleaves level work with -consumer-language enablement — see `spec/L13-L16-reserved-syntax.adoc` for the -full trajectory and keyword reservations. - -| Version | Levels | Surface | Meaning | -|---------|--------|---------|---------| -| v0.1 | L1-10 | v0.1 grammar | Checked proof core (proofs + runtime L1-6, compile-time L7-10) | -| v1.0 | L1-10 | v0.1 grammar | Audited release of the checked core | -| v1.1 | L1-10 | v0.2 sugar | `const`, `match` on unions, block-expr `if`, split effects `{memory:, caps:}`, `striated` regions. L11-L12 remain draft. | -| v1.2 | L1-10, L13 | v0.3 sugar | +L13 Module isolation: `module Name isolated { ... }`, `private_memory`, `boundary`. Idris2 proof: ModuleIsolation.idr. Surface enforcement: Checker.checkIsolatedModule. | -| v1.3 | L1-10, L13, L14 | v0.4 sugar | +L14 Session protocols: `session Name { state ...; transition consume X -> yield Y; dual : ...; }`. Idris2 proof: SessionProtocol.idr (SessionHandle parameterised by state index, step soundness, DualPair symmetry). Surface enforcement: Checker.checkSession. 63/63 parser tests. | -| **v1.4** | **L1-10, L13, L14, L15** | **v0.5 sugar** | **+L15 Resource capabilities: `capability NAME;` top-level and isolated-module-body declarations; v1.1 `caps: { ... }` sub-clause becomes load-bearing. Idris2 proof: ResourceCapabilities.idr (DistinctCaps L15-A, ContainedIn + containedTrans L15-B, CallCompatible + callCompose L15-C, FullEffectBudget orthogonality with L8). Surface enforcement: Checker.checkCapabilities + scope-threaded checkDeclaration. L15-A (distinct) + L15-B (well-scoped) live at v1.4; L15-C (call-graph monotone) deferred to v1.4.x (proof already carries the theorem). 76/76 parser tests pass.** | -| **v1.5** | **L1-10, L13, L14, L15, L16** | **v0.6 sugar** | **+L16 Agent choreography: `choreography { agent_role ...; message ...; composes: L13 + L14 + L15; }`. Idris2 proof: Choreography.idr (composition-only theorem citing lower levels). Surface enforcement: Checker.checkChoreography (L16-A..L16-D). 88/88 parser tests pass.** | -| L17 (reserved) | L1-L16, **L17** | future | "Layout-proof striation" with `strided_ptr` — removes the projection-only restriction on striated regions | - -**L11 (Tropical)** and **L12 (Epistemic)** remain draft-only at v1.1. They are -orthogonal to the L13-L16 rollout and can promote to checked-in-package at -any intermediate version without blocking the main trajectory. L11 is the -natural home for "striation is cheaper" proofs once it lands. - -## v1.1 surface sugar — status - -| Feature | Grammar | AST | Lexer | Parser | Checker | Tests | -|---------|---------|-----|-------|--------|---------|-------| -| `const` top-level | spec/grammar.ebnf | Ast.ConstDecl | Const | **DONE** parseConstDecl (Parser.affine:2088) | Checker.constValueIsLiteral | **DONE** | -| `match` on union | spec/grammar.ebnf | Ast.MatchStmt | Match | **DONE** (Parser.affine:1191) | Checker.matchIsExhaustive | **DONE** | -| Block-expr `if` | spec/grammar.ebnf | Ast.BlockIfExpr | Yield | **DONE** (Parser.affine:529) | Checker.blockIfBranchesAgree | **DONE** | -| Split `effects` | spec/grammar.ebnf | functionDecl.caps | (contextual) | **DONE** parseEffectsClause (Parser.affine:1554) | (opaque until L15) | **DONE** | -| `striated` regions | spec/grammar.ebnf | regionDecl.layout | Striated | **DONE** | Checker.striatedLayoutIsWellFormed | **DONE** | -| Reserved keywords (L13-L16) | spec/L13-L16-reserved-syntax.adoc | — | contextual (per-block) | **DONE** (Parser.affine:2685-2718) | — | **DONE** (v1.4/v1.5 rejection tests) | - -**v1.1 surface sugar fully landed: parser, checker, tests all live. -88/88 parser tests pass (verified 2026-04-18). LEVEL-STATUS table was stale -between 2026-04-13 (AST landed) and 2026-04-18 (verification).** - -## Current: checked core = L1-10 + L13-L16, L11-L12 = draft - -| Level | Name | Idris2 Proof | Zig FFI | Tests | Status | -|-------|------|-------------|---------|-------|--------| -| 1 | Instruction validity | Region.idr | Parser | ECHIDNA 10^5 | **E2E complete** | -| 2 | Region-binding | Region.idr + TypedAccess.idr | Schema lookup | ECHIDNA 10^5 | **E2E complete** | -| 3 | Type-compatible access | TypedAccess.idr | Typed load/store | ECHIDNA 10^5 | **E2E complete** | -| 4 | Null safety | Pointer.idr | Pointer kinds | ECHIDNA 10^5 | **E2E complete** | -| 5 | Bounds-proof | TypedAccess.idr + Levels.idr | Bounds check | ECHIDNA 10^5 | **E2E complete** | -| 6 | Result-type | TypedAccess.idr | Type flow | ECHIDNA 10^5 | **E2E complete** | -| 7 | Aliasing safety | Pointer.idr (Unique) | Erased (QTT) | ECHIDNA 10^4 | **Proven [sfap], erased** | -| 8 | Effect-tracking | Effects.idr | Erased (QTT) | ECHIDNA 10^4 | **Proven [sfap], erased. Preorder + composition theorems added A5 (2026-04-18): `subsumeRefl` (alias of `effectSubsumesRefl`), `hasEffectTrans`, `subsumeTrans`, `hasEffectCombineL`/`CombineR`, `subsumePrepend`/`Append`, and the flagship `subsumeCompose` giving `EffectSubsumes d1 a1 -> EffectSubsumes d2 a2 -> EffectSubsumes (d1++d2) (a1++a2)` so L8 attestations compose.** | -| 9 | Lifetime safety | Lifetime.idr | Erased (QTT) | ECHIDNA 10^4 | **Proven [sfap], erased. Preorder + load-safety theorems added A4 (2026-04-18): `outlivesRefl`, `outlivesTrans` (alias of pre-existing `outlivesTransitive` with 7-constructor case analysis), `loadSafe` proof-term, behavioural lemmas `loadSafeOffset` and `loadSafeIrrelevant` (proof irrelevance at the value level).** | -| 10 | Linearity | Linear.idr (QTT q=1) | Erased (QTT) | ECHIDNA 10^4 | **Proven [sfap], erased. Propositional state-machine theorems added A3 (2026-04-18): distinctUsage, consumePreservesData, noReuse, noReuseEcho — usage-indexed handle `LinHandleU Fresh/Consumed tok` with `consume` state transition, alongside the QTT structural layer.** | -| 11 | Tropical cost-tracking | Tropical.idr | Not yet | None | **In package (A1, 2026-04-18). Commutative-semiring closure PROVEN (A2, 2026-04-18): all 12 axioms. Uses structural `tropMin` (007-lang template). Zero dangerous patterns. A16 (2026-06-16) estate accommodation: added the canonical dioid ORDER layer (`tropLe` refl/trans + add/mul monotonicity, mirrors `tropical-resource-typing` `Resource.Algebra.Ordered`), the MinMax BOTTLENECK layer (`tropMax` + `hubCeiling`, mirrors `Resource.Instances.MinMax` + `Bridge.hub_ceiling_le`), `ResidueMeasure` (E→R, mirrors `Resource.EchoBridge`), and `Level11BottleneckProof` + `bottleneckCeilsEdges` wired into `Proofs.attestL11_Bottleneck`/`_Sound`.** | -| 12 | Epistemic safety | Epistemic.idr | Not yet | None | **In package (A1, 2026-04-18); A10 (2026-05-26) closes the "freshness propagation under concurrent writes" gap with `freshnessPropagatesUnderWrites` + supporting theorems (11 total; closes PROOF-NEEDS §P1.2). A15 (2026-06-16) estate accommodation: ADDITIVE `syncGrade` layer reusing sibling `Tropical.TropCost` (∞ = never-synced) + `neverSyncedInfeasible`/`observedFeasible`/`observedNotInfeasible` — extant Nat-indexed proofs untouched. Header IS-NOT note: this read-consistency model is a DIFFERENT problem from canonical `epistemic-types`' standpoint-indexed modality.** | -| 13 | Module isolation | ModuleIsolation.idr | (per-module handles, future) | 12 parser/Checker tests | **v1.2 — Idris2 proof + surface checker live; 007 lowering DONE (task #5)** | -| 14 | Session protocols | SessionProtocol.idr | (typed-state handles, future) | 13 parser/Checker tests | **v1.3 — Idris2 proof + surface checker live; 007 send/receive lowering DONE (task #7)** | -| 15 | Resource capabilities | ResourceCapabilities.idr | (future) | 13 parser/Checker tests | **v1.4 — Idris2 proof + surface checker (L15-A + L15-B) live; L15-C call-graph check deferred to v1.4.x; 007 lowering DONE (task #9)** | -| 16 | Agent choreography | Choreography.idr | (future) | 12 parser/Checker tests | **v1.5 — composition proof over L13+L14+L15 live; surface checker enforces L16-A (role targets exist), L16-B (message endpoints declared), L16-C (payload primitive/declared region ref), L16-D (exact `L13 + L14 + L15` composition spec).** | - -**[sfap]** = "so far as possible" — proofs are machine-checked in Idris2 with -zero dangerous patterns. They are as complete as the Idris2 type checker can -verify. Full mechanical verification against a formal Wasm operational -semantics (e.g. WasmCert-Isabelle) remains future work. - -## What "proven, erased" means - -Levels 7-10 are verified by the Idris2 type checker at compile time, then -erased before code generation via QTT (Quantitative Type Theory). The -emitted Wasm is identical to hand-written code — zero runtime overhead. -This is by design, not a gap. The proofs exist to catch bugs at compile -time; they are not needed at runtime. - -## What "draft" means - -Levels 11-12 are draft for surface semantics, not for ipkg membership. -As of 2026-04-18 (commit A1) both `Tropical.idr` and `Epistemic.idr` are -in `typed-wasm.ipkg` and build clean under Idris2 0.8.0 — see the -2026-05-18 reconciliation in `PROOF-NEEDS.md`. The "draft" label -applies to the level semantics themselves (Tropical cost-tracking and -Epistemic freshness propagation under concurrent writes remain -research-grade): theorems live, but the surface language and Zig FFI -do not yet expose them. Wiring these levels through the rest of the -toolchain remains future work. - -## Proof inventory - -| File | believe_me | postulate | assert_total | Checked status | -|------|-----------|-----------|--------------|----------------| -| Region.idr | 0 | 0 | 0 | In package. Structural injectivity added A8 (2026-04-18): `fieldNameInj` / `fieldTypeInj` / `fieldInj` (MkField constructor injectivity), `schemaEqSym` / `schemaEqTrans` (making SchemaEq a full equivalence relation with the pre-existing `schemaEqRefl`), `lookupFieldName` (L2 soundness — `FieldIn name schema` implies `fieldName (lookupField prf) = name`). A12 (2026-05-26): byte-disjointness layer added — `RegionDisjoint r1 r2` (two constructors covering both orderings of footprint endpoints) plus `regionDisjointSym` proving symmetry. Closes post-A10 audit item 6. A13 (2026-05-26): byte-separation cross-level layer added — `RegionsOverlap r1 r2` (an address inside both region footprints), `disjointImpliesNoOverlap` proving `RegionDisjoint r1 r2 -> Not (RegionsOverlap r1 r2)`, plus `regionsOverlapSym`. Closes the L7/L10 cross-level link explicitly deferred at A12. | -| TypedAccess.idr | 0 | 0 | 0 | In package | -| Levels.idr | 0 | 0 | 0 | In package | -| Pointer.idr | 0 | 0 | 0 | In package | -| Effects.idr | 0 | 0 | 0 | In package | -| Lifetime.idr | 0 | 0 | 0 | In package | -| Linear.idr | 0 | 0 | 0 | In package | -| MultiModule.idr | 0 | 0 | 0 | In package. Flagship no-spoofing theorem proven A6 (2026-04-18): `FieldMatches`, `SchemaSub` preorder (`schemaSubRefl`, `schemaSubTrans`), `ModuleCompat` indexed on modules + schemas (`compatRefl`, `compatTrans`), and the flagship `noSpoofing : ModuleCompat from to imp exp -> FieldMatches f imp -> FieldMatches f exp`. Worked Rust-exports / AffineScript-imports example (4-field export, 2-field import subset) constructs a live certificate and applies the theorem. A10 (2026-05-26) closes the deferred `compatCommute` item: mutual-subschema commutativity `compatCommute : ModuleCompat from to imp exp -> SchemaSub exp imp -> ModuleCompat to from exp imp`, plus the `noSpoofingBidir` corollary returning a pair of field-transport functions. Second worked example (`serviceA`/`serviceB` with permuted schemas) demonstrates `compatCommute` on a case where both `SchemaSub` directions hold. | -| ModuleIsolation.idr | 0 | 0 | 0 | In package (v1.2 / L13). A13 (2026-05-26): L13×L10 cross-level layer added — imports `Linear`, exposes `LinearAcrossBoundary from to regName bs token` (an L13 `AccessWitness` paired with an L10 `LinHandle`) plus accessors `acrossWitness` / `acrossHandle`, the no-bypass theorem `linearTransferRequiresBoundary` (any non-local linear-handle transfer requires a concrete boundary in `bs`, proved by reusing `crossAccessImpliesBoundary`), and `linearTransferLocal` (local-case constructor). Closes post-A10 audit item 5a. | -| SessionProtocol.idr | 0 | 0 | 0 | In package (v1.3 / L14). A13 (2026-05-26): L14×L13 cross-level layer added — imports `ModuleIsolation`, exposes `SessionAcrossBoundary from to proto state regName bs` plus accessors, `sessionAcrossPreservesState` (the state index survives the transfer), `sessionTransferRequiresBoundary` (no-bypass, same shape as the L10 version one level up), and `sessionTransferLocal`. Closes post-A10 audit item 5b. | -| ResourceCapabilities.idr | 0 | 0 | 0 | In package (v1.4 / L15). A12 (2026-05-26): `containedConcat` proves `ContainedIn` distributes over `++`; `jointBudgetCompose` proves the L8 ↔ L15 **joint** budget composition theorem — given individual `EffectSubsumes` witnesses and individual `FunctionCaps` witnesses for two functions sharing an owner module, the compound function still satisfies both the combined L8 envelope (via `subsumeCompose`) AND the combined L15 module envelope (via `containedConcat` + `l15bSoundness`). Closes post-A10 audit item 3. | -| Choreography.idr | 0 | 0 | 0 | In package (v1.5 / L16) | -| Proofs.idr | 0 | 0 | 0 | In package. Attestation API hardened A7 (2026-04-18): every L1-L10 attestation now requires a witness from its level module (Schema / FieldIn / WasmTypeCompat / Ptr-NonNull / InBounds / AccessResult / ExclusiveWitness / EffectSubsumes / Lifetime.Outlives / CompletedProtocol). `simpleReadCert` / `fullCert12` / `fullCert15` thread witnesses per level; the certificate cannot be constructed without real proof artefacts. Level-achievement layer added A8 (2026-04-18): `LevelAchievedIn` predicate, `achievedAppendL` / `achievedAppendR` list-append preservation, `LevelAchieved n cert` lifted to certificates, `composeAchievedL` / `composeAchievedR` proving any level achieved in either component of `composeCertificates` is still achieved in the composition. Attestation soundness A9 (2026-05-18): per-level `attestLN_Sound` family proving `LevelAchievedIn N [attestLN_X w]` — the weak "certificate claims level N" face. A11 (2026-05-26): partial laws for `composeCertificates` — `achievedAppendSplit`, `composeAssocLists`, `composeAchievedSym`. A12 (2026-05-26): switched `composeCertificates` from Ord-derived `Prelude.min` to structural `Data.Nat.minimum`; **full** `composeAssoc`; `composeHighProvenComm`. Closes post-A10 audit item 4 in full. **Witness-indexed redesign 2026-05-27 (PR #80, closes standards#130 long-tail)**: `LevelAttestationW : (n : Nat) -> Type` GADT with one ctor per level packaging the actual witness; 15 `attestLNW_*` smart ctors; 15 `attestLNW_Entails` extractors (a consumer holding `LevelAttestationW 7` can now discharge L7 alias-freeness via `ExclusiveWitness s`, not just the weak claim-predicate); `toLegacy` bridge; 15 round-trip `Refl`s; uniform `attestLW_AchievedIn` subsuming the A9 family. **`WitnessCertificate` lift 2026-05-27 (PR #80, folded from #83)**: existential `SomeAttestationW` wrapper, `record WitnessCertificate` mirror of `ProofCertificate` with witness-carrying levels, `witnessToLegacy` bridge, `composeWitness` mirror, `composeWitnessLegacyAgree` compat lemma, `WitnessAchieved` predicate. | -| Tropical.idr | 0 | 0 | 0 | In package (A1, 2026-04-18) | -| Epistemic.idr | 0 | 0 | 0 | In package (A1, 2026-04-18). A10 (2026-05-26): propagation theorems added — `freshImpliesEqual`, `staleImpliesLT`, `freshNotStale` (mutual exclusion via local `ltIrreflexive`), `concurrentWriteStales`, `resyncRecoversFresh`, the flagship `freshnessPropagatesUnderWrites`, `syncChainEndsFresh`, and the `epistemicFreshness` projector on `Level12Proof` (closes PROOF-NEEDS §P1.2). A11 (2026-05-26): constructor-tightening pass — `WriteSync` now demands a `FieldVersion` witness with three equality components (`field`/`version`/`lastWriter`), and `Knowledge.Observed` is grounded in a `Sync` event (no more unfounded versions). Corollaries: `writeSyncIdentifiesWriter` returns the `FieldVersion` (+ the three projections) for an explicit-or-implicit Sync; `observedHasProvenance` extracts the witnessing prior-version and `Sync` from any `Observed` value. | -| Echo.idr | 0 | 0 | 0 | In package (A0, 2026-04-18). A16 (2026-06-16) estate accommodation: header re-characterised to the accurate echo-types definition — a **tropically-graded modality of structured information loss** (grade = min-plus = `Tropical.TropCost` = irrecoverability), exact-on-a-fiber recoverability; monad/comonad/adjunction VARIANCE explicitly deferred to upstream `--safe` Agda (cf echo-types RETRACTION R-2026-05-18 + experimental R0–R4). Added `EchoR` + `echoToResidue` (mirrors `echo-types` `EchoResidue.agda`; an attestation = a retained residue). Categorical base remains the settled fiber/slice structure. | -| VerifierSpec.idr | 0 | 0 | 0 | Introduced A13 (2026-05-26, PR #72) as statement-level spec-of-record for post-A10 items 7+8. **Promoted to total bodies 2026-05-27 (PR #79)**: same `ModuleSummary` / `FunctionSummary` / `OwnershipIntent` shapes, plus structural acceptance predicates `TokenFresh` / `IntentsLinearAcceptable` / `FunctionsAccepted`, the three acceptance predicates `SpecAccepts` / `VerifierAccepts` / `SourceAccepts` (the latter two carry a `TrustedFixture` inline so the differential ctor still terminates in a structural witness), the two **agreement records `VerifierSpecAgreement` (item 7) and `SourceVerifierAgreement` (item 8)** with totally-proven bodies, concrete inhabitants `verifierSpecAgreement` / `sourceVerifierAgreement` (the first total no-`believe_me` agreement values in the codebase), end-to-end composition lemmas `sourceImpliesSpec` / `specImpliesSource` and `*Concrete` specialisations, demo modules (empty / `allocFreeModule` / `allocFreeWithBorrowModule` / `fixtureCleanLinearConsumerModule` mirrored from cross_compat row 1), and four discrimination proofs (`notSpecAcceptsBadDoubleConsume`, `notVerifierAcceptsBadDoubleConsume` ruling out BOTH ctors, `notSourceAcceptsBadDoubleConsume` ruling out BOTH ctors, `notSpecAcceptsBadDoubleProduce`) showing L10 has teeth and the differential escape hatch cannot smuggle a bad module past the verifier. | - -## Post-codegen verifier (Rust) - -The Idris2 proofs above establish that **the type discipline is sound** — -L1-L10 (and L13-L16) are mechanically verified at the spec level. They -say nothing about whether a particular wasm module out of a particular -codegen actually obeys the discipline. - -`crates/typed-wasm-verify/` (added 2026-05-15) closes that loop on the -**post-codegen** side. Given a wasm module plus an -`typedwasm.ownership` custom section, the crate runs a per-path -`(min, max)` use-range analysis over every function body and reports -L7 (aliasing) + L10 (linearity) violations. It's a second line of -defence: the source-level checker enforces the rules during compilation; -this crate re-checks them on the emitted IR to catch codegen bugs. - -| Layer | What it proves | Where | -|-------|----------------|-------| -| Idris2 proofs | Type discipline is sound (spec-level) | `src/abi/TypedWasm/ABI/*.idr` | -| Source checker | Source program respects discipline | `hyperpolymath/affinescript:lib/codegen.ml` (QTT pass), upcoming `.twasm` parser/checker | -| **Post-codegen verifier** | **Emitted wasm respects discipline** | **`crates/typed-wasm-verify/` (Rust)** + `hyperpolymath/affinescript:lib/{tw_verify,tw_interface}.ml` (OCaml, reference impl) | - -The Rust crate + Idris2 `VerifierSpec.idr` are the **spec of record** -(ADR-0008, 2026-07-07); the OCaml files are a conforming -implementation. The synthetic-fixture cross-compat -suite at `crates/typed-wasm-verify/tests/cross_compat.rs` is the -parity oracle; **C5.1** (`tests/cross_compat_real.rs`, landed -2026-05-27 via PR #81) cross-checks it against real -`affinescript`-emitted bytes (4-fixture corpus, regenerate workflow -pins affinescript SHA for drift detection). - -**Coverage** (2026-05-27): - -| Level | Enforced on emitted wasm? | Where | -|-------|---------------------------|-------| -| L7 (aliasing) | **YES** | `verify_function` per-path use-range | -| L10 (linearity) | **YES** | `verify_function` per-path use-range | -| L13 (module isolation, negative form) | **YES** | `verify_from_module`, gated on ownership-section presence (PR #37, 2026-05-19) | -| L13 (cross-module schema agreement, positive form) | **YES (import-bound, carrier-backed)** | `typedwasm.region-imports` carrier — proposal 0003 `[accepted]` 2026-07-07 → ADR-0007; `verify_region_imports_from_module` (module-local) + `verify_link_graph` (cross-module `SchemaSub` → `CompatCertificate`s); gated `cargo feature = "unstable-l13-imports"`; in-tree producer emits from `import region … from "…" { … }` source (`tests/example02.rs`) | -| L2 (region binding) | **YES** (carrier-backed) | `verify_access_sites_from_module` PR #109; reads `typedwasm.regions` + `typedwasm.access-sites` (proposals 0001 + 0002 `[accepted]` 2026-05-30; codec PR #107; gated `cargo feature = "unstable-l2"`) | -| L3–L6 (type-compat, null, bounds, result-type) | **YES** (carrier-backed, schema half) | `typedwasm.regions` codec PR #107; cross-checks against `Region.idr::WasmType`, `Pointer.idr::Nullability`, cardinality. Per-access enforcement gated on producer codegen of access-sites (`affinescript#462`, `ephapax#251`). | -| L15 (resource capabilities, L15-A/B) | **YES** (carrier-backed) | `verify_capabilities_from_module` PR #109; reads `typedwasm.capabilities` (proposal 0001 `[accepted]`; codec PR #107; gated `cargo feature = "unstable-l15"`). L15-C deferred to proposal 0004 `[draft]`. | -| L14, L16 | **out of scope** | Gated on AffineScript surface work (no `session`/`choreography` producer emission yet) | - -**Open gating items** (post proposals 0001 + 0002 acceptance, 2026-05-30): - -1. **Producer codegen** — verifier passes ship; producer-side emission - lags. See proposal 0001 §"Appendix B — Producer-readiness checklist" - for IR prerequisites of each carrier. Tracking: - `affinescript#444` (Tw_section dedup, ✅ merged), `affinescript#462` - (access-sites codegen, open), `ephapax#221` (Ty::Borrow surfacing, - open), `ephapax#251` (access-sites codegen, filed 2026-05-30), - `ephapax#250` (Codegen dead-fields cleanup, ✅ merged 2026-05-30). -2. **L13 cross-module (positive form)** — DONE in-tree (2026-07-07): - proposal 0003 `[accepted]` → ADR-0007; codec + `verify_link_graph` - behind `unstable-l13-imports`; in-tree producer emits from source. - Sibling-producer adoption (AffineScript Roadmap C3 / Ephapax) - tracked by cross-repo issues. -3. **L15-C (call-graph monotonicity)** — proposal 0004 `[draft]` - (`docs/proposals/0004`). Gated on producer-side L15-A emission - (Roadmap C2 not started in either producer). -4. **ADR promotion** — DONE (2026-05-30): proposals 0001 + 0002 - promoted to `docs/decisions/0002-multi-producer-carrier-sections.adoc` - (ADR-0002) and `docs/decisions/0003-access-site-carrier.adoc` - (ADR-0003). Proposal files retained as canonical wire-format - references. - -**Spec-of-record alignment (2026-05-27, PR #79).** The -`TypedWasm.ABI.VerifierSpec` Idris2 module now states the -**verifier ↔ spec ↔ source** agreement as totally-proven -inhabitants of two records (`VerifierSpecAgreement`, -`SourceVerifierAgreement`). Closes the multi-week residual flagged -by PR #74 ("Items 7 + 8 stated as obligations" from PR #72). The -Rust verifier's accept-verdicts on differential-harness fixtures are -modelled via `TrustedFixture m` values that package the structural -witness inline — the trust-injection moment is `MkTrustedFixture` -construction (single grep point for audit). A drift between this -module and the Rust verifier's behaviour now shows up as either a -failing differential-harness fixture or as an absent -`TrustedFixture` registration. - -**Consumers** (live as of 2026-05-15): - -- `hyperpolymath/ephapax:src/ephapax-wasm/` — emits the - `typedwasm.ownership` section on every compile -- `hyperpolymath/ephapax:src/ephapax-cli/` — exposes the verifier via - `ephapax compile --verify-ownership` - -## Estate-axis accommodation (A15/A16 — 2026-06-16) - -An adversarially-verified audit (idris2 ground-truth) found that L11/L12 and -the Echo module were internally sound and compiling but **not accommodated** to -the canonical estate repos — each had been sourced/ported from somewhere *other* -than the canonical repo (Tropical from `007-lang`, Echo from a dead -`~/Desktop/EchoFibers.agda`, Epistemic independently reinvented), with stale or -absent cross-references. This is the estate boundary-erosion pattern. The -following accommodation work landed **local, unpushed, all type-checking under -idris2 0.8.0** (`%default total`, no `believe_me`); the full `typed-wasm.ipkg` -package builds green (22 modules): - -| Axis | Canonical repo | Accommodation | -|------|----------------|---------------| -| L11 Tropical | `tropical-resource-typing` (Lean4 `Resource.*`) @ `2e35229` | cross-doc fixed (was stale `f6c5a6f`, Isabelle-only); added `tropLe` dioid order (refl/trans/monotonicity ~ `Resource.Algebra.Ordered`), `tropMax` MinMax bottleneck + `hubCeiling` (~ `Resource.Instances.MinMax` + `Bridge.hub_ceiling_le`), `ResidueMeasure` (~ `Resource.EchoBridge`), `Level11BottleneckProof` + `bottleneckCeilsEdges` wired into `Proofs.attestL11_Bottleneck`/`_Sound` | -| Echo | `echo-types` (Agda) @ `2bbdb49` | header re-characterised to the accurate definition — a **tropically-graded modality of structured information loss** (grade = min-plus = `Tropical.TropCost`), exact-on-a-fiber recoverability, variance (monad/comonad/adjunction) **deferred to upstream `--safe` Agda** (cf RETRACTION R-2026-05-18 + experimental R0–R4); added `EchoR` + `echoToResidue` (~ `EchoResidue.agda`) | -| L12 Epistemic | `epistemic-types` (Agda) @ `87ff8b4` | cross-doc + IS-NOT note (read-consistency is a *different* problem from canonical standpoint-indexed modality); **additive** `syncGrade` reusing sibling `Tropical.TropCost` (∞ = never-synced) — extant A10–A14 proofs untouched | - -The min-plus grade is the **same object** across all three axes -(`echo-types` loss grade ≡ `Resource.Instances.MinPlus` ≡ `epistemic-types` -`EchoBridge.Grade` ≡ `Tropical.TropCost`) — echo/tropical/epistemic are one -graded structure. - -**Upstream drafts prepped (local, unpushed, await owner review)** — three -extend-upstream candidates, each verified by its own prover: - -- `tropical-resource-typing/Resource/Closure.lean` — Kleene/Floyd-Warshall - all-pairs closure functor over `[ResourceAlgebra R]` (order/monotonicity/bound - half proved; star-equation algebra deferred). `lake build` green, no axioms. -- `epistemic-types/src/EpistemicTypes/ReadConsistency.agda` — version-monotone - re-sync liveness as a concrete `AccessibleModality` instance. `--safe`, closed. -- `echo-types/proofs/agda/EchoDisplayed.agda` — `Displayed`/`DispHom`/ - `fromHomOver` fibration packaging (no comonad claims). `--safe`, closed. - -Nothing pushed or PR'd — drafts are for owner review per the stop-first rule. diff --git a/PROOF-NEEDS.adoc b/PROOF-NEEDS.adoc new file mode 100644 index 0000000..5b8f329 --- /dev/null +++ b/PROOF-NEEDS.adoc @@ -0,0 +1,1169 @@ +== PROOF-NEEDS.md + +*Scope:* handoff document for the Claude instance that will deepen +typed-wasm’s formal verification. Read this file in full before touching +`+src/abi/TypedWasm/ABI/*.idr+`. Written 2026-04-13 by the dual-AST / +parser-panic cleanup Claude after a targeted audit. + +=== The one-line honest summary + +typed-wasm has *eleven Idris2 files encoding a safety protocol using QTT +linearity and dependent types, zero dangerous patterns, but almost no +explicit theorems* — most of the guarantees are structural consequences +of the type encoding rather than propositions that have been stated and +mechanically proven. `+Proofs.idr+` ceremonially rubber-stamps +attestations without using their witnesses. The next Claude’s job is to +close the gap between "`the types forbid it at compile time`" (true) and +"`here is a lemma proving it is forbidden`" (mostly absent). The +distinction matters for publication-quality claims — a reviewer asking +_"`where is the theorem?`"_ currently has no answer to point at. + +=== RECONCILIATION 2026-06-16 (codegen climb — the second assurance axis: T1 execution gate landed, T2 in progress) + +____ +*The honest summary above concerns the _Idris-model_ axis ("`where is +the theorem?`"). This block introduces the _codegen→verified-wasm_ axis +— the assurance that the Rust producer’s emitted bytes are what an +independent verifier accepts and a wasm engine executes correctly. The +two axes are complementary: the Idris ABI proves the _protocol_; the +climb proves the _running implementation honours it_. (Module count is +now 22, not the "`eleven`" of the 2026-04-13 summary — later +reconciliations supersede it.)* + +*The assurance ladder (`+.twasm+` source → IR → emitted wasm → +verified):* + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|Tier |Obligation |Status (2026-06-16) +|*T1* Execution gate |emitted store/load bodies _compute_ the intended +memory semantics (width, offset, sign/zero-extension, no-clobber) |✅ +*landed* — `+crates/typed-wasm-codegen/tests/execute_lowering.rs+` +instantiates the lowered module in *wasmi* (pure-Rust, runs in CI +without a system wasmtime) and round-trips every scalar width + proves a +narrow store touches *only* its own bytes. Proven non-vacuous by +mutation (reintroducing a narrow-width bug fails the gate). + +|*T2* Verifier self-certification |the verifier independently _decodes +the code section_ and checks each pinned access lands on a load/store of +the field’s exact type/width/offset, in-region |🟡 *in progress* (this +session). Producer half: access sites pinned to a body-instruction index +(`+AccessSite.instr_index: Option+`; the hand-built `+example01+` +/ paint-type representative sites are carried *declared-only*, honestly +_not_ type-checked). Verifier half: `+verify_access_typing_from_module+` ++ `+AccessTypingReport { type_verified, declared_only, errors }+`, +surfaced by `+tw-verify+`. Closes proposal-0002’s deferred +`+AccessSiteMisalignment+`. + +|*T3* Parser totality |the `+.twasm+` parser never panics on any input +|⚠️ *partial* — v0 hardened against malformed/truncated input (PR #168), +but *3 pre-existing arithmetic panics remain* (div-by-zero / overflow in +`+parse_array_size_expr+` + `+compute_region_byte_size+`). Deferred to a +hardening PR. + +|*T4* Layout-equivalence lemma |`+Layout/ABI.idr+` field offsets *=* +Rust `+resolve_field+` offsets |❌ *open* — two independent +implementations of the same field-offset arithmetic, with no proof they +agree. The next formal bridge. + +|*T5a* Verifier↔spec link |the Rust verifier _refines_ +`+VerifierSpec.idr+` |◐ *trusted-base* — ADR-0005 pins audit invariants +(I1 provenance / I2 witness fidelity / I3 module shape) at the +`+MkTrustedFixture+` boundary; the Rust verifier remains the trusted +base. Constructive soundness (path 2) and WasmCert tie-back (path 1) are +future superseding ADRs. + +|*T5b* Wasm-semantics tie-back |emitted bytes mean what we claim under a +mechanised wasm semantics (WasmCert-Isabelle/Coq) |❌ *open* — +multi-week external dependency. T1’s execution gate is the empirical +stand-in. +|=== + +*Climb position.* Front-end staircase (languages → typed-region IR) is +stop-gapped by the `+.twasm+` parser seam (ADR-0004 _Proposed_; real +AffineScript/ephapax AST bridge deferred). Back-end staircase (IR → +verified wasm) is where the climb is: Steps 1 (field readers, #169) + 2 +(field writers + width-exact scalar accesses, #171) merged; the T1 gate +landed alongside; T2 self-certification is the active work, then the T4 +layout lemma, then the T5a verifier↔spec link. + +*Ground truth re-verified 2026-06-16:* +`+idris2 --build src/abi/typed-wasm.ipkg+` → exit 0, *22/22 modules*; +zero `+believe_me+` / `+postulate+` / `+sorry+` / `+Admitted+` / +`+assert_total+` / holes (every scanner hit is a docstring disclaimer). +The `+docs/proof-debt.md+` zero-debt invariant holds. + +*Governance note.* The whole `+crates/typed-wasm-verify/src/+` +(`+verify.rs+`, `+section.rs+`, `+lib.rs+`) carried the SPDX tag but was +*missing the literal owner `+Copyright+` line* — invisible drift that +trips the strict pre-commit hook on any commit touching those files (so +T2’s verifier half was commit-blocked). Surfaced and corrected under a +one-time owner authorisation this session; the hook is kept strict. + +*No `+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+` / +`+assert_smaller+` introduced; `+%default total+` preserved. T1 is an +executable test, not a proof obligation; T2 is a decode-time check +_inside_ the (trusted-base) Rust verifier — it strengthens the trusted +base’s self-consistency, it does not reduce the trusted base.* +____ + +=== RECONCILIATION 2026-06-16 (A15/A16 — estate-axis accommodation) + +____ +L11/L12/Echo have been *cross-documented and mirrored to the canonical +estate repos* after an adversarially-verified audit found them +internally-sound but un-accommodated (sourced/ported from non-canonical +origins). New, machine-checked (idris2 0.8.0, full `+typed-wasm.ipkg+` +green): + +* *Tropical.idr* — dioid order `+tropLe+` (refl/trans + add/mul +monotonicity), MinMax bottleneck `+tropMax+` + `+hubCeiling+`, +`+ResidueMeasure+`, and a new `+Level11BottleneckProof+` + +`+bottleneckCeilsEdges+` wired into +`+Proofs.attestL11_Bottleneck+`/`+_Sound+`. Mirrors +`+tropical-resource-typing+` +`+Resource.{Algebra.Ordered, Instances.MinMax, Bridge, EchoBridge}+` @ +2e35229. +* *Echo.idr* — `+EchoR+` + `+echoToResidue+` (mirrors `+echo-types+` +`+EchoResidue.agda+` @ 2bbdb49); header re-characterised: an echo-type +is a *tropically-graded modality of structured information loss* (grade += min-plus = `+Tropical.TropCost+`), exact-on-a-fiber recoverability — +the monad/comonad/adjunction VARIANCE is deferred to upstream `+--safe+` +Agda (RETRACTION R-2026-05-18 + experimental R0–R4), NOT asserted here. +* *Epistemic.idr* — ADDITIVE `+syncGrade+` (∞ = never-synced) reusing +the sibling `+Tropical.TropCost+`; extant A10–A14 Nat-indexed proofs +untouched. Header IS-NOT note: read-consistency is a _different_ problem +from canonical `+epistemic-types+`’ standpoint-indexed modality. + +Three extend-upstream drafts prepped local/unpushed (Lean closure +functor; Agda re-sync liveness `+AccessibleModality+` instance; Agda +`+DispHom+` packaging), each verified by its own prover. See +LEVEL-STATUS.md "`Estate-axis accommodation`". +____ + +=== RECONCILIATION 2026-06-02 (audit-boundary half of post-A10 items 7 + 8 promoted to ADR-0005 — read this FIRST) + +____ +*The "`Full proof bodies for `+VerifierSpecAgreement+` / +`+SourceVerifierAgreement+``" long-tail item (issue #103) is now closed +via path (3) — explicit ADR.* + +The 2026-05-27 banner below recorded the bodies as TOTAL in PR #79 +(commit `+06ec00e+`). What remained per issue #103 was a load-bearing +home for the audit-boundary story: every `+VADifferential+` / +`+SADifferential+` step ultimately routes through a `+MkTrustedFixture+` +construction, and the trust-injection moment needed a single, named, +cross-referenced specification rather than an inline docstring. + +*ADR-0005* (`+docs/decisions/0005-trustedfixture-audit-boundary.adoc+`, +2026-06-02) pins three inspection invariants every +`+MkTrustedFixture m+` construction site is audited against: + +* *I1 — Provenance.* The pair +`+(trustedFixtureName, trustedFixtureId)+` must correspond to an +existing row in the Rust differential harness +(`+crates/typed-wasm-verify/tests/cross_compat.rs+`). +* *I2 — Witness fidelity.* The `+FunctionsAccepted m.functions+` payload +must be the structural witness the harness’s ACCEPT verdict establishes; +rejected fixtures yield no `+MkTrustedFixture+`. +* *I3 — Module shape.* The indexing `+ModuleSummary+` must mirror the +harness’s `+ModuleSummary+` reconstruction for the same fixture bytes +(function order + decoded ownership intents). + +*What this is not.* ADR-0005 is not a constructive proof of +Rust-verifier soundness; the Rust verifier remains the trusted base for +the differential path. The two supersession paths from issue #103 — +WasmCert-Isabelle tie-back (path 1) or constructive Rust-verifier +soundness (path 2) — remain valid future upgrades and would each ship as +a fresh ADR superseding 0005. + +*Source-code cross-reference.* A docstring near `+MkTrustedFixture+` in +`+src/abi/TypedWasm/ABI/VerifierSpec.idr+` points at ADR-0005, so a +reader landing on the record’s definition can find the invariants +without rediscovering them. Single grep point for trust injections: +`+git grep MkTrustedFixture+`. + +*No `+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+` / +`+assert_smaller+` introduced; `+%default total+` preserved across the +arc. The closure work was an ADR + a docstring cross-reference + a +proof-debt banner — no new proof obligations, no new code behind the +lemma bodies that PR #79 already shipped.* +____ + +=== RECONCILIATION 2026-05-30 (carrier-ABI proposals 0001 + 0002 accepted + ADR’d — read this FIRST) + +____ +*The "`verifier L1-L6 + L13-L16 coverage on emitted wasm`" long-tail +item shrinks substantially.* The 2026-05-27 banner below listed this as +"`in progress on PRs #76 / #77 in a parallel session`"; the arc has now +closed end-to-end: + +* *Proposal 0001* +(`+docs/proposals/0001-multi-producer-carrier-section.adoc+`) — +`+typedwasm.regions+` + `+typedwasm.capabilities+` carrier sections. +`+[accepted]+` 2026-05-30 (PR #115) → promoted to +`+docs/decisions/0002-multi-producer-carrier-sections.adoc+` (ADR-0002) +in PR #116. +* *Proposal 0002* (`+docs/proposals/0002-access-site-carrier.adoc+`) — +`+typedwasm.access-sites+` per-instruction carrier for L2 enforcement. +`+[accepted]+` 2026-05-30 (PR #115) → promoted to +`+docs/decisions/0003-access-site-carrier.adoc+` (ADR-0003) in PR #116. +* Verifier passes shipped: `+verify_regions_from_module+` (PR #107), +`+verify_capabilities_from_module+` and +`+verify_access_sites_from_module+` (PR #109) — all behind +`+unstable-l2+` / `+unstable-l15+` Cargo features in +`+crates/typed-wasm-verify/+`. + +*What this closes.* L2-the-enforcement, L3, L4, L5, L6 (regions half), +and L15-A/B on emitted wasm now have carrier-backed verifier passes. +`+LEVEL-STATUS.md+` rows updated from "`proposal-stage`" to "`YES +(carrier-backed)`" in PR #115. + +*What is still open in the long-tail.* + +* *L13 cross-module schema agreement (positive form)* — proposal 0003 +(`+docs/proposals/0003-region-imports-carrier.adoc+`) is `+[draft]+`. +Wire format defined; gated on producer-side multi-module emission +(AffineScript Roadmap C3 / Ephapax not yet on roadmap). +* *L15-C (per-call-site capability monotonicity)* — proposal 0004 +(`+docs/proposals/0004-capability-grants-carrier.adoc+`) is `+[draft]+`. +Wire format defined; gated on producer-side L15-A emission. +* *WasmCert-Isabelle tie-back* — unchanged (multi-week external +dependency). +* *Emitted-wasm byte-equality (P3.1(a))* — unchanged (blocked on +`+.twasm → .wasm+` emitter not yet existing). +* *Idris2 parser round-trip* — unchanged (blocked on AffineScript parser +port to Idris2). +* *Producer-side codegen of access-sites* — AffineScript at +affinescript#462; Ephapax counterpart owner-action pending (auto-mode +classifier blocked the cross-repo create on 2026-05-30). + +*No `+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+` / +`+assert_smaller+` introduced; `+%default total+` preserved across the +arc. The acceptance work was design-doc + ADR + verifier-pass codecs, +not new proof obligations.* +____ + +=== RECONCILIATION 2026-05-27 (post-A10 items 7 + 8 bodies closed — read this FIRST) + +____ +*The two agreement records introduced by PR #72 / A13 are now +inhabited.* `+VerifierSpecAgreement+` and `+SourceVerifierAgreement+` +have concrete inhabitants `+verifierSpecAgreement+` / +`+sourceVerifierAgreement+` with totally-proven bodies in every +direction. This was the "`multi-week residual`" PR #74 explicitly +flagged. Closed in PR #79. + +*Design choice that unblocked the bodies.* The differential constructor +carries the structural witness it certifies, packaged inline via an +embedded `+TrustedFixture m+`: + +.... +data VerifierAccepts : ModuleSummary -> Type where + VAStructural : FunctionsAccepted m.functions + -> VerifierAccepts m + VADifferential : (fixture : TrustedFixture m) + -> VerifierAccepts m + +record TrustedFixture (m : ModuleSummary) where + constructor MkTrustedFixture + trustedFixtureName : String + trustedFixtureId : Nat + trustedWitness : FunctionsAccepted m.functions +.... + +Trust-injection moves to `+MkTrustedFixture+` construction (single grep +point for audit). All four agreement lemmas become total by case +analysis: both `+VAStructural+` and `+VADifferential+` surface a +`+FunctionsAccepted m.functions+` payload that wraps directly into +`+SpecAccepts+`; the spec-to-verifier direction lifts via +`+VAStructural+`; source ↔ verifier mirror the same pattern. + +*Module: `+src/abi/TypedWasm/ABI/VerifierSpec.idr+` (~620 LOC).* Zero +`+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+` / +`+assert_smaller+`; `+%default total+`. Build green 22/22 modules under +Idris2 0.8.0. +33 Layer 1 regression assertions. + +*End-to-end demo.* `+fixtureCleanLinearConsumerModule+` mirrors +cross_compat row 1. `+fixtureCleanLinearConsumerDifferentialAccepts+` +exercises the smart constructor; +`+fixtureCleanLinearConsumerSpecAccepts+` runs the witness through +`+verifierSpecAgreement.verifierIsSound+` for the end-to-end closure. + +*Discrimination.* `+notSpecAcceptsBadDoubleConsume+`, +`+notVerifierAcceptsBadDoubleConsume+` (both ctors), +`+notSourceAcceptsBadDoubleConsume+` (both ctors), +`+notSpecAcceptsBadDoubleProduce+` — show L10 has teeth and the +differential escape hatch cannot smuggle a bad module past the verifier +(since `+MkTrustedFixture+` requires a structural witness, which is +impossible for the bad module). + +*Comparison with PR #74 (closed as superseded).* #74 kept +`+VADifferential+` opaque (string + nat only) and offered +`+Maybe+`-returning bridges plus a closed-world `+RegisteredFixture+` +GADT. Soundness/completeness for the unparameterised agreement records +remained unprovable in that design — that’s the "`multi-week residual`" +#74’s description named. #79 refactors the data type instead. The audit +story is preserved; the agreement records cease to be obligations. + +*Open after this closure.* Items remaining in the long-tail (in rough +decreasing priority): verifier L1-L6 + L13-L16 coverage on emitted wasm +(#34, #35; in progress on PRs #76 / #77 in a parallel session), +WasmCert-Isabelle tie-back, emitted-wasm byte-equality (P3.1(a), blocked +on emitter), parser round-trip in Idris2 (blocked on parser port). +____ + +=== RECONCILIATION 2026-05-27 (standards#130 long-tail closed — read this FIRST) + +____ +*The "`LevelAttestation reindexed by witness`" residual is closed.* The +2026-05-18 reconciliation banner below flagged that the A9 +`+attestLN_Sound+` family proves only "`the certificate provably claims +level N`", not the stronger "`attestation entails the level’s semantic +property`" claim — and that the stronger version required +`+LevelAttestation+` reindexed by the witness. That redesign now lands +in `+Proofs.idr+` as the *purely additive* `+LevelAttestationW+` +section. + +[arabic] +. *`+data LevelAttestationW : (n : Nat) -> Type+`* — witness-indexed +GADT, fifteen constructors, one per level. Each constructor packages the +actual level-specific witness (`+Schema+`, `+FieldIn+`, +`+WasmTypeCompat+`, `+Pointer.Ptr ... NonNull+`, `+InBounds+`, +`+AccessResult+`, `+ExclusiveWitness+`, `+EffectSubsumes+`, +`+Lifetime.Outlives+`, `+CompletedProtocol+`, `+AllPairsCosts+`, +`+Level12Proof+`, `+IsolatedModule+`, `+WellFormedProtocol+`, +`+FunctionCaps+`). +. *Fifteen `+attestLNW_*+` smart constructors* mirror the legacy +`+attestLN_*+` family but return the witness-carrying variant instead of +the unindexed `+LevelAttestation+`. +. *Fifteen `+attestLNW_Entails+` extractors* — the +"`attestation entails the level’s semantic property`" lemmas. Each is a +one-line pattern match that returns the witness (paired with its +existential type-level indices via dependent pair where applicable). A +consumer holding `+LevelAttestationW 7+` can now discharge the L7 +semantic property (alias-freeness via `+ExclusiveWitness s+`) — not just +the predicate "`claims L7`". +. *Legacy bridge +`+toLegacy : {n : Nat} -> LevelAttestationW n -> LevelAttestation+`* +projects to the unindexed shape so existing callers of +`+List LevelAttestation+` (e.g. `+ProofCertificate+`) keep working +unchanged. +. *Fifteen round-trip `+Refl+` equalities* +`+toLegacy (attestLNW_X w) = attestLN_X w+` pin the two +representations together at the type-equality level — any future drift +trips the typechecker. +. *`+attestLW_AchievedIn : (att : LevelAttestationW n) -> LevelAchievedIn n [toLegacy att]+`* +— uniform achievement lemma subsuming the fifteen A9 `+attestLN_Sound+` +cases. One lemma covers every level under the witness-carrying redesign. + +*Purely additive.* Existing `+LevelAttestation+`, `+MkAttestation+`, +`+attestLN_*+`, `+attestLN_Sound+`, `+LevelAchievedIn+`, +`+composeCertificates+`, `+ProofCertificate+` — all unchanged, all prior +proofs unaffected. Idris2 0.8.0 `+--build+` green, 21/21 modules, rc=0, +zero new `+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+` / +`+assert_smaller+`, `+%default total+` preserved. + +*Open after this closure.* Standards#130 sub-issue is fully discharged +(its A9 weak form + this stronger reindexed form). Other long-tail items +unchanged: WasmCert-Isabelle tie-back, emitted-wasm byte-equality +(P3.1(a), blocked on emitter), parser round-trip in Idris2 (blocked on +parser port), verifier L1-L6 + L13-L16 coverage (#34/#35, in progress on +PRs #76/#77). +____ + +=== RECONCILIATION 2026-05-26 (A13 follow-up) + +____ +*A13 follows A12 in the same calendar day.* Per coordinator +pre-clearance for items 5 + 7 + 8 (and the small A12 leave-behind), this +round closes *the remaining post-A10 audit items in their +statement-level form*: + +[arabic] +. *Item 5a (L13 × L10) closed.* `+ModuleIsolation.idr+` gains +`+LinearAcrossBoundary from to regName bs token+`, pairing an L13 +`+AccessWitness+` with an L10 `+LinHandle+`. The no-bypass theorem +`+linearTransferRequiresBoundary+` proves that any non-local +linear-handle transfer requires a concrete boundary in `+bs+` — a linear +handle cannot leave an isolated module without an L13 boundary +declaration. `+linearTransferLocal+` is the local-case constructor. +Proof shape reuses `+crossAccessImpliesBoundary+` from L13 directly; the +cross-level claim is a clean lift. +. *Item 5b (L14 × L13) closed.* `+SessionProtocol.idr+` now imports +`+ModuleIsolation+` and gains `+SessionAcrossBoundary+` with three +theorems: `+sessionAcrossPreservesState+` (the state index survives the +transfer), `+sessionTransferRequiresBoundary+` (the same no-bypass shape +as L10), and `+sessionTransferLocal+` (local-case). Together they prove +a session handle cannot silently change state or escape its module +without an L13 witness. +. *A12 leave-behind closed.* `+Region.idr+` gains `+RegionsOverlap+` (an +address lying inside both region footprints) and +`+disjointImpliesNoOverlap+` proving +`+RegionDisjoint -> Not RegionsOverlap+`. This is the L7/L10 +cross-level link the A12 section header promised — disjointness now has +byte-level teeth. `+regionsOverlapSym+` is the symmetry companion. +. *Items 7 + 8 stated as obligations.* New module `+VerifierSpec.idr+` +introduces `+SpecAccepts m+` (the Idris2 L7+L10 structural acceptance +predicate on `+ModuleSummary+`), `+VerifierAccepts m+` (opaque; +witnessed by the Rust differential harness via +`+differentialAccepted+`), and `+SourceAccepts m+` (opaque; witnessed by +the source-side harness). Two record obligations — +`+VerifierSpecAgreement+` (item 7) and `+SourceVerifierAgreement+` (item +8) — bundle the soundness and completeness directions so partial proofs +can land one face at a time. Composition lemmas `+sourceImpliesSpec+` +and `+specImpliesSource+` give the test harness end-to-end targets. ++ +*What this does NOT do.* Items 7 and 8 are stated, not proven. The full +equivalence proofs require either a full simulation between two +implementations (multi-week) or extending the verifier’s coverage to +every level the source checker promises. A13 pins the obligations as +typed Idris2 predicates so the long-tail work has a fixed target. + +*15 new named theorems / data types* (`+LinearAcrossBoundary+`, +`+acrossWitness+`, `+acrossHandle+`, `+linearTransferRequiresBoundary+`, +`+linearTransferLocal+`, `+SessionAcrossBoundary+`, +`+sessionAcrossPreservesState+`, `+sessionTransferRequiresBoundary+`, +`+sessionTransferLocal+`, `+RegionsOverlap+`, +`+disjointImpliesNoOverlap+`, `+regionsOverlapSym+`, `+SpecAccepts+`, +`+VerifierAccepts+`, `+SourceAccepts+` plus `+VerifierSpecAgreement+` / +`+SourceVerifierAgreement+` / `+sourceImpliesSpec+` / +`+specImpliesSource+`). Regression *68/68* under Idris2 0.8.0 (both +layers). + +*Open after A13.* No items remain from the original post-A10 8-item +audit. Long-tail work that exceeds a one-session scope: the actual proof +bodies for `+VerifierSpecAgreement+` / `+SourceVerifierAgreement+`; the +`+LevelAttestation+` reindexed-by- witness redesign (standards#130 / +epic standards#124); WasmCert- Isabelle tie-back; emitted-wasm +byte-equality for erasure (P3.1(a), blocked on emitter); parser +round-trip in Idris2 (ECHIDNA-only at present). +____ + +=== RECONCILIATION 2026-05-26 (A12 follow-up) + +____ +*A12 follows A11 in the same calendar day.* Per coordinator-routed A12 +go-ahead, this round closes *3 more* of the 8 untracked gaps from +`+project_typed_wasm_proof_debt_post_a10.md+`: + +[arabic] +. *Item 4 closed IN FULL.* The A11 partial (`+composeAssocLists+` was +list-side only) is now superseded by `+composeAssoc+` proving three-way +associativity of `+composeCertificates+` across all three fields (list +parts, multi-module parts, AND the `+highestProven+` Nat). Made possible +by switching `+composeCertificates+` from the Ord-derived +`+Prelude.min+` to the structural `+Data.Nat.minimum+` (per coordinator +hint), which makes `+minimumAssociative+` apply directly. +`+composeHighProvenComm+` adds Nat-side commutativity via +`+minimumCommutative+`. The original `+composeAssocLists+` is kept as a +back-compat corollary. +. *Item 6 closed.* `+RegionDisjoint r1 r2+` in `+Region.idr+` — a +two-constructor data type witnessing that two regions’ byte footprints +`+[baseAddr, baseAddr + totalSize)+` don’t overlap in either ordering. +`+regionDisjointSym+` proves symmetry. The cross-level theorem linking +disjointness to L7 aliasing-safety and L10 linearity is left for a +future pass — disjointness as a predicate is the missing primitive the +audit flagged. +. *Item 3 closed.* `+jointBudgetCompose+` in +`+ResourceCapabilities.idr+` proves L8 ↔ L15 joint composition: given +individual `+EffectSubsumes+` witnesses + individual `+FunctionCaps+` +witnesses for two functions sharing an owner module, the compound +function satisfies both the combined L8 envelope (via +`+subsumeCompose+`) AND the combined L15 module envelope (via the new +`+containedConcat+` + the existing `+l15bSoundness+`). + +All five new theorems (`+composeAssoc+`, `+composeHighProvenComm+`, +`+RegionDisjoint+`, `+regionDisjointSym+`, `+jointBudgetCompose+`, +`+containedConcat+`) are guarded by `+tests/proof/regression.mjs+`. +Regression now *50/50*. + +Items remaining from the original post-A10 audit (all explicitly A12 → +A13 inheritance per coordinator clearance): item 5 (L13×L10, L14×L13 +cross-level), item 7 (Rust verifier ↔ Idris2 spec equivalence), item 8 +(source-checker ↔ verifier coverage agreement). +____ + +=== RECONCILIATION 2026-05-26 (A11 follow-up) + +____ +*A11 follows A10 in the same calendar day.* Where A10 closed the _named_ +deferred items, A11 attacks three of the *untracked* gaps uncovered by +the post-A10 audit (`+project_typed_wasm_proof_debt_post_a10.md+`): + +[arabic] +. *`+Sync.WriteSync+` no longer admits fake writers.* The constructor +now requires a `+FieldVersion+` witness with three equalities +(`+fv.field = field+`, `+fv.version = newVersion+`, +`+fv.lastWriter = mod+`) and the corollary `+writeSyncIdentifiesWriter+` +extracts that witness. An adversarial construction +`+WriteSync (MkFieldVersion otherField otherVer differentModule) Refl Refl Refl+` +is now ill-typed unless the three coincide with the indexed +field/version/writer — the very "`provenance gap`" Audit Item 1 flagged. +. *`+Knowledge.Observed+` is grounded in a `+Sync+` event.* The +constructor now takes `+(sync : Sync mod field oldVer ver)+` so +`+Observed mod field ver+` cannot be inhabited without a causally-prior +write. `+observedHasProvenance+` reads the witness back out. Audit Item +2 ("`Knowledge.Observed admits unfounded versions`") is closed. +. *`+composeCertificates+` gets its first algebraic laws.* +`+achievedAppendSplit+` proves +`+LevelAchievedIn n (xs ++ ys) -> Either (LevelAchievedIn n xs) (LevelAchievedIn n ys)+`; +`+composeAssocLists+` proves the achieved-set under three-way +composition is associative; `+composeAchievedSym+` is the symmetric +counterpart of `+composeAchievedL+`/`+R+`. Audit Item 4 +("`composeCertificates laws unproven`") is *partially* closed — +list-level associativity is proven, but the `+Nat+`-min commutativity on +`+highestProven+` is left for A12 because Idris2 0.8’s +`+Prelude.min Nat+` is a non-structural `+if x < y then x else y+` +and does not reduce to `+Refl+` on symbolic inputs. See +`+composeAssocLists+` docstring in `+Proofs.idr+` for the discharge +plan. + +All five new theorems (`+writeSyncIdentifiesWriter+`, +`+observedHasProvenance+`, `+achievedAppendSplit+`, +`+composeAssocLists+`, `+composeAchievedSym+`) are guarded by +`+tests/proof/regression.mjs+` Layer 1 grep + Layer 2 `+--build+`. Items +3, 5, 6, 7, 8 from the post-A10 audit remain open and inherit to a +future A12. +____ + +=== RECONCILIATION 2026-05-26 (A10 closure — read this first) + +____ +*A10 closes the last two named "`deferred`" items* that survived the +2026-05-18 reconciliation below. Both are now mechanically proven and +guarded by `+tests/proof/regression.mjs+` (Layer 1 grep + Layer 2 build, +Layer 2 invocation fixed to `+--build+` from a no-op `+--check+`). + +[arabic] +. *L12 freshness propagation under concurrent writes* (PROOF-NEEDS §P1.2 +and LEVEL-STATUS row 12) — closed by 8 new theorems in `+Epistemic.idr+` +headlined by +`+freshnessPropagatesUnderWrites : Fresh mod field v v -> LT v cur -> Sync mod field v cur -> Fresh mod field cur cur+` +plus `+concurrentWriteStales+`, `+resyncRecoversFresh+`, +`+freshNotStale+`, `+freshImpliesEqual+`, `+staleImpliesLT+`, +`+syncChainEndsFresh+`, and the named +`+epistemicFreshness : (p : Level12Proof) -> Fresh p.reader p.field p.knownVersion p.currentVersion+` +projector that satisfies the P1.2 obligation directly. +. *`+compatCommute+` mutual-subschema case* (PROOF-NEEDS §P0.5 paragraph +246) — closed in `+MultiModule.idr+` by +`+compatCommute : ModuleCompat from to imp exp -> SchemaSub exp imp -> ModuleCompat to from exp imp+` +plus the `+noSpoofingBidir+` corollary. A second worked example +(`+serviceA+`/`+serviceB+` with permuted schemas, both `+SchemaSub+` +directions inhabited) demonstrates the theorem on a non-trivial input. + +The only proof-side item still explicitly deferred is the *stronger +`+LevelAttestation+` reindexed by witness* noted at the end of the +2026-05-18 reconciliation; everything LEVEL-STATUS or this file +previously called "`deferred`" or "`future work`" at the proof level is +now resolved. L15-C call-graph *surface-checker* enforcement remains +future work (the proof-side `+callCompose+` was already in place; +LEVEL-STATUS row 15 carries the marker). +____ + +=== RECONCILIATION 2026-05-18 (verified ground truth) + +____ +Routed from estate proof-debt epic *hyperpolymath/standards#124*, +sub-issue *#130*. The 2026-04-13 inventory below is *superseded* and +retained for history (estate convention: dated snapshots get historical +banners, not rewrites). + +*standards#130’s stated debt is refuted by ground truth.* It claimed "`5 +`+believe_me+` + 5 `+assert_total+` + 5 `+partial+``" and that an agent +"`called it fully real; it is not`". A comprehensive re-grep +(`+believe_me+`, `+really_believe_me+`, `+assert_total+`, +`+assert_smaller+`, `+postulate+`, `+idris_crash+`, `+prim__crash+`, +`+%default partial+`, `+Admitted+`, `+sorry+`, `+unsafePerformIO+`, +`+assert_linear+`) over all 21 `+.idr+` files finds *zero* in code — +only inside "`NO believe_me`" banner comments. This is the survey-agent +*over-report* failure mode the epic explicitly warns about (the inverse +of under-report). + +*Verified build (Idris2 0.8.0, `+typed-wasm.ipkg+`, 2026-05-18):* +`+rc=0+`, *zero errors*, *21/21 modules → TTC*, `+%default total+` in +all 21. Only 11 warnings, all one cosmetic kind (lowercase implicit-bind +shadowing of `+mod+`/`+field+`/`+payload+`) — no soundness impact. The +2026-04-13 "`2 files draft-only, standalone check fails (Tropical, +Epistemic)`" item is *resolved*: both are now in the ipkg and build +clean (`+believe_me+` eliminated from Epistemic by commit `+e4253f0+`). + +*The genuine residual debt is the one §P1 below already names* — not +trust escapes but `+Proofs.idr+` attestations that required a witness +then discarded it (`+attestLN_* _ = MkAttestation N Proven+`). This pass +discharges that for *all 15 levels* additively: the new +`+attestLN_Sound+` family (Proofs.idr §A9) is a per-level theorem that +cannot be invoked without the exact witness type and proves +`+LevelAchievedIn N [attestLN witness]+` — the missing "`witness ⟹ +certificate-claims-level`" bridge. Additive (no existing definition +touched → no prior proof can regress), verified by the same clean +`+rc=0+` build. Stronger "`attestation entails the level’s semantic +property`" (needs `+LevelAttestation+` reindexed by witness) remains +tracked future work under standards#130. +____ + +=== Inventory snapshot (2026-04-13 — SUPERSEDED, see reconciliation above) + +* 11 `+.idr+` files, 2,589 LOC total, `+%default total+` everywhere, +zero `+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+`. +* 9 files are in `+typed-wasm.ipkg+` (Region, TypedAccess, Levels, +Pointer, Effects, Lifetime, Linear, MultiModule, Proofs) + Layout +aggregate. +* 2 files are *draft only* and standalone `+idris2 --check+` fails: +`+Tropical.idr+`, `+Epistemic.idr+`. They are NOT in the ipkg. Fix them +before claiming L11/L12. +* Structure: mostly `+data+` declarations + constructor helpers. No +`+record+` except in Region (RegionSchema) and Tropical (CostAnnotated). +Zero theorem statements of the form `+lemma : P -> Q -> R+` that +manipulate witnesses to prove properties. +* `+LEVEL-STATUS.md+` line 28 correctly labels L7-L10 as *"`Proven +[sfap], erased`"* where "`[sfap]`" = "`so far as possible`". That is the +honest status. L11-L12 are "`draft only; not in package; standalone +check currently fails`". + +=== The proof-writing priority order + +Ordered by _dependability > security > interop > usability > performance +> versatility > functional extension_ per estate standing order. Every +item below names a file, a theorem to state, and a rough difficulty. + +==== P0 — Dependability (existence proofs for the structural claims) + +*P0.1. Tropical semiring laws — Tropical.idr.* The eight axioms of a +commutative semiring with zero. 007 has done this work already in +`+proofs/idris2/TropicalSemiring.idr+` (12 theorems, CLEAN, zero +`+believe_me+`). Port it. Specifically prove: + +.... +tropAddAssoc : (a, b, c : TropCost) -> tropAdd (tropAdd a b) c = tropAdd a (tropAdd b c) +tropAddComm : (a, b : TropCost) -> tropAdd a b = tropAdd b a +tropAddIdent : (a : TropCost) -> tropAdd Infinity a = a +tropMulAssoc : (a, b, c : TropCost) -> tropMul (tropMul a b) c = tropMul a (tropMul b c) +tropMulComm : (a, b : TropCost) -> tropMul a b = tropMul b a +tropMulIdent : (a : TropCost) -> tropMul (Finite 0) a = a +tropMulAnnihil : (a : TropCost) -> tropMul Infinity a = Infinity +tropDistrib : (a, b, c : TropCost) -> tropMul a (tropAdd b c) = tropAdd (tropMul a b) (tropMul a c) +.... + +Hardest one is distributivity — in min-plus you need +`+a + min(b,c) = min(a+b, a+c)+`, which requires case analysis on Nat. +Use the 007 versions as templates. + +*Also fix the standalone check failure.* File does not currently +type-check on its own. Investigate why (likely a missing import or a +dependent type that isn’t reduced) before writing new theorems. Getting +it into `+typed-wasm.ipkg+` is the entry ticket for L11. + +*Difficulty:* medium. Bulk of the work is Nat-arithmetic case splits. +The 007 file is 333 LOC and clean, so it’s a rehearsed path. + +*P0.2. Linear.idr — explicit consumption theorem.* The file says +"`double-free is impossible by construction`" in a comment, then +declares a nullary data type `+NoDoubleFree+` as a "`witness`". This is +documentation, not a proof. Replace with: + +.... +||| A linear handle, once consumed, cannot be consumed again. +||| This is the central safety property of Level 10. +linearConsumedOnce : (1 h : LinHandle token) -> + (after : FreeResult) -> + (freeRegion h live = after) -> + -- Cannot produce a second FreeResult from h. + Void +.... + +The exact shape depends on how you model "`cannot produce`" — QTT’s +erased `+(0 _ : X)+` won’t give you the negation. The cleanest approach +is a *usage-counter encoding*: + +.... +data Usage : Type where + Fresh : Usage + Consumed : Usage + +data LinHandleU : (u : Usage) -> (token : Nat) -> Type where + MkFresh : (off : Nat) -> (sid : Nat) -> LinHandleU Fresh token + +consume : LinHandleU Fresh token -> (LinHandleU Consumed token, Nat) +-- then prove: no function Type -> LinHandleU Fresh token exists +-- that produces a fresh handle from a consumed one. +.... + +Then prove +`+noReuse : LinHandleU Consumed t -> LinHandleU Fresh t -> Void+`. That +is the actual theorem behind the protocol. + +*Difficulty:* medium-hard. The nullary `+NoDoubleFree+` needs real +witness manipulation. Budget a session. + +*P0.3. Lifetime.idr — Outlives is a preorder.* File declares +`+Outlives : Lifetime -> Lifetime -> Type+` as an abstract relation. The +safety of `+LiveRef+` depends on `+Outlives+` being at least reflexive +and transitive. Prove: + +.... +outlivesRefl : (l : Lifetime) -> l `Outlives` l +outlivesTrans : l1 `Outlives` l2 -> l2 `Outlives` l3 -> l1 `Outlives` l3 +.... + +Then the *load-safety theorem*, which is the actual L9 guarantee: + +.... +loadSafe : (ref : LiveRef lref a) -> + (scope : RegionLife token) -> + (p : scope `Outlives` lref) -> + -- dereferencing in this scope produces a well-typed a + a +.... + +Currently `+LiveRef+` extracts its offset and hopes for the best. +`+loadSafe+` is the proof that the hope is justified. + +*Difficulty:* medium. Depends on how `+Outlives+` is defined — if it’s +just an opaque type, you have to add constructors first. + +*P0.4. Effects.idr — EffectSubsumes preorder + monotonicity.* +`+Proofs.idr:171+` shows +`+attestL8_EffectSafe : EffectSubsumes declared actual -> LevelAttestation+` +which takes a witness and discards it. For this attestation to mean +anything, `+EffectSubsumes+` must be a real preorder: + +.... +subsumeRefl : (es : List Effect) -> EffectSubsumes es es +subsumeTrans : EffectSubsumes xs ys -> EffectSubsumes ys zs -> EffectSubsumes xs zs +.... + +Plus the composition theorem — when you sequence two operations, the +combined effect set is the union and the subsumption is preserved: + +.... +subsumeCompose : EffectSubsumes d1 a1 -> EffectSubsumes d2 a2 -> + EffectSubsumes (d1 ++ d2) (a1 ++ a2) +.... + +Otherwise L8 is a fiction — a correct-looking attestation with no +content. `+SubNil+` is referenced in `+Proofs.idr:239+` but I did not +find its definition; verify it exists and strengthen it if it does not. + +*Difficulty:* easy-medium if `+EffectSubsumes+` has concrete +constructors, hard if it has to be redesigned. + +*P0.5. MultiModule.idr — CompatCertificate reflexivity + transitivity + +composition. ✅ DONE 2026-04-18 (A6).* + +The strengthened propositional layer was added to MultiModule.idr +alongside the existing data declarations (none of which were rewritten). +The new relation `+ModuleCompat+` is indexed by both modules _and_ +schemas, which avoids the "`compatCommute implicit bidirectionality`" +question: the schema order pins the direction of the subschema witness. + +Proved: + +.... +compatRefl : (m : ModuleId) -> (s : Schema) -> ModuleCompat m m s s +compatTrans : ModuleCompat m1 m2 s1 s2 -> ModuleCompat m2 m3 s2 s3 + -> ModuleCompat m1 m3 s1 s3 +.... + +plus the flagship no-spoofing theorem: + +.... +noSpoofing : ModuleCompat from to imp exp + -> (f : Field) -> FieldMatches f imp + -> FieldMatches f exp +.... + +and a type-preservation corollary `+noTypeSpoofing+` at a known +`+(name, ty)+` pair. The work-horse lemma is +`+fieldMatchesLift : FieldMatches f y -> SchemaSub y z -> FieldMatches f z+`, +which walks the SchemaSub witness field-by-field — so the proof is not +vacuous. + +Sanity-checked with a worked Rust-exports / AffineScript-imports example +(4-field export `+[id: U64, age: U8, score: F32, banned: WBool]+`, +2-field subset import `+[id: U64, age: U8]+`) that constructs a live +`+ModuleCompat+` certificate and applies `+noSpoofing+` to it. Zero +`+believe_me+` / `+assert_total+` / `+postulate+` / `+sorry+`; +`+%default total+` preserved. + +`+compatCommute+` is NOT proven because it only holds when the two +subschema relations are mutually witnessed — at that point the two +schemas are equal up to reordering and the commutativity is a one-line +corollary of `+noSpoofing+` in both directions. Left as future work only +if a downstream consumer actually needs it. + +*Original task description preserved for history:* File has 12 `+data+` +declarations describing cross-module memory compatibility. Prove: + +.... +compatRefl : (m : ModuleId) -> Compat m m +compatTrans : Compat m1 m2 -> Compat m2 m3 -> Compat m1 m3 +compatCommute : Compat m1 m2 -> Compat m2 m1 -- if bidirectional +.... + +Plus the *no-spoofing theorem*: if `+Compat m1 m2+` holds, then every +region accessible from `+m1+` is either exported by `+m1+` or imported +from a module compatible with `+m1+`. This is the actual multi-module +memory safety invariant — the paper’s killer feature. If you can state +and prove this one, typed-wasm has a real story to tell. + +*Difficulty:* hard. This is the flagship theorem. Budget multiple +sessions. Consider writing a small example multi-module program first to +sanity-check the statement before proving it. + +==== P1 — Security (the parts where ceremony ≠ evidence) + +*P1.1. Replace every ceremonial attestation in `+Proofs.idr+` with +evidence-consuming versions. ✅ DONE 2026-04-18 (A7).* + +Every nullary attestation in `+Proofs.idr+` has been promoted to require +a witness from its level’s proof module: + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|Attestation |Witness type |Source module +|`+attestL1_InstructionValid+` |`+Schema+` |Region.idr + +|`+attestL2_RegionBound+` |`+FieldIn name schema+` |Region.idr + +|`+attestL3_TypeCompat+` |`+WasmTypeCompat a b+` |MultiModule.idr + +|`+attestL4_NullSafe+` |`+Pointer.Ptr k s l NonNull+` |Pointer.idr + +|`+attestL5_BoundsProof+` |`+InBounds idx count+` |Region.idr + +|`+attestL6_ResultType+` |`+AccessResult ty+` |TypedAccess.idr + +|`+attestL7_AliasFree+` |`+ExclusiveWitness s+` |Pointer.idr + +|`+attestL8_EffectSafe+` |`+EffectSubsumes declared actual+` +|Effects.idr (pre-existing) + +|`+attestL9_LifetimeSafe+` |`+Lifetime.Outlives rl sl+` |Lifetime.idr + +|`+attestL10_Linear+` |`+CompletedProtocol tok+` |Linear.idr +|=== + +`+simpleReadCert+`, `+fullCert12+`, and `+fullCert15+` now thread each +of the required witnesses through their signatures. The top-level +certificate cannot be constructed without a proof term for every level +it claims. + +Qualification note: `+Lifetime+` and `+Outlives+` are resolved as +`+Lifetime.Lifetime+` / `+Lifetime.Outlives+` (from Lifetime.idr), while +`+Pointer.Ptr+`’s lifetime parameter takes `+Levels.Lifetime+` (which is +what Pointer.idr itself imports from Levels.idr). A small comment in +Proofs.idr explains the qualification; both `+Lifetime+` types remain in +the codebase for now. + +*Original task description preserved for history:* Current state: + +.... +attestL10_Linear : LevelAttestation +attestL10_Linear = MkAttestation 10 Proven +.... + +Takes no arguments — anyone can call it. Should be: + +.... +attestL10_Linear : (p : LinearProof t) -> LevelAttestation +attestL10_Linear _ = MkAttestation 10 Proven +.... + +where `+LinearProof t+` is a real proof-carrying type (built on P0.2). +Same treatment for `+attestL9_LifetimeSafe+` (should require a +`+LoadSafe+` witness), `+attestL7_AliasFree+` (should require a +`+Unique+` witness from Pointer.idr), `+attestL3_TypeCompat+`, etc. The +whole point of a certificate is that you cannot construct it without the +underlying proofs. + +*Difficulty:* mechanical once P0.1–P0.4 land. Do it immediately after +each P0 completes. + +*P1.2. Epistemic.idr — fix standalone check, then prove Level12Proof +implies freshness.* Draft-only. First make it type-check in isolation +(figure out the missing imports / unresolved variables), then state: + +.... +Level12Proof : (writer : Commit) -> (reader : View) -> Type +-- constructor requires view.timestamp >= commit.timestamp + +epistemicFreshness : Level12Proof w r -> (LTE (commitTimestamp w) (viewTimestamp r)) +.... + +Currently the existence of `+Level12Proof+` is waved through by +`+attestL12_EpistemicFresh _ = MkAttestation 12 Proven+`. As with P0.2 +and P1.1, the actual theorem has to be written down. + +*Difficulty:* medium once the file type-checks. Getting it to type-check +is the hard bit — may require understanding a design decision that the +draft obscures. + +*P1.3. Region.idr — schema injectivity. ✅ DONE 2026-04-18 (A8) — +reframed for current Schema = List Field design.* + +The original P1.3 asked for `+schemaIdInjective+` over a +`+RegionSchema+` record with a `+schemaId : Nat+`. That record does not +exist in the current codebase — a Schema is just a `+List Field+`, +identified structurally. The equivalent L2 soundness claims at the +current design are proven in Region.idr: + +.... +fieldNameInj : MkField n1 t1 = MkField n2 t2 -> n1 = n2 +fieldTypeInj : MkField n1 t1 = MkField n2 t2 -> t1 = t2 +fieldInj : MkField n1 t1 = MkField n2 t2 -> (n1 = n2, t1 = t2) +schemaEqSym : SchemaEq s1 s2 -> SchemaEq s2 s1 +schemaEqTrans : SchemaEq s1 s2 -> SchemaEq s2 s3 -> SchemaEq s1 s3 +lookupFieldName : (prf : FieldIn name schema) + -> fieldName (lookupField prf) = name +.... + +Together with the pre-existing `+schemaEqRefl+`, these make `+SchemaEq+` +a full equivalence relation and pin down "`same structural identifier +implies same schema`" at the Idris2 level. `+lookupFieldName+` closes +the L2 soundness gap: having a `+FieldIn+` witness guarantees the +extracted field really answers to the looked-up name. + +*Original task description preserved for history:* If two schemas have +the same `+schemaId : Nat+`, they are the same schema. This is required +for the L2 guarantee (region-binding) to be sound: + +.... +schemaIdInjective : (s1, s2 : RegionSchema) -> + schemaId s1 = schemaId s2 -> + s1 = s2 +.... + +Without this, an attacker can mint two schemas with the same ID and +confuse the typed-access layer. If `+RegionSchema+` is a record then you +need decidable equality on every field. + +*Difficulty:* easy if `+RegionSchema+` is simple, medium if it has +nested List/Map fields. + +==== P2 — Interop (parser + round-trip, ECHIDNA coverage) + +*P2.1. Parser round-trip property.* AffineScript parser in +`+lib/ocaml/Parser.affine+` / `+Lexer.affine+` / `+Ast.affine+`. The +ECHIDNA runs listed in `+LEVEL-STATUS.md+` are for runtime L1-L6; there +is no property-based test asserting `+parse (print ast) = Right ast+`. +Add one. This is not an Idris2 proof — it’s an ECHIDNA generator + a +fuzz run at 10^5 or higher. Until the parser is ported to Idris2, the +formal-proof version is not available, but the ECHIDNA check is cheap +and catches round-trip bugs immediately. + +*Difficulty:* easy. + +*P2.2. Parser produces well-formed modules.* Similar — state that every +successful parse yields an AST satisfying a `+WellFormed+` predicate (no +dangling region refs, no unbound locals, all function indices in range). +Can be an ECHIDNA predicate today and a mechanical proof once the parser +ports to Idris2. + +*Difficulty:* easy. + +==== P3 — Usability / performance / versatility + +*P3.1. Erasure guarantee formalization. ✅ DONE 2026-04-18 (A9) — +parser-level + QTT witness; full `+.wasm+` byte-equality deferred.* + +`+ProofErasureGuarantee+` was a nullary +`+MkErasure : ProofErasureGuarantee+` sitting in `+Proofs.idr+` as a +documentation witness only. The A9 session landed the strongest erasure +claim the current codebase can support: + +* *Parser-level property test* (`+tests/echidna/echidna-harness.mjs+`, +Property 5): random `+.twasm+` programs are textually stripped of their +`+effects { ... }+` clauses, both versions are parsed, and their ASTs +are asserted equal modulo the proof-only keys `+effects+`, `+caps+`, and +`+loc+`. Structural equality modulo those keys demonstrates that the +`+effects+` annotation is carried in a separable syntactic slot — +removing it does not reshape the rest of the program. Running with +`+--iterations 50+` currently produces 8/8 successful pairs matching +(100%). A new obligation `+effects-erasure-parser-level+` is submitted +to ECHIDNA alongside the existing parser obligations. +* *QTT-level witness in Idris2* (`+TypedWasm/ABI/Proofs.idr+` — +`+Erases f+` + `+dropCertErases+`): the nullary +`+ProofErasureGuarantee+` is kept as a legacy alias; the new +per-function witness `+Erases f+` forces `+f+`’s certificate argument to +be multiplicity-0, so constructing `+MkErases f+` only type-checks when +the 0-quantity discipline is preserved — at which point QTT (Brady & +Christiansen 2021) guarantees the certificate is not in the runtime +closure. `+dropCertErases : Erases dropCert+` is a machine-checked +instance. + +*Deferred (P3.1(a) literal byte-equality):* compiling a proof-carrying +program alongside its hand-written counterpart and diffing the `+.wasm+` +output is blocked pending a `+.twasm+`→`+.wasm+` emitter. Once an +emitter lands, extend Property 5 to run both sides through the emitter +and `+assertBytesEqual+`. The parser-level property captures the +erasability claim at the strongest scope testable against the current +toolchain. + +*Difficulty (historical):* (a) easy _given an emitter_ — today it +reduces to extending Property 5 with two `+emit()+` calls and a byte +buffer compare; (b) done via QTT citation in the Proofs.idr header +comment. + +*P3.2. Levels progression monotonicity. ✅ DONE 2026-04-18 (A8) — +reframed for current ProgressiveCheck / ProofCertificate design.* + +The original P3.2 asked for +`+levelMonotone : LevelAchieved n -> LTE m n -> LevelAchieved m+` over a +`+LevelAchieved+` predicate that does not exist in the codebase. Under +the current design, the structural monotonicity relevant at the Idris2 +level is _composition preservation_, proven in Proofs.idr: + +.... +LevelAchievedIn : (n : Nat) -> List LevelAttestation -> Type + LAHere : LevelAchievedIn n (MkAttestation n Proven :: rest) + LAThere : LevelAchievedIn n rest -> LevelAchievedIn n (att :: rest) + +achievedAppendL : LevelAchievedIn n xs -> LevelAchievedIn n (xs ++ ys) +achievedAppendR : LevelAchievedIn n ys -> LevelAchievedIn n (xs ++ ys) + +LevelAchieved : Nat -> ProofCertificate -> Type + -- lifted from LevelAchievedIn over the certificate's attestations + +composeAchievedL : LevelAchieved n c1 -> LevelAchieved n (composeCertificates c1 c2) +composeAchievedR : LevelAchieved n c2 -> LevelAchieved n (composeCertificates c1 c2) +.... + +A level achieved in either component of a `+composeCertificates+` +combination is still achieved in the composition. The stronger +"`progressive-order`" claim — achieving level N implies all lower levels +hold — would require redesigning `+ProgressiveCheck+` with a typed +`+level = S prevLevel+` invariant. That redesign is left as future work; +the composition monotonicity above is the useful structural claim at the +current design. + +*Original task description preserved for history:* If a program achieves +Level N, it achieves all levels 1..N. Stated as: + +.... +levelMonotone : LevelAchieved n -> (m : Nat) -> LTE m n -> LevelAchieved m +.... + +Currently `+ProgressiveCheck+` in `+Proofs.idr+` sort of encodes this +operationally but does not prove the monotonicity as a theorem. + +*Difficulty:* easy once you add a `+LevelAchieved+` predicate. + +=== What NOT to do + +* *Don’t rewrite the existing files.* The data encodings are thoughtful +and the comments are valuable. Add theorems alongside them, don’t +replace them. +* *Don’t start from Tropical or Epistemic.* Those are the draft files. +Fix the standalone check as preliminary work but do not pour proof +effort into them until they compile. +* *Don’t try to prove erasure inside Idris2* — it is a property of the +compiler, not the language. P3.1 documents the correct approach. +* *Don’t conflate structural and propositional claims.* "`QTT enforces +single consumption`" is a structural claim (true); “`forall +[loweralpha, start=8] +. consumed h -> consumed h -> Void`” is a theorem (currently unproven). +The paper should distinguish these. +* *Don’t add `+believe_me+`, `+assert_total+`, `+postulate+`, or +`+sorry+`.* The zero-dangerous-pattern inventory is a selling point. +Preserve it. +* *Don’t reach for Lean4 or Coq.* Idris2 is the right prover for this +codebase per the estate rule (Idris2 is the preferred proof backend). +Staying in-tree keeps the proof toolchain singular. + +=== Recommended session sequence + +[arabic] +. *Session 1* — fix `+Tropical.idr+` and `+Epistemic.idr+` standalone +checks. Get both into `+typed-wasm.ipkg+`. Commit as a single +infrastructure fix. +. *Session 2* — port TropicalSemiring axioms from 007. This is low-risk +rehearsed work and gives the proof harness a workout. +. *Session 3* — Linear.idr consumption theorem (P0.2). This is the real +L10 guarantee. +. *Session 4* — Lifetime.idr `+Outlives+` preorder + `+loadSafe+` +(P0.3). L9. +. *Session 5* — Effects.idr `+EffectSubsumes+` preorder + compose +(P0.4). L8. +. *Session 6* — MultiModule.idr CompatCertificate preorder + no-spoofing +theorem (P0.5). The flagship. May run long; split if needed. +. *Session 7* — Replace every ceremonial attestation in `+Proofs.idr+` +with evidence-consuming variants (P1.1). Mechanical once P0 is done. +. *Session 8* — Region.idr injectivity (P1.3), parser ECHIDNA (P2.1, +P2.2), Levels monotonicity (P3.2). Cleanup session. + +After each session: run `+idris2 --check+` on every file in +`+typed-wasm.ipkg+`, run `+panic-attack assail+` on the +Rust/AffineScript adjacent code (no new unsafe code should land), update +this file’s inventory table, commit. + +=== Outstanding infrastructure work — Layout module fix ✅ DONE 2026-04-18 + +*Status:* resolved in the same session it was identified. All four +`+Layout.*+` modules plus the `+TypedWasm.ABI.Layout+` bridge are back +in `+typed-wasm.ipkg+`, the `+import TypedWasm.ABI.Layout+` is restored +in `+TypedWasm/ABI/Proofs.idr+`, and the full 21-module ipkg builds +cleanly under Idris2 0.8.0-712523a89. + +*Fixes applied, by issue:* + +[arabic] +. *Mutual recursion not declared* — wrapped `+WasmHeapType+` and +`+WasmValType+` in a single `+mutual+` block (and separately +`+WasmValTypeValid+` / `+WasmGCLayoutValid+` in +`+TypedWasm.ABI.Layout+`). +. *Visibility annotations missing* — added `+public export+` to every +data type, constructor, function, layout value, and `+DecEq+` / data +instance in `+Layout/Types.idr+`, `+Layout/ABI.idr+`, +`+Layout/Stdlib.idr+`, `+Layout/AirborneSubmarineSquadron.idr+`, and +`+TypedWasm/ABI/Layout.idr+`. +. *Imports missing* — added `+Decidable.Equality+` + `+Data.List+` to +`+Layout/Types.idr+`; `+Data.List.Quantifiers+` to +`+TypedWasm.ABI.Layout+`; `+Data.List+` to +`+Layout/AirborneSubmarineSquadron.idr+`. +. *Nested `+with+` block patterns* — rewrote the `+DecEq WasmHeapType+` +and `+DecEq WasmValType+` instances as four plain mutual functions +(`+decEqHT+`, `+decEqVT+`, `+decEqVTList+`, `+decEqFields+`) with thin +non-mutual interface wrappers. This sidesteps Idris2 0.8’s +interface-resolution chain through `+List (String, WasmValType)+`. +. *Refl-impossible patterns* — replaced `+LHS impossible+` clauses with +`+prf = case prf of Refl impossible+`. The scope change lets Idris2 +reduce the layout values after they see `+public export+`. +. *Auto-bound implicit shadowing* — lowercase references to +`+stringLayout+`, `+resultLayout+`, etc. inside type signatures were +being treated as implicit pattern variables that shadowed the real +definitions. Fully qualifying as `+Layout.Types.stringLayout+` (and +friends) suppresses the auto-bind and lets the definitions reduce. +. *`+(x y : T)+` binder syntax* — Idris2 0.8 prefers comma-separated +`+(x, y : T)+`; updated all affected binders. +. *`+prefix+` is reserved* — renamed `+SubStruct+`’s `+prefix+` argument +to `+pre+` (operator fixity keyword in Idris2 0.8). +. *Non-linear SubStruct transitivity pattern* — rewrote +`+data Subtype+`’s `+SubStruct+` constructor to carry an explicit +equality witness `+prf : fs = pre ++ rest+`, then proved `+subTrans+` +for the SubStruct/SubStruct case using `+trans+`, `+cong+`, and +`+sym appendAssociative+`. (The direction of +`+appendAssociative : l ++ (c ++ r) = (l ++ c) ++ r+` needs `+sym+` to +rearrange `+(pre ++ rest1) ++ rest2+` into `+pre ++ (rest1 ++ rest2)+`.) +. *`+WasmGCLayoutValid+` struct-field predicate* — replaced the +`+case vt of … => True+` predicate (which mixed `+Bool+` with `+Type+`) +with a proper `+WasmValTypeValid+` inductive in a mutual block. +. *`+WasmGCEq+` constructor* — replaced the over-strong +`+MkGCEq : decEq h1 h2 = Yes Refl -> WasmGCEq h1 h2+` with the simpler +propositional form `+MkGCEq : h1 = h2 -> WasmGCEq h1 h2+`. The original +encoding required a non-trivial theorem about `+decEq+` to construct a +reflexive witness. + +*Net result:* the aggregate-library Layout contracts (the secondary +purpose of typed-wasm, per ADR-004) are back in the ipkg alongside the +typed-wasm core, with zero `+believe_me+` / `+assert_total+` / +`+postulate+` / `+sorry+`. `+%default total+` preserved throughout. + +=== Pre-existing notes (preserved from prior revision) + +==== Template ABI Cleanup (2026-03-29) + +Template ABI removed – was creating false impression of formal +verification. The removed files (Types.idr, Layout.idr, Foreign.idr) +contained only RSR template scaffolding with unresolved project/author +template tokens and no domain-specific proofs. diff --git a/PROOF-NEEDS.md b/PROOF-NEEDS.md deleted file mode 100644 index 145c454..0000000 --- a/PROOF-NEEDS.md +++ /dev/null @@ -1,1114 +0,0 @@ - -# PROOF-NEEDS.md - -**Scope:** handoff document for the Claude instance that will deepen -typed-wasm's formal verification. Read this file in full before -touching `src/abi/TypedWasm/ABI/*.idr`. Written 2026-04-13 by the -dual-AST / parser-panic cleanup Claude after a targeted audit. - -## The one-line honest summary - -typed-wasm has **eleven Idris2 files encoding a safety protocol using -QTT linearity and dependent types, zero dangerous patterns, but almost -no explicit theorems** — most of the guarantees are structural -consequences of the type encoding rather than propositions that have -been stated and mechanically proven. `Proofs.idr` ceremonially -rubber-stamps attestations without using their witnesses. The next -Claude's job is to close the gap between "the types forbid it at -compile time" (true) and "here is a lemma proving it is forbidden" -(mostly absent). The distinction matters for publication-quality -claims — a reviewer asking _"where is the theorem?"_ currently has no -answer to point at. - -## RECONCILIATION 2026-06-16 (codegen climb — the second assurance axis: T1 execution gate landed, T2 in progress) - -> **The honest summary above concerns the _Idris-model_ axis ("where is the -> theorem?"). This block introduces the _codegen→verified-wasm_ axis — the -> assurance that the Rust producer's emitted bytes are what an independent -> verifier accepts and a wasm engine executes correctly. The two axes are -> complementary: the Idris ABI proves the _protocol_; the climb proves the -> _running implementation honours it_. (Module count is now 22, not the -> "eleven" of the 2026-04-13 summary — later reconciliations supersede it.)** -> -> **The assurance ladder (`.twasm` source → IR → emitted wasm → verified):** -> -> | Tier | Obligation | Status (2026-06-16) | -> |---|---|---| -> | **T1** Execution gate | emitted store/load bodies _compute_ the intended memory semantics (width, offset, sign/zero-extension, no-clobber) | ✅ **landed** — `crates/typed-wasm-codegen/tests/execute_lowering.rs` instantiates the lowered module in **wasmi** (pure-Rust, runs in CI without a system wasmtime) and round-trips every scalar width + proves a narrow store touches **only** its own bytes. Proven non-vacuous by mutation (reintroducing a narrow-width bug fails the gate). | -> | **T2** Verifier self-certification | the verifier independently _decodes the code section_ and checks each pinned access lands on a load/store of the field's exact type/width/offset, in-region | 🟡 **in progress** (this session). Producer half: access sites pinned to a body-instruction index (`AccessSite.instr_index: Option`; the hand-built `example01` / paint-type representative sites are carried **declared-only**, honestly _not_ type-checked). Verifier half: `verify_access_typing_from_module` + `AccessTypingReport { type_verified, declared_only, errors }`, surfaced by `tw-verify`. Closes proposal-0002's deferred `AccessSiteMisalignment`. | -> | **T3** Parser totality | the `.twasm` parser never panics on any input | ⚠️ **partial** — v0 hardened against malformed/truncated input (PR #168), but **3 pre-existing arithmetic panics remain** (div-by-zero / overflow in `parse_array_size_expr` + `compute_region_byte_size`). Deferred to a hardening PR. | -> | **T4** Layout-equivalence lemma | `Layout/ABI.idr` field offsets **=** Rust `resolve_field` offsets | ❌ **open** — two independent implementations of the same field-offset arithmetic, with no proof they agree. The next formal bridge. | -> | **T5a** Verifier↔spec link | the Rust verifier _refines_ `VerifierSpec.idr` | ◐ **trusted-base** — ADR-0005 pins audit invariants (I1 provenance / I2 witness fidelity / I3 module shape) at the `MkTrustedFixture` boundary; the Rust verifier remains the trusted base. Constructive soundness (path 2) and WasmCert tie-back (path 1) are future superseding ADRs. | -> | **T5b** Wasm-semantics tie-back | emitted bytes mean what we claim under a mechanised wasm semantics (WasmCert-Isabelle/Coq) | ❌ **open** — multi-week external dependency. T1's execution gate is the empirical stand-in. | -> -> **Climb position.** Front-end staircase (languages → typed-region IR) is -> stop-gapped by the `.twasm` parser seam (ADR-0004 _Proposed_; real -> AffineScript/ephapax AST bridge deferred). Back-end staircase (IR → verified -> wasm) is where the climb is: Steps 1 (field readers, #169) + 2 (field writers -> + width-exact scalar accesses, #171) merged; the T1 gate landed alongside; -> T2 self-certification is the active work, then the T4 layout lemma, then the -> T5a verifier↔spec link. -> -> **Ground truth re-verified 2026-06-16:** `idris2 --build src/abi/typed-wasm.ipkg` -> → exit 0, **22/22 modules**; zero `believe_me` / `postulate` / `sorry` / -> `Admitted` / `assert_total` / holes (every scanner hit is a docstring -> disclaimer). The `docs/proof-debt.md` zero-debt invariant holds. -> -> **Governance note.** The whole `crates/typed-wasm-verify/src/` (`verify.rs`, -> `section.rs`, `lib.rs`) carried the SPDX tag but was **missing the literal -> owner `Copyright` line** — invisible drift that trips the strict pre-commit -> hook on any commit touching those files (so T2's verifier half was -> commit-blocked). Surfaced and corrected under a one-time owner authorisation -> this session; the hook is kept strict. -> -> **No `believe_me` / `assert_total` / `postulate` / `sorry` / `assert_smaller` -> introduced; `%default total` preserved. T1 is an executable test, not a proof -> obligation; T2 is a decode-time check _inside_ the (trusted-base) Rust -> verifier — it strengthens the trusted base's self-consistency, it does not -> reduce the trusted base.** - -## RECONCILIATION 2026-06-16 (A15/A16 — estate-axis accommodation) - -> L11/L12/Echo have been **cross-documented and mirrored to the canonical -> estate repos** after an adversarially-verified audit found them -> internally-sound but un-accommodated (sourced/ported from non-canonical -> origins). New, machine-checked (idris2 0.8.0, full `typed-wasm.ipkg` green): -> -> - **Tropical.idr** — dioid order `tropLe` (refl/trans + add/mul monotonicity), -> MinMax bottleneck `tropMax` + `hubCeiling`, `ResidueMeasure`, and a new -> `Level11BottleneckProof` + `bottleneckCeilsEdges` wired into -> `Proofs.attestL11_Bottleneck`/`_Sound`. Mirrors `tropical-resource-typing` -> `Resource.{Algebra.Ordered, Instances.MinMax, Bridge, EchoBridge}` @ 2e35229. -> - **Echo.idr** — `EchoR` + `echoToResidue` (mirrors `echo-types` -> `EchoResidue.agda` @ 2bbdb49); header re-characterised: an echo-type is a -> **tropically-graded modality of structured information loss** (grade = min-plus -> = `Tropical.TropCost`), exact-on-a-fiber recoverability — the -> monad/comonad/adjunction VARIANCE is deferred to upstream `--safe` Agda -> (RETRACTION R-2026-05-18 + experimental R0–R4), NOT asserted here. -> - **Epistemic.idr** — ADDITIVE `syncGrade` (∞ = never-synced) reusing the -> sibling `Tropical.TropCost`; extant A10–A14 Nat-indexed proofs untouched. -> Header IS-NOT note: read-consistency is a *different* problem from canonical -> `epistemic-types`' standpoint-indexed modality. -> -> Three extend-upstream drafts prepped local/unpushed (Lean closure functor; -> Agda re-sync liveness `AccessibleModality` instance; Agda `DispHom` packaging), -> each verified by its own prover. See LEVEL-STATUS.md "Estate-axis accommodation". - -## RECONCILIATION 2026-06-02 (audit-boundary half of post-A10 items 7 + 8 promoted to ADR-0005 — read this FIRST) - -> **The "Full proof bodies for `VerifierSpecAgreement` / -> `SourceVerifierAgreement`" long-tail item (issue #103) is now -> closed via path (3) — explicit ADR.** -> -> The 2026-05-27 banner below recorded the bodies as TOTAL in PR #79 -> (commit `06ec00e`). What remained per issue #103 was a load-bearing -> home for the audit-boundary story: every `VADifferential` / -> `SADifferential` step ultimately routes through a -> `MkTrustedFixture` construction, and the trust-injection moment -> needed a single, named, cross-referenced specification rather than -> an inline docstring. -> -> **ADR-0005** -> (`docs/decisions/0005-trustedfixture-audit-boundary.adoc`, -> 2026-06-02) pins three inspection invariants every -> `MkTrustedFixture m` construction site is audited against: -> -> * **I1 — Provenance.** The pair `(trustedFixtureName, -> trustedFixtureId)` must correspond to an existing row in the -> Rust differential harness -> (`crates/typed-wasm-verify/tests/cross_compat.rs`). -> * **I2 — Witness fidelity.** The `FunctionsAccepted m.functions` -> payload must be the structural witness the harness's ACCEPT -> verdict establishes; rejected fixtures yield no `MkTrustedFixture`. -> * **I3 — Module shape.** The indexing `ModuleSummary` must mirror -> the harness's `ModuleSummary` reconstruction for the same -> fixture bytes (function order + decoded ownership intents). -> -> **What this is not.** ADR-0005 is not a constructive proof of -> Rust-verifier soundness; the Rust verifier remains the trusted -> base for the differential path. The two supersession paths from -> issue #103 — WasmCert-Isabelle tie-back (path 1) or constructive -> Rust-verifier soundness (path 2) — remain valid future upgrades -> and would each ship as a fresh ADR superseding 0005. -> -> **Source-code cross-reference.** A docstring near `MkTrustedFixture` -> in `src/abi/TypedWasm/ABI/VerifierSpec.idr` points at ADR-0005, so -> a reader landing on the record's definition can find the -> invariants without rediscovering them. Single grep point for -> trust injections: `git grep MkTrustedFixture`. -> -> **No `believe_me` / `assert_total` / `postulate` / `sorry` / -> `assert_smaller` introduced; `%default total` preserved across -> the arc. The closure work was an ADR + a docstring cross-reference -> + a proof-debt banner — no new proof obligations, no new code -> behind the lemma bodies that PR #79 already shipped.** - -## RECONCILIATION 2026-05-30 (carrier-ABI proposals 0001 + 0002 accepted + ADR'd — read this FIRST) - -> **The "verifier L1-L6 + L13-L16 coverage on emitted wasm" long-tail -> item shrinks substantially.** The 2026-05-27 banner below listed -> this as "in progress on PRs #76 / #77 in a parallel session"; the -> arc has now closed end-to-end: -> -> * **Proposal 0001** (`docs/proposals/0001-multi-producer-carrier-section.adoc`) -> — `typedwasm.regions` + `typedwasm.capabilities` carrier sections. -> `[accepted]` 2026-05-30 (PR #115) → promoted to -> `docs/decisions/0002-multi-producer-carrier-sections.adoc` -> (ADR-0002) in PR #116. -> * **Proposal 0002** (`docs/proposals/0002-access-site-carrier.adoc`) -> — `typedwasm.access-sites` per-instruction carrier for L2 -> enforcement. `[accepted]` 2026-05-30 (PR #115) → promoted to -> `docs/decisions/0003-access-site-carrier.adoc` (ADR-0003) in PR -> #116. -> * Verifier passes shipped: `verify_regions_from_module` (PR #107), -> `verify_capabilities_from_module` and -> `verify_access_sites_from_module` (PR #109) — all behind -> `unstable-l2` / `unstable-l15` Cargo features in -> `crates/typed-wasm-verify/`. -> -> **What this closes.** L2-the-enforcement, L3, L4, L5, L6 (regions -> half), and L15-A/B on emitted wasm now have carrier-backed verifier -> passes. `LEVEL-STATUS.md` rows updated from "proposal-stage" to -> "YES (carrier-backed)" in PR #115. -> -> **What is still open in the long-tail.** -> -> * **L13 cross-module schema agreement (positive form)** — proposal -> 0003 (`docs/proposals/0003-region-imports-carrier.adoc`) is -> `[draft]`. Wire format defined; gated on producer-side -> multi-module emission (AffineScript Roadmap C3 / Ephapax not yet -> on roadmap). -> * **L15-C (per-call-site capability monotonicity)** — proposal -> 0004 (`docs/proposals/0004-capability-grants-carrier.adoc`) is -> `[draft]`. Wire format defined; gated on producer-side L15-A -> emission. -> * **WasmCert-Isabelle tie-back** — unchanged (multi-week external -> dependency). -> * **Emitted-wasm byte-equality (P3.1(a))** — unchanged (blocked -> on `.twasm → .wasm` emitter not yet existing). -> * **Idris2 parser round-trip** — unchanged (blocked on AffineScript -> parser port to Idris2). -> * **Producer-side codegen of access-sites** — AffineScript at -> affinescript#462; Ephapax counterpart owner-action pending -> (auto-mode classifier blocked the cross-repo create on 2026-05-30). -> -> **No `believe_me` / `assert_total` / `postulate` / `sorry` / -> `assert_smaller` introduced; `%default total` preserved across the -> arc. The acceptance work was design-doc + ADR + verifier-pass -> codecs, not new proof obligations.** - -## RECONCILIATION 2026-05-27 (post-A10 items 7 + 8 bodies closed — read this FIRST) - -> **The two agreement records introduced by PR #72 / A13 are now -> inhabited.** `VerifierSpecAgreement` and `SourceVerifierAgreement` -> have concrete inhabitants `verifierSpecAgreement` / -> `sourceVerifierAgreement` with totally-proven bodies in every -> direction. This was the "multi-week residual" PR #74 explicitly -> flagged. Closed in PR #79. -> -> **Design choice that unblocked the bodies.** The differential -> constructor carries the structural witness it certifies, packaged -> inline via an embedded `TrustedFixture m`: -> -> data VerifierAccepts : ModuleSummary -> Type where -> VAStructural : FunctionsAccepted m.functions -> -> VerifierAccepts m -> VADifferential : (fixture : TrustedFixture m) -> -> VerifierAccepts m -> -> record TrustedFixture (m : ModuleSummary) where -> constructor MkTrustedFixture -> trustedFixtureName : String -> trustedFixtureId : Nat -> trustedWitness : FunctionsAccepted m.functions -> -> Trust-injection moves to `MkTrustedFixture` construction (single -> grep point for audit). All four agreement lemmas become total by -> case analysis: both `VAStructural` and `VADifferential` surface a -> `FunctionsAccepted m.functions` payload that wraps directly into -> `SpecAccepts`; the spec-to-verifier direction lifts via -> `VAStructural`; source ↔ verifier mirror the same pattern. -> -> **Module: `src/abi/TypedWasm/ABI/VerifierSpec.idr` (~620 LOC).** -> Zero `believe_me` / `assert_total` / `postulate` / `sorry` / -> `assert_smaller`; `%default total`. Build green 22/22 modules -> under Idris2 0.8.0. +33 Layer 1 regression assertions. -> -> **End-to-end demo.** `fixtureCleanLinearConsumerModule` mirrors -> cross_compat row 1. `fixtureCleanLinearConsumerDifferentialAccepts` -> exercises the smart constructor; -> `fixtureCleanLinearConsumerSpecAccepts` runs the witness through -> `verifierSpecAgreement.verifierIsSound` for the end-to-end -> closure. -> -> **Discrimination.** `notSpecAcceptsBadDoubleConsume`, -> `notVerifierAcceptsBadDoubleConsume` (both ctors), -> `notSourceAcceptsBadDoubleConsume` (both ctors), -> `notSpecAcceptsBadDoubleProduce` — show L10 has teeth and the -> differential escape hatch cannot smuggle a bad module past the -> verifier (since `MkTrustedFixture` requires a structural witness, -> which is impossible for the bad module). -> -> **Comparison with PR #74 (closed as superseded).** #74 kept -> `VADifferential` opaque (string + nat only) and offered -> `Maybe`-returning bridges plus a closed-world `RegisteredFixture` -> GADT. Soundness/completeness for the unparameterised agreement -> records remained unprovable in that design — that's the -> "multi-week residual" #74's description named. #79 refactors -> the data type instead. The audit story is preserved; the agreement -> records cease to be obligations. -> -> **Open after this closure.** Items remaining in the long-tail (in -> rough decreasing priority): verifier L1-L6 + L13-L16 coverage on -> emitted wasm (#34, #35; in progress on PRs #76 / #77 in a parallel -> session), WasmCert-Isabelle tie-back, emitted-wasm byte-equality -> (P3.1(a), blocked on emitter), parser round-trip in Idris2 -> (blocked on parser port). - -## RECONCILIATION 2026-05-27 (standards#130 long-tail closed — read this FIRST) - -> **The "LevelAttestation reindexed by witness" residual is closed.** -> The 2026-05-18 reconciliation banner below flagged that the A9 -> `attestLN_Sound` family proves only "the certificate provably claims -> level N", not the stronger "attestation entails the level's -> semantic property" claim — and that the stronger version required -> `LevelAttestation` reindexed by the witness. That redesign now -> lands in `Proofs.idr` as the **purely additive** `LevelAttestationW` -> section. -> -> 1. **`data LevelAttestationW : (n : Nat) -> Type`** — witness-indexed -> GADT, fifteen constructors, one per level. Each constructor -> packages the actual level-specific witness (`Schema`, `FieldIn`, -> `WasmTypeCompat`, `Pointer.Ptr ... NonNull`, `InBounds`, -> `AccessResult`, `ExclusiveWitness`, `EffectSubsumes`, -> `Lifetime.Outlives`, `CompletedProtocol`, `AllPairsCosts`, -> `Level12Proof`, `IsolatedModule`, `WellFormedProtocol`, -> `FunctionCaps`). -> -> 2. **Fifteen `attestLNW_*` smart constructors** mirror the legacy -> `attestLN_*` family but return the witness-carrying variant -> instead of the unindexed `LevelAttestation`. -> -> 3. **Fifteen `attestLNW_Entails` extractors** — the -> "attestation entails the level's semantic property" lemmas. -> Each is a one-line pattern match that returns the witness (paired -> with its existential type-level indices via dependent pair where -> applicable). A consumer holding `LevelAttestationW 7` can now -> discharge the L7 semantic property (alias-freeness via -> `ExclusiveWitness s`) — not just the predicate "claims L7". -> -> 4. **Legacy bridge `toLegacy : {n : Nat} -> LevelAttestationW n -> -> LevelAttestation`** projects to the unindexed shape so existing -> callers of `List LevelAttestation` (e.g. `ProofCertificate`) -> keep working unchanged. -> -> 5. **Fifteen round-trip `Refl` equalities** `toLegacy -> (attestLNW_X w) = attestLN_X w` pin the two representations -> together at the type-equality level — any future drift trips -> the typechecker. -> -> 6. **`attestLW_AchievedIn : (att : LevelAttestationW n) -> -> LevelAchievedIn n [toLegacy att]`** — uniform achievement lemma -> subsuming the fifteen A9 `attestLN_Sound` cases. One lemma -> covers every level under the witness-carrying redesign. -> -> **Purely additive.** Existing `LevelAttestation`, `MkAttestation`, -> `attestLN_*`, `attestLN_Sound`, `LevelAchievedIn`, -> `composeCertificates`, `ProofCertificate` — all unchanged, all -> prior proofs unaffected. Idris2 0.8.0 `--build` green, 21/21 -> modules, rc=0, zero new `believe_me` / `assert_total` / `postulate` -> / `sorry` / `assert_smaller`, `%default total` preserved. -> -> **Open after this closure.** Standards#130 sub-issue is fully -> discharged (its A9 weak form + this stronger reindexed form). -> Other long-tail items unchanged: WasmCert-Isabelle tie-back, -> emitted-wasm byte-equality (P3.1(a), blocked on emitter), parser -> round-trip in Idris2 (blocked on parser port), verifier L1-L6 + -> L13-L16 coverage (#34/#35, in progress on PRs #76/#77). - -## RECONCILIATION 2026-05-26 (A13 follow-up) - -> **A13 follows A12 in the same calendar day.** Per coordinator -> pre-clearance for items 5 + 7 + 8 (and the small A12 leave-behind), -> this round closes **the remaining post-A10 audit items in their -> statement-level form**: -> -> 1. **Item 5a (L13 × L10) closed.** `ModuleIsolation.idr` gains -> `LinearAcrossBoundary from to regName bs token`, pairing an L13 -> `AccessWitness` with an L10 `LinHandle`. The no-bypass theorem -> `linearTransferRequiresBoundary` proves that any non-local -> linear-handle transfer requires a concrete boundary in `bs` — a -> linear handle cannot leave an isolated module without an L13 -> boundary declaration. `linearTransferLocal` is the local-case -> constructor. Proof shape reuses `crossAccessImpliesBoundary` -> from L13 directly; the cross-level claim is a clean lift. -> -> 2. **Item 5b (L14 × L13) closed.** `SessionProtocol.idr` now -> imports `ModuleIsolation` and gains `SessionAcrossBoundary` with -> three theorems: `sessionAcrossPreservesState` (the state index -> survives the transfer), `sessionTransferRequiresBoundary` (the -> same no-bypass shape as L10), and `sessionTransferLocal` -> (local-case). Together they prove a session handle cannot -> silently change state or escape its module without an L13 -> witness. -> -> 3. **A12 leave-behind closed.** `Region.idr` gains `RegionsOverlap` -> (an address lying inside both region footprints) and -> `disjointImpliesNoOverlap` proving `RegionDisjoint -> Not -> RegionsOverlap`. This is the L7/L10 cross-level link the A12 -> section header promised — disjointness now has byte-level -> teeth. `regionsOverlapSym` is the symmetry companion. -> -> 4. **Items 7 + 8 stated as obligations.** New module -> `VerifierSpec.idr` introduces `SpecAccepts m` (the Idris2 L7+L10 -> structural acceptance predicate on `ModuleSummary`), -> `VerifierAccepts m` (opaque; witnessed by the Rust differential -> harness via `differentialAccepted`), and `SourceAccepts m` -> (opaque; witnessed by the source-side harness). Two record -> obligations — `VerifierSpecAgreement` (item 7) and -> `SourceVerifierAgreement` (item 8) — bundle the soundness and -> completeness directions so partial proofs can land one face at -> a time. Composition lemmas `sourceImpliesSpec` and -> `specImpliesSource` give the test harness end-to-end targets. -> -> **What this does NOT do.** Items 7 and 8 are stated, not -> proven. The full equivalence proofs require either a full -> simulation between two implementations (multi-week) or -> extending the verifier's coverage to every level the source -> checker promises. A13 pins the obligations as typed Idris2 -> predicates so the long-tail work has a fixed target. -> -> **15 new named theorems / data types** (`LinearAcrossBoundary`, -> `acrossWitness`, `acrossHandle`, `linearTransferRequiresBoundary`, -> `linearTransferLocal`, `SessionAcrossBoundary`, -> `sessionAcrossPreservesState`, `sessionTransferRequiresBoundary`, -> `sessionTransferLocal`, `RegionsOverlap`, -> `disjointImpliesNoOverlap`, `regionsOverlapSym`, `SpecAccepts`, -> `VerifierAccepts`, `SourceAccepts` plus `VerifierSpecAgreement` / -> `SourceVerifierAgreement` / `sourceImpliesSpec` / -> `specImpliesSource`). Regression **68/68** under Idris2 0.8.0 -> (both layers). -> -> **Open after A13.** No items remain from the original post-A10 -> 8-item audit. Long-tail work that exceeds a one-session scope: -> the actual proof bodies for `VerifierSpecAgreement` / -> `SourceVerifierAgreement`; the `LevelAttestation` reindexed-by- -> witness redesign (standards#130 / epic standards#124); WasmCert- -> Isabelle tie-back; emitted-wasm byte-equality for erasure -> (P3.1(a), blocked on emitter); parser round-trip in Idris2 -> (ECHIDNA-only at present). - -## RECONCILIATION 2026-05-26 (A12 follow-up) - -> **A12 follows A11 in the same calendar day.** Per coordinator-routed -> A12 go-ahead, this round closes **3 more** of the 8 untracked gaps -> from `project_typed_wasm_proof_debt_post_a10.md`: -> -> 1. **Item 4 closed IN FULL.** The A11 partial (`composeAssocLists` -> was list-side only) is now superseded by `composeAssoc` proving -> three-way associativity of `composeCertificates` across all three -> fields (list parts, multi-module parts, AND the `highestProven` -> Nat). Made possible by switching `composeCertificates` from the -> Ord-derived `Prelude.min` to the structural `Data.Nat.minimum` -> (per coordinator hint), which makes `minimumAssociative` apply -> directly. `composeHighProvenComm` adds Nat-side commutativity -> via `minimumCommutative`. The original `composeAssocLists` is -> kept as a back-compat corollary. -> -> 2. **Item 6 closed.** `RegionDisjoint r1 r2` in `Region.idr` — -> a two-constructor data type witnessing that two regions' byte -> footprints `[baseAddr, baseAddr + totalSize)` don't overlap in -> either ordering. `regionDisjointSym` proves symmetry. The -> cross-level theorem linking disjointness to L7 aliasing-safety -> and L10 linearity is left for a future pass — disjointness as a -> predicate is the missing primitive the audit flagged. -> -> 3. **Item 3 closed.** `jointBudgetCompose` in -> `ResourceCapabilities.idr` proves L8 ↔ L15 joint composition: -> given individual `EffectSubsumes` witnesses + individual -> `FunctionCaps` witnesses for two functions sharing an owner -> module, the compound function satisfies both the combined L8 -> envelope (via `subsumeCompose`) AND the combined L15 module -> envelope (via the new `containedConcat` + the existing -> `l15bSoundness`). -> -> All five new theorems (`composeAssoc`, `composeHighProvenComm`, -> `RegionDisjoint`, `regionDisjointSym`, `jointBudgetCompose`, -> `containedConcat`) are guarded by `tests/proof/regression.mjs`. -> Regression now **50/50**. -> -> Items remaining from the original post-A10 audit (all explicitly -> A12 → A13 inheritance per coordinator clearance): item 5 (L13×L10, -> L14×L13 cross-level), item 7 (Rust verifier ↔ Idris2 spec -> equivalence), item 8 (source-checker ↔ verifier coverage agreement). - -## RECONCILIATION 2026-05-26 (A11 follow-up) - -> **A11 follows A10 in the same calendar day.** Where A10 closed the -> *named* deferred items, A11 attacks three of the **untracked** gaps -> uncovered by the post-A10 audit (`project_typed_wasm_proof_debt_post_a10.md`): -> -> 1. **`Sync.WriteSync` no longer admits fake writers.** The constructor -> now requires a `FieldVersion` witness with three equalities -> (`fv.field = field`, `fv.version = newVersion`, -> `fv.lastWriter = mod`) and the corollary -> `writeSyncIdentifiesWriter` extracts that witness. An adversarial -> construction `WriteSync (MkFieldVersion otherField otherVer -> differentModule) Refl Refl Refl` is now ill-typed unless the three -> coincide with the indexed field/version/writer — the very -> "provenance gap" Audit Item 1 flagged. -> -> 2. **`Knowledge.Observed` is grounded in a `Sync` event.** The -> constructor now takes `(sync : Sync mod field oldVer ver)` so -> `Observed mod field ver` cannot be inhabited without a -> causally-prior write. `observedHasProvenance` reads the witness -> back out. Audit Item 2 ("Knowledge.Observed admits unfounded -> versions") is closed. -> -> 3. **`composeCertificates` gets its first algebraic laws.** -> `achievedAppendSplit` proves `LevelAchievedIn n (xs ++ ys) -> -> Either (LevelAchievedIn n xs) (LevelAchievedIn n ys)`; -> `composeAssocLists` proves the achieved-set under three-way -> composition is associative; `composeAchievedSym` is the symmetric -> counterpart of `composeAchievedL`/`R`. Audit Item 4 -> ("composeCertificates laws unproven") is **partially** closed — -> list-level associativity is proven, but the `Nat`-min commutativity -> on `highestProven` is left for A12 because Idris2 0.8's `Prelude.min -> Nat` is a non-structural `if x < y then x else y` and does not -> reduce to `Refl` on symbolic inputs. See `composeAssocLists` -> docstring in `Proofs.idr` for the discharge plan. -> -> All five new theorems (`writeSyncIdentifiesWriter`, -> `observedHasProvenance`, `achievedAppendSplit`, `composeAssocLists`, -> `composeAchievedSym`) are guarded by `tests/proof/regression.mjs` -> Layer 1 grep + Layer 2 `--build`. Items 3, 5, 6, 7, 8 from the -> post-A10 audit remain open and inherit to a future A12. - -## RECONCILIATION 2026-05-26 (A10 closure — read this first) - -> **A10 closes the last two named "deferred" items** that survived the -> 2026-05-18 reconciliation below. Both are now mechanically proven and -> guarded by `tests/proof/regression.mjs` (Layer 1 grep + Layer 2 build, -> Layer 2 invocation fixed to `--build` from a no-op `--check`). -> -> 1. **L12 freshness propagation under concurrent writes** (PROOF-NEEDS -> §P1.2 and LEVEL-STATUS row 12) — closed by 8 new theorems in -> `Epistemic.idr` headlined by `freshnessPropagatesUnderWrites : -> Fresh mod field v v -> LT v cur -> Sync mod field v cur -> -> Fresh mod field cur cur` plus `concurrentWriteStales`, -> `resyncRecoversFresh`, `freshNotStale`, `freshImpliesEqual`, -> `staleImpliesLT`, `syncChainEndsFresh`, and the named -> `epistemicFreshness : (p : Level12Proof) -> Fresh p.reader p.field -> p.knownVersion p.currentVersion` projector that satisfies the -> P1.2 obligation directly. -> -> 2. **`compatCommute` mutual-subschema case** (PROOF-NEEDS §P0.5 -> paragraph 246) — closed in `MultiModule.idr` by `compatCommute : -> ModuleCompat from to imp exp -> SchemaSub exp imp -> -> ModuleCompat to from exp imp` plus the `noSpoofingBidir` -> corollary. A second worked example (`serviceA`/`serviceB` with -> permuted schemas, both `SchemaSub` directions inhabited) -> demonstrates the theorem on a non-trivial input. -> -> The only proof-side item still explicitly deferred is the **stronger -> `LevelAttestation` reindexed by witness** noted at the end of the -> 2026-05-18 reconciliation; everything LEVEL-STATUS or this file -> previously called "deferred" or "future work" at the proof level is -> now resolved. L15-C call-graph **surface-checker** enforcement -> remains future work (the proof-side `callCompose` was already in -> place; LEVEL-STATUS row 15 carries the marker). - -## RECONCILIATION 2026-05-18 (verified ground truth) - -> Routed from estate proof-debt epic **hyperpolymath/standards#124**, -> sub-issue **#130**. The 2026-04-13 inventory below is **superseded** -> and retained for history (estate convention: dated snapshots get -> historical banners, not rewrites). -> -> **standards#130's stated debt is refuted by ground truth.** It -> claimed "5 `believe_me` + 5 `assert_total` + 5 `partial`" and that an -> agent "called it fully real; it is not". A comprehensive re-grep -> (`believe_me`, `really_believe_me`, `assert_total`, `assert_smaller`, -> `postulate`, `idris_crash`, `prim__crash`, `%default partial`, -> `Admitted`, `sorry`, `unsafePerformIO`, `assert_linear`) over all -> 21 `.idr` files finds **zero** in code — only inside "NO believe_me" -> banner comments. This is the survey-agent **over-report** failure -> mode the epic explicitly warns about (the inverse of under-report). -> -> **Verified build (Idris2 0.8.0, `typed-wasm.ipkg`, 2026-05-18):** -> `rc=0`, **zero errors**, **21/21 modules → TTC**, `%default total` -> in all 21. Only 11 warnings, all one cosmetic kind (lowercase -> implicit-bind shadowing of `mod`/`field`/`payload`) — no soundness -> impact. The 2026-04-13 "2 files draft-only, standalone check fails -> (Tropical, Epistemic)" item is **resolved**: both are now in the -> ipkg and build clean (`believe_me` eliminated from Epistemic by -> commit `e4253f0`). -> -> **The genuine residual debt is the one §P1 below already names** — -> not trust escapes but `Proofs.idr` attestations that required a -> witness then discarded it (`attestLN_* _ = MkAttestation N Proven`). -> This pass discharges that for **all 15 levels** additively: the new -> `attestLN_Sound` family (Proofs.idr §A9) is a per-level theorem that -> cannot be invoked without the exact witness type and proves -> `LevelAchievedIn N [attestLN witness]` — the missing -> "witness ⟹ certificate-claims-level" bridge. Additive (no existing -> definition touched → no prior proof can regress), verified by the -> same clean `rc=0` build. Stronger "attestation entails the level's -> semantic property" (needs `LevelAttestation` reindexed by witness) -> remains tracked future work under standards#130. - -## Inventory snapshot (2026-04-13 — SUPERSEDED, see reconciliation above) - -- 11 `.idr` files, 2,589 LOC total, `%default total` everywhere, zero - `believe_me` / `assert_total` / `postulate` / `sorry`. -- 9 files are in `typed-wasm.ipkg` (Region, TypedAccess, Levels, - Pointer, Effects, Lifetime, Linear, MultiModule, Proofs) + Layout - aggregate. -- 2 files are **draft only** and standalone `idris2 --check` fails: - `Tropical.idr`, `Epistemic.idr`. They are NOT in the ipkg. Fix them - before claiming L11/L12. -- Structure: mostly `data` declarations + constructor helpers. No - `record` except in Region (RegionSchema) and Tropical (CostAnnotated). - Zero theorem statements of the form `lemma : P -> Q -> R` that - manipulate witnesses to prove properties. -- `LEVEL-STATUS.md` line 28 correctly labels L7-L10 as **"Proven - [sfap], erased"** where "[sfap]" = "so far as possible". That is the - honest status. L11-L12 are "draft only; not in package; standalone - check currently fails". - -## The proof-writing priority order - -Ordered by _dependability > security > interop > usability > -performance > versatility > functional extension_ per estate standing -order. Every item below names a file, a theorem to state, and a -rough difficulty. - -### P0 — Dependability (existence proofs for the structural claims) - -**P0.1. Tropical semiring laws — Tropical.idr.** The eight axioms of -a commutative semiring with zero. 007 has done this work already in -`proofs/idris2/TropicalSemiring.idr` (12 theorems, CLEAN, zero -`believe_me`). Port it. Specifically prove: - -``` -tropAddAssoc : (a, b, c : TropCost) -> tropAdd (tropAdd a b) c = tropAdd a (tropAdd b c) -tropAddComm : (a, b : TropCost) -> tropAdd a b = tropAdd b a -tropAddIdent : (a : TropCost) -> tropAdd Infinity a = a -tropMulAssoc : (a, b, c : TropCost) -> tropMul (tropMul a b) c = tropMul a (tropMul b c) -tropMulComm : (a, b : TropCost) -> tropMul a b = tropMul b a -tropMulIdent : (a : TropCost) -> tropMul (Finite 0) a = a -tropMulAnnihil : (a : TropCost) -> tropMul Infinity a = Infinity -tropDistrib : (a, b, c : TropCost) -> tropMul a (tropAdd b c) = tropAdd (tropMul a b) (tropMul a c) -``` - -Hardest one is distributivity — in min-plus you need `a + min(b,c) = -min(a+b, a+c)`, which requires case analysis on Nat. Use the 007 -versions as templates. - -**Also fix the standalone check failure.** File does not currently -type-check on its own. Investigate why (likely a missing import or a -dependent type that isn't reduced) before writing new theorems. -Getting it into `typed-wasm.ipkg` is the entry ticket for L11. - -**Difficulty:** medium. Bulk of the work is Nat-arithmetic case -splits. The 007 file is 333 LOC and clean, so it's a rehearsed path. - -**P0.2. Linear.idr — explicit consumption theorem.** The file says -"double-free is impossible by construction" in a comment, then -declares a nullary data type `NoDoubleFree` as a "witness". This is -documentation, not a proof. Replace with: - -``` -||| A linear handle, once consumed, cannot be consumed again. -||| This is the central safety property of Level 10. -linearConsumedOnce : (1 h : LinHandle token) -> - (after : FreeResult) -> - (freeRegion h live = after) -> - -- Cannot produce a second FreeResult from h. - Void -``` - -The exact shape depends on how you model "cannot produce" — QTT's -erased `(0 _ : X)` won't give you the negation. The cleanest approach -is a **usage-counter encoding**: - -``` -data Usage : Type where - Fresh : Usage - Consumed : Usage - -data LinHandleU : (u : Usage) -> (token : Nat) -> Type where - MkFresh : (off : Nat) -> (sid : Nat) -> LinHandleU Fresh token - -consume : LinHandleU Fresh token -> (LinHandleU Consumed token, Nat) --- then prove: no function Type -> LinHandleU Fresh token exists --- that produces a fresh handle from a consumed one. -``` - -Then prove `noReuse : LinHandleU Consumed t -> LinHandleU Fresh t -> -Void`. That is the actual theorem behind the protocol. - -**Difficulty:** medium-hard. The nullary `NoDoubleFree` needs real -witness manipulation. Budget a session. - -**P0.3. Lifetime.idr — Outlives is a preorder.** File declares -`Outlives : Lifetime -> Lifetime -> Type` as an abstract relation. The -safety of `LiveRef` depends on `Outlives` being at least reflexive and -transitive. Prove: - -``` -outlivesRefl : (l : Lifetime) -> l `Outlives` l -outlivesTrans : l1 `Outlives` l2 -> l2 `Outlives` l3 -> l1 `Outlives` l3 -``` - -Then the **load-safety theorem**, which is the actual L9 guarantee: - -``` -loadSafe : (ref : LiveRef lref a) -> - (scope : RegionLife token) -> - (p : scope `Outlives` lref) -> - -- dereferencing in this scope produces a well-typed a - a -``` - -Currently `LiveRef` extracts its offset and hopes for the best. -`loadSafe` is the proof that the hope is justified. - -**Difficulty:** medium. Depends on how `Outlives` is defined — if it's -just an opaque type, you have to add constructors first. - -**P0.4. Effects.idr — EffectSubsumes preorder + monotonicity.** -`Proofs.idr:171` shows `attestL8_EffectSafe : EffectSubsumes declared -actual -> LevelAttestation` which takes a witness and discards it. -For this attestation to mean anything, `EffectSubsumes` must be a -real preorder: - -``` -subsumeRefl : (es : List Effect) -> EffectSubsumes es es -subsumeTrans : EffectSubsumes xs ys -> EffectSubsumes ys zs -> EffectSubsumes xs zs -``` - -Plus the composition theorem — when you sequence two operations, the -combined effect set is the union and the subsumption is preserved: - -``` -subsumeCompose : EffectSubsumes d1 a1 -> EffectSubsumes d2 a2 -> - EffectSubsumes (d1 ++ d2) (a1 ++ a2) -``` - -Otherwise L8 is a fiction — a correct-looking attestation with no -content. `SubNil` is referenced in `Proofs.idr:239` but I did not -find its definition; verify it exists and strengthen it if it does -not. - -**Difficulty:** easy-medium if `EffectSubsumes` has concrete -constructors, hard if it has to be redesigned. - -**P0.5. MultiModule.idr — CompatCertificate reflexivity + transitivity -+ composition. ✅ DONE 2026-04-18 (A6).** - -The strengthened propositional layer was added to MultiModule.idr alongside -the existing data declarations (none of which were rewritten). The new -relation `ModuleCompat` is indexed by both modules *and* schemas, which -avoids the "compatCommute implicit bidirectionality" question: the schema -order pins the direction of the subschema witness. - -Proved: - -``` -compatRefl : (m : ModuleId) -> (s : Schema) -> ModuleCompat m m s s -compatTrans : ModuleCompat m1 m2 s1 s2 -> ModuleCompat m2 m3 s2 s3 - -> ModuleCompat m1 m3 s1 s3 -``` - -plus the flagship no-spoofing theorem: - -``` -noSpoofing : ModuleCompat from to imp exp - -> (f : Field) -> FieldMatches f imp - -> FieldMatches f exp -``` - -and a type-preservation corollary `noTypeSpoofing` at a known -`(name, ty)` pair. The work-horse lemma is `fieldMatchesLift : -FieldMatches f y -> SchemaSub y z -> FieldMatches f z`, which walks -the SchemaSub witness field-by-field — so the proof is not vacuous. - -Sanity-checked with a worked Rust-exports / AffineScript-imports example -(4-field export `[id: U64, age: U8, score: F32, banned: WBool]`, -2-field subset import `[id: U64, age: U8]`) that constructs a live -`ModuleCompat` certificate and applies `noSpoofing` to it. Zero -`believe_me` / `assert_total` / `postulate` / `sorry`; `%default -total` preserved. - -`compatCommute` is NOT proven because it only holds when the two -subschema relations are mutually witnessed — at that point the two -schemas are equal up to reordering and the commutativity is a -one-line corollary of `noSpoofing` in both directions. Left as -future work only if a downstream consumer actually needs it. - -**Original task description preserved for history:** File has 12 -`data` declarations describing cross-module memory compatibility. -Prove: - -``` -compatRefl : (m : ModuleId) -> Compat m m -compatTrans : Compat m1 m2 -> Compat m2 m3 -> Compat m1 m3 -compatCommute : Compat m1 m2 -> Compat m2 m1 -- if bidirectional -``` - -Plus the **no-spoofing theorem**: if `Compat m1 m2` holds, then every -region accessible from `m1` is either exported by `m1` or imported -from a module compatible with `m1`. This is the actual multi-module -memory safety invariant — the paper's killer feature. If you can -state and prove this one, typed-wasm has a real story to tell. - -**Difficulty:** hard. This is the flagship theorem. Budget multiple -sessions. Consider writing a small example multi-module program first -to sanity-check the statement before proving it. - -### P1 — Security (the parts where ceremony ≠ evidence) - -**P1.1. Replace every ceremonial attestation in `Proofs.idr` with -evidence-consuming versions. ✅ DONE 2026-04-18 (A7).** - -Every nullary attestation in `Proofs.idr` has been promoted to require -a witness from its level's proof module: - -| Attestation | Witness type | Source module | -|---|---|---| -| `attestL1_InstructionValid` | `Schema` | Region.idr | -| `attestL2_RegionBound` | `FieldIn name schema` | Region.idr | -| `attestL3_TypeCompat` | `WasmTypeCompat a b` | MultiModule.idr | -| `attestL4_NullSafe` | `Pointer.Ptr k s l NonNull` | Pointer.idr | -| `attestL5_BoundsProof` | `InBounds idx count` | Region.idr | -| `attestL6_ResultType` | `AccessResult ty` | TypedAccess.idr | -| `attestL7_AliasFree` | `ExclusiveWitness s` | Pointer.idr | -| `attestL8_EffectSafe` | `EffectSubsumes declared actual` | Effects.idr (pre-existing) | -| `attestL9_LifetimeSafe` | `Lifetime.Outlives rl sl` | Lifetime.idr | -| `attestL10_Linear` | `CompletedProtocol tok` | Linear.idr | - -`simpleReadCert`, `fullCert12`, and `fullCert15` now thread each of the -required witnesses through their signatures. The top-level certificate -cannot be constructed without a proof term for every level it claims. - -Qualification note: `Lifetime` and `Outlives` are resolved as -`Lifetime.Lifetime` / `Lifetime.Outlives` (from Lifetime.idr), while -`Pointer.Ptr`'s lifetime parameter takes `Levels.Lifetime` (which is -what Pointer.idr itself imports from Levels.idr). A small comment in -Proofs.idr explains the qualification; both `Lifetime` types remain -in the codebase for now. - -**Original task description preserved for history:** Current state: - -``` -attestL10_Linear : LevelAttestation -attestL10_Linear = MkAttestation 10 Proven -``` - -Takes no arguments — anyone can call it. Should be: - -``` -attestL10_Linear : (p : LinearProof t) -> LevelAttestation -attestL10_Linear _ = MkAttestation 10 Proven -``` - -where `LinearProof t` is a real proof-carrying type (built on P0.2). -Same treatment for `attestL9_LifetimeSafe` (should require a -`LoadSafe` witness), `attestL7_AliasFree` (should require a `Unique` -witness from Pointer.idr), `attestL3_TypeCompat`, etc. The whole -point of a certificate is that you cannot construct it without the -underlying proofs. - -**Difficulty:** mechanical once P0.1–P0.4 land. Do it immediately -after each P0 completes. - -**P1.2. Epistemic.idr — fix standalone check, then prove Level12Proof -implies freshness.** Draft-only. First make it type-check in -isolation (figure out the missing imports / unresolved variables), -then state: - -``` -Level12Proof : (writer : Commit) -> (reader : View) -> Type --- constructor requires view.timestamp >= commit.timestamp - -epistemicFreshness : Level12Proof w r -> (LTE (commitTimestamp w) (viewTimestamp r)) -``` - -Currently the existence of `Level12Proof` is waved through by -`attestL12_EpistemicFresh _ = MkAttestation 12 Proven`. As with P0.2 -and P1.1, the actual theorem has to be written down. - -**Difficulty:** medium once the file type-checks. Getting it to -type-check is the hard bit — may require understanding a design -decision that the draft obscures. - -**P1.3. Region.idr — schema injectivity. ✅ DONE 2026-04-18 (A8) — -reframed for current Schema = List Field design.** - -The original P1.3 asked for `schemaIdInjective` over a -`RegionSchema` record with a `schemaId : Nat`. That record does not -exist in the current codebase — a Schema is just a `List Field`, -identified structurally. The equivalent L2 soundness claims at the -current design are proven in Region.idr: - -``` -fieldNameInj : MkField n1 t1 = MkField n2 t2 -> n1 = n2 -fieldTypeInj : MkField n1 t1 = MkField n2 t2 -> t1 = t2 -fieldInj : MkField n1 t1 = MkField n2 t2 -> (n1 = n2, t1 = t2) -schemaEqSym : SchemaEq s1 s2 -> SchemaEq s2 s1 -schemaEqTrans : SchemaEq s1 s2 -> SchemaEq s2 s3 -> SchemaEq s1 s3 -lookupFieldName : (prf : FieldIn name schema) - -> fieldName (lookupField prf) = name -``` - -Together with the pre-existing `schemaEqRefl`, these make `SchemaEq` -a full equivalence relation and pin down "same structural identifier -implies same schema" at the Idris2 level. `lookupFieldName` closes -the L2 soundness gap: having a `FieldIn` witness guarantees the -extracted field really answers to the looked-up name. - -**Original task description preserved for history:** If two schemas have the -same `schemaId : Nat`, they are the same schema. This is required for -the L2 guarantee (region-binding) to be sound: - -``` -schemaIdInjective : (s1, s2 : RegionSchema) -> - schemaId s1 = schemaId s2 -> - s1 = s2 -``` - -Without this, an attacker can mint two schemas with the same ID and -confuse the typed-access layer. If `RegionSchema` is a record then -you need decidable equality on every field. - -**Difficulty:** easy if `RegionSchema` is simple, medium if it has -nested List/Map fields. - -### P2 — Interop (parser + round-trip, ECHIDNA coverage) - -**P2.1. Parser round-trip property.** AffineScript parser in -`lib/ocaml/Parser.affine` / `Lexer.affine` / `Ast.affine`. The ECHIDNA runs -listed in `LEVEL-STATUS.md` are for runtime L1-L6; there is no -property-based test asserting `parse (print ast) = Right ast`. Add -one. This is not an Idris2 proof — it's an ECHIDNA generator + a -fuzz run at 10^5 or higher. Until the parser is ported to Idris2, the -formal-proof version is not available, but the ECHIDNA check is cheap -and catches round-trip bugs immediately. - -**Difficulty:** easy. - -**P2.2. Parser produces well-formed modules.** Similar — state that -every successful parse yields an AST satisfying a `WellFormed` -predicate (no dangling region refs, no unbound locals, all function -indices in range). Can be an ECHIDNA predicate today and a mechanical -proof once the parser ports to Idris2. - -**Difficulty:** easy. - -### P3 — Usability / performance / versatility - -**P3.1. Erasure guarantee formalization. ✅ DONE 2026-04-18 (A9) — -parser-level + QTT witness; full `.wasm` byte-equality deferred.** - -`ProofErasureGuarantee` was a nullary `MkErasure : ProofErasureGuarantee` -sitting in `Proofs.idr` as a documentation witness only. The A9 session -landed the strongest erasure claim the current codebase can support: - - - **Parser-level property test** (`tests/echidna/echidna-harness.mjs`, - Property 5): random `.twasm` programs are textually stripped of - their `effects { ... }` clauses, both versions are parsed, and - their ASTs are asserted equal modulo the proof-only keys - `effects`, `caps`, and `loc`. Structural equality modulo those - keys demonstrates that the `effects` annotation is carried in a - separable syntactic slot — removing it does not reshape the rest - of the program. Running with `--iterations 50` currently produces - 8/8 successful pairs matching (100%). A new obligation - `effects-erasure-parser-level` is submitted to ECHIDNA alongside - the existing parser obligations. - - - **QTT-level witness in Idris2** (`TypedWasm/ABI/Proofs.idr` — - `Erases f` + `dropCertErases`): the nullary `ProofErasureGuarantee` - is kept as a legacy alias; the new per-function witness - `Erases f` forces `f`'s certificate argument to be multiplicity-0, - so constructing `MkErases f` only type-checks when the - 0-quantity discipline is preserved — at which point QTT (Brady & - Christiansen 2021) guarantees the certificate is not in the - runtime closure. `dropCertErases : Erases dropCert` is a - machine-checked instance. - -**Deferred (P3.1(a) literal byte-equality):** compiling a -proof-carrying program alongside its hand-written counterpart and -diffing the `.wasm` output is blocked pending a `.twasm`→`.wasm` -emitter. Once an emitter lands, extend Property 5 to run both -sides through the emitter and `assertBytesEqual`. The parser-level -property captures the erasability claim at the strongest scope -testable against the current toolchain. - -**Difficulty (historical):** (a) easy *given an emitter* — today it -reduces to extending Property 5 with two `emit()` calls and a byte -buffer compare; (b) done via QTT citation in the Proofs.idr header -comment. - -**P3.2. Levels progression monotonicity. ✅ DONE 2026-04-18 (A8) — -reframed for current ProgressiveCheck / ProofCertificate design.** - -The original P3.2 asked for `levelMonotone : LevelAchieved n -> LTE -m n -> LevelAchieved m` over a `LevelAchieved` predicate that does -not exist in the codebase. Under the current design, the -structural monotonicity relevant at the Idris2 level is -*composition preservation*, proven in Proofs.idr: - -``` -LevelAchievedIn : (n : Nat) -> List LevelAttestation -> Type - LAHere : LevelAchievedIn n (MkAttestation n Proven :: rest) - LAThere : LevelAchievedIn n rest -> LevelAchievedIn n (att :: rest) - -achievedAppendL : LevelAchievedIn n xs -> LevelAchievedIn n (xs ++ ys) -achievedAppendR : LevelAchievedIn n ys -> LevelAchievedIn n (xs ++ ys) - -LevelAchieved : Nat -> ProofCertificate -> Type - -- lifted from LevelAchievedIn over the certificate's attestations - -composeAchievedL : LevelAchieved n c1 -> LevelAchieved n (composeCertificates c1 c2) -composeAchievedR : LevelAchieved n c2 -> LevelAchieved n (composeCertificates c1 c2) -``` - -A level achieved in either component of a `composeCertificates` -combination is still achieved in the composition. The stronger -"progressive-order" claim — achieving level N implies all lower -levels hold — would require redesigning `ProgressiveCheck` with a -typed `level = S prevLevel` invariant. That redesign is left as -future work; the composition monotonicity above is the useful -structural claim at the current design. - -**Original task description preserved for history:** If a program achieves -Level N, it achieves all levels 1..N. Stated as: - -``` -levelMonotone : LevelAchieved n -> (m : Nat) -> LTE m n -> LevelAchieved m -``` - -Currently `ProgressiveCheck` in `Proofs.idr` sort of encodes this -operationally but does not prove the monotonicity as a theorem. - -**Difficulty:** easy once you add a `LevelAchieved` predicate. - -## What NOT to do - -- **Don't rewrite the existing files.** The data encodings are - thoughtful and the comments are valuable. Add theorems alongside - them, don't replace them. -- **Don't start from Tropical or Epistemic.** Those are the draft - files. Fix the standalone check as preliminary work but do not - pour proof effort into them until they compile. -- **Don't try to prove erasure inside Idris2** — it is a property of - the compiler, not the language. P3.1 documents the correct - approach. -- **Don't conflate structural and propositional claims.** "QTT - enforces single consumption" is a structural claim (true); "`forall - h. consumed h -> consumed h -> Void`" is a theorem (currently - unproven). The paper should distinguish these. -- **Don't add `believe_me`, `assert_total`, `postulate`, or `sorry`.** - The zero-dangerous-pattern inventory is a selling point. Preserve - it. -- **Don't reach for Lean4 or Coq.** Idris2 is the right prover for - this codebase per the estate rule (Idris2 is the preferred proof - backend). Staying in-tree keeps the proof toolchain singular. - -## Recommended session sequence - -1. **Session 1** — fix `Tropical.idr` and `Epistemic.idr` standalone - checks. Get both into `typed-wasm.ipkg`. Commit as a single - infrastructure fix. -2. **Session 2** — port TropicalSemiring axioms from 007. This is - low-risk rehearsed work and gives the proof harness a workout. -3. **Session 3** — Linear.idr consumption theorem (P0.2). This is - the real L10 guarantee. -4. **Session 4** — Lifetime.idr `Outlives` preorder + `loadSafe` - (P0.3). L9. -5. **Session 5** — Effects.idr `EffectSubsumes` preorder + compose - (P0.4). L8. -6. **Session 6** — MultiModule.idr CompatCertificate preorder + - no-spoofing theorem (P0.5). The flagship. May run long; split if - needed. -7. **Session 7** — Replace every ceremonial attestation in - `Proofs.idr` with evidence-consuming variants (P1.1). Mechanical - once P0 is done. -8. **Session 8** — Region.idr injectivity (P1.3), parser ECHIDNA - (P2.1, P2.2), Levels monotonicity (P3.2). Cleanup session. - -After each session: run `idris2 --check` on every file in -`typed-wasm.ipkg`, run `panic-attack assail` on the Rust/AffineScript -adjacent code (no new unsafe code should land), update this file's -inventory table, commit. - -## Outstanding infrastructure work — Layout module fix ✅ DONE 2026-04-18 - -**Status:** resolved in the same session it was identified. All four -`Layout.*` modules plus the `TypedWasm.ABI.Layout` bridge are back in -`typed-wasm.ipkg`, the `import TypedWasm.ABI.Layout` is restored in -`TypedWasm/ABI/Proofs.idr`, and the full 21-module ipkg builds cleanly -under Idris2 0.8.0-712523a89. - -**Fixes applied, by issue:** - -1. **Mutual recursion not declared** — wrapped `WasmHeapType` and - `WasmValType` in a single `mutual` block (and separately - `WasmValTypeValid` / `WasmGCLayoutValid` in `TypedWasm.ABI.Layout`). -2. **Visibility annotations missing** — added `public export` to every - data type, constructor, function, layout value, and `DecEq` / data - instance in `Layout/Types.idr`, `Layout/ABI.idr`, `Layout/Stdlib.idr`, - `Layout/AirborneSubmarineSquadron.idr`, and `TypedWasm/ABI/Layout.idr`. -3. **Imports missing** — added `Decidable.Equality` + `Data.List` to - `Layout/Types.idr`; `Data.List.Quantifiers` to `TypedWasm.ABI.Layout`; - `Data.List` to `Layout/AirborneSubmarineSquadron.idr`. -4. **Nested `with` block patterns** — rewrote the `DecEq WasmHeapType` - and `DecEq WasmValType` instances as four plain mutual functions - (`decEqHT`, `decEqVT`, `decEqVTList`, `decEqFields`) with thin - non-mutual interface wrappers. This sidesteps Idris2 0.8's - interface-resolution chain through `List (String, WasmValType)`. -5. **Refl-impossible patterns** — replaced `LHS impossible` clauses - with `prf = case prf of Refl impossible`. The scope change lets - Idris2 reduce the layout values after they see `public export`. -6. **Auto-bound implicit shadowing** — lowercase references to - `stringLayout`, `resultLayout`, etc. inside type signatures were - being treated as implicit pattern variables that shadowed the real - definitions. Fully qualifying as `Layout.Types.stringLayout` (and - friends) suppresses the auto-bind and lets the definitions reduce. -7. **`(x y : T)` binder syntax** — Idris2 0.8 prefers comma-separated - `(x, y : T)`; updated all affected binders. -8. **`prefix` is reserved** — renamed `SubStruct`'s `prefix` argument - to `pre` (operator fixity keyword in Idris2 0.8). -9. **Non-linear SubStruct transitivity pattern** — rewrote - `data Subtype`'s `SubStruct` constructor to carry an explicit - equality witness `prf : fs = pre ++ rest`, then proved - `subTrans` for the SubStruct/SubStruct case using `trans`, `cong`, - and `sym appendAssociative`. (The direction of - `appendAssociative : l ++ (c ++ r) = (l ++ c) ++ r` needs `sym` to - rearrange `(pre ++ rest1) ++ rest2` into `pre ++ (rest1 ++ rest2)`.) -10. **`WasmGCLayoutValid` struct-field predicate** — replaced the - `case vt of … => True` predicate (which mixed `Bool` with `Type`) - with a proper `WasmValTypeValid` inductive in a mutual block. -11. **`WasmGCEq` constructor** — replaced the over-strong - `MkGCEq : decEq h1 h2 = Yes Refl -> WasmGCEq h1 h2` with the - simpler propositional form `MkGCEq : h1 = h2 -> WasmGCEq h1 h2`. - The original encoding required a non-trivial theorem about `decEq` - to construct a reflexive witness. - -**Net result:** the aggregate-library Layout contracts (the secondary -purpose of typed-wasm, per ADR-004) are back in the ipkg alongside -the typed-wasm core, with zero `believe_me` / `assert_total` / -`postulate` / `sorry`. `%default total` preserved throughout. - -## Pre-existing notes (preserved from prior revision) - -### Template ABI Cleanup (2026-03-29) - -Template ABI removed -- was creating false impression of formal -verification. The removed files (Types.idr, Layout.idr, Foreign.idr) -contained only RSR template scaffolding with unresolved -project/author template tokens and no domain-specific proofs. diff --git a/SECURITY.adoc b/SECURITY.adoc new file mode 100644 index 0000000..e47fdd9 --- /dev/null +++ b/SECURITY.adoc @@ -0,0 +1,16 @@ +== Security Policy + +=== Reporting a Vulnerability + +If you discover a security vulnerability, please report it responsibly. + +*Email:* j.d.a.jewell@open.ac.uk + +*Please include:* - Description of the vulnerability - Steps to +reproduce - Potential impact + +*Response timeline:* - Acknowledgement within 48 hours - Initial +assessment within 7 days - Fix or mitigation within 90 days + +*Safe harbour:* We will not pursue legal action against security +researchers who follow responsible disclosure. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index 5c4d5e9..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,20 +0,0 @@ - -# Security Policy - -## Reporting a Vulnerability - -If you discover a security vulnerability, please report it responsibly. - -**Email:** j.d.a.jewell@open.ac.uk - -**Please include:** -- Description of the vulnerability -- Steps to reproduce -- Potential impact - -**Response timeline:** -- Acknowledgement within 48 hours -- Initial assessment within 7 days -- Fix or mitigation within 90 days - -**Safe harbour:** We will not pursue legal action against security researchers who follow responsible disclosure. diff --git a/TEST-NEEDS.adoc b/TEST-NEEDS.adoc new file mode 100644 index 0000000..dfbe058 --- /dev/null +++ b/TEST-NEEDS.adoc @@ -0,0 +1,158 @@ +== TEST-NEEDS: typed-wasm + +=== CRG Grade: C — ACHIEVED 2026-04-04 + +=== Current State + +[width="100%",cols="40%,26%,34%",options="header",] +|=== +|Category |Count |Details +|*Source modules* |22 |12 Idris2 ABI (Region, TypedAccess, Levels, +Pointer, Effects, Lifetime, Linear, MultiModule, Proofs, Tropical, +Epistemic, *VerifierSpec — added 2026-05-27 via PR #79* as the +spec-of-record for the Rust post-codegen verifier), 4 AffineScript +parser (Ast, Parser, Lexer, Checker), 3 Idris2 interface ABI, 2 Zig FFI ++ cache, 1 Rust verifier crate (typed-wasm-verify, ~1.6k LOC + 53 tests) + +|*Unit tests* |2 files |ParserTests.affine (88 assertions), +crates/typed-wasm-verify (43 unit + 10 cross-compat) + +|*Integration tests* |1 +|tests/contracts/airborne-step-state-contract.mjs (14 assertions) + +|*E2E tests* |2 |tests/smoke/e2e-smoke.mjs (40 assertions), +tests/e2e/e2e-driver.mjs (corpus driver) + +|*Per-level tests* |10 |tests/levels/L1.mjs .. L10.mjs (56 assertions +total) + +|*Aspect tests* |2 |tests/aspect/claim-envelope.mjs (53 assertions — +added 2026-05, bumped 49→53 in PR #60 for §8 drift detection), +tests/aspect/security-envelope.mjs (10 assertions — added 2026-05-24) + +|*Property-based tests* |1 |tests/property/property_test.mjs (29 +assertions across 6 invariants P1-P6) + +|*Proof regression* |1 |tests/proof/regression.mjs (107 named-theorem +presence assertions + optional idris2 `+--build+` layer; bumped +25→58→107 across 2026-05-24, PR #79 +33, PR #80 +49) + +|*Benchmarks* |1 |benchmarks/parser-bench.mjs (per-example wallclock; +median/p95/min/throughput; JSON summary on stderr; added 2026-05) + +|*ECHIDNA harness* |1 |tests/echidna/echidna-harness.mjs (659 LOC, 124 +local assertions, remote prover-wars submission) +|=== + +=== What’s Missing + +==== P2P Tests + +* [x] *DONE 2026-05-24*: `+tests/property/property_test.mjs+` exists +with 29 assertions across 6 invariants (parser determinism, comment +stability, diagnostic positional consistency, example-corpus liveness, +level-fixture coverage, 5-trial stability). Wired into Justfile +`+test-property+` and CI smoke job. Closes the revoked 2026-04-04 ghost +entry. +* [ ] No tests for Idris2 ABI type checking with Zig FFI +* [ ] No tests for AffineScript parser feeding into Idris2 type checker + +==== E2E Tests + +* [x] *DONE 2026-05*: `+tests/e2e/e2e-driver.mjs+` exercises every +example through parse + check with skip/expect-clean/expect-diagnostic +pragmas. Smoke test still narrow (40 assertions) but now augmented by +the per-level suite (56 more) and the aspect test (49 more). +* [ ] No WASM module compilation and execution test (blocked on codegen) +* [ ] No multi-module linking test (MultiModule.idr untested at runtime) + +==== Aspect Tests + +* [x] *DONE 2026-05*: `+tests/aspect/claim-envelope.mjs+` — 49 checks +that cross-document claims (README/ROADMAP/LEVEL-STATUS/EXPLAINME) stay +consistent with actual artefacts (ipkg, Rust constants, CI pins, example +corpus, RSR surface). Built in response to a deep audit finding five +drifts the test now catches. +* [x] *DONE 2026-05-24* (security claim-envelope dimension): +`+tests/aspect/security-envelope.mjs+` — 10 assertions covering +SECURITY.md ↔ .well-known/security.txt contact alignment, +disclosure-timeline concreteness, SPDX-header presence on all +git-tracked source files, README badge-claim-vs-reality (parses Idris2 +comments out before substring matching), no committed credential +patterns, LICENSE-vs-SPDX consistency. Caught two real bugs in the same +commit it was added: template residue in `+.well-known/security.txt+` +and missing SPDX on three files. +* [ ] *Security (behavioural)*: No memory safety violation detection +tests at the verifier-rejects-bad-program level beyond what +`+tests/levels/L*.mjs+` covers (10/10 per-level negative cases exist). +Reaching full safety-violation coverage is a Phase 1 deliverable since +it requires end-to-end codegen. +* [ ] *Performance*: see Benchmarks below +* [ ] *Concurrency*: No concurrent WASM module compilation tests +* [ ] *Error handling*: 10/10 per-level test suites +(`+tests/levels/L*.mjs+`) include negative cases — partial coverage + +==== Build & Execution + +* [x] *PARTIAL 2026-05-24*: `+tests/proof/regression.mjs+` provides +Layer 1 (named-theorem presence) — 25 assertions covering Region, +TypedAccess, Levels, Linear, Lifetime, Effects, Pointer, MultiModule, +Layout, Proofs. Catches silent theorem deletion or rename. Layer 2 +(`+idris2 --check typed-wasm.ipkg+`) runs only when idris2 is on PATH, +falls back to skip otherwise; pass `+--strict+` to require idris2. The +strong test still depends on the toolchain being installable in CI, +which is its own Phase 0 item. +* [ ] Zig FFI integration_test.zig likely a template placeholder + +==== Benchmarks + +* [x] *DONE 2026-05*: `+benchmarks/parser-bench.mjs+` — per-example +parse + check wallclock with median / p95 / min / throughput and JSON +summary for trend tracking. Only the parser is end-to-end today, so +that’s where benchmark evidence has to start. +* [ ] Type-checking overhead per WASM instruction (blocked on codegen + +Zig FFI runtime path) +* [ ] Memory region tracking performance (blocked on codegen) +* [ ] Lifetime analysis scaling with module size (blocked on codegen) +* [ ] Comparison: typed-wasm overhead vs raw WASM execution (blocked on +codegen) + +==== Self-Tests + +* [ ] No type system self-consistency check + +=== FLAGGED ISSUES + +* *Type safety system with no safety-level-specific tests* – 10 levels +claimed, 0 level-specific test suites (IN PROGRESS 2026-04-18 — L1-L3 +pilot + agent handoff for L4-L10) +* *11 Idris2 proof modules with 0 proof verification tests* – "`proven`" +is unproven. Update 2026-04-18: A3-A9 theorems landed in commits +987930c, c896a44, 3097b50, 9ebe867 (injectivity, level-achievement +monotonicity, erasure P3.1, QTT witness, witness-requiring +attestations). L7-L10 preorder + composition lemmas now live. Full +per-level Idris2 test files still absent. +* *Tropical.idr and Epistemic.idr (novel type features) have 0 tests* – +research features untested (L11 semiring closure proven A2 2026-04-18 +but no dedicated test suite) +* [line-through]#*ECHIDNA harness is 7 assertions* – token gesture, not +real verification# SUPERSEDED 2026-04-18: +tests/echidna/echidna-harness.mjs is now 659 LOC with a random-program +generator, 36 proof obligations per run, and parse-rate measurement. +* *arXiv potential claimed* – paper-worthy claims need paper-worthy +evidence + +=== Priority: P0 (CRITICAL) + +=== FAKE-FUZZ ALERT — RESOLVED 2026-04-18 + +* [line-through]#`+tests/fuzz/placeholder.txt+` is a scorecard +placeholder inherited from rsr-template-repo — it does NOT provide real +fuzz testing# RESOLVED. The placeholder file is gone; +`+tests/fuzz/README.adoc+` is now an honest status marker pointing at +`+tests/echidna/echidna-harness.mjs+` (659 LOC, real random-program +fuzz) and `+ffi/zig/test/+`. A dedicated retained fuzz corpus is still +future work. +* Replace with an actual fuzz harness (see +rsr-template-repo/tests/fuzz/README.adoc) or remove the file +* Priority: P2 — creates false impression of fuzz coverage diff --git a/TEST-NEEDS.md b/TEST-NEEDS.md deleted file mode 100644 index 7746170..0000000 --- a/TEST-NEEDS.md +++ /dev/null @@ -1,104 +0,0 @@ -# TEST-NEEDS: typed-wasm - -## CRG Grade: C — ACHIEVED 2026-04-04 - -## Current State - -| Category | Count | Details | -|----------|-------|---------| -| **Source modules** | 22 | 12 Idris2 ABI (Region, TypedAccess, Levels, Pointer, Effects, Lifetime, Linear, MultiModule, Proofs, Tropical, Epistemic, **VerifierSpec — added 2026-05-27 via PR #79** as the spec-of-record for the Rust post-codegen verifier), 4 AffineScript parser (Ast, Parser, Lexer, Checker), 3 Idris2 interface ABI, 2 Zig FFI + cache, 1 Rust verifier crate (typed-wasm-verify, ~1.6k LOC + 53 tests) | -| **Unit tests** | 2 files | ParserTests.affine (88 assertions), crates/typed-wasm-verify (43 unit + 10 cross-compat) | -| **Integration tests** | 1 | tests/contracts/airborne-step-state-contract.mjs (14 assertions) | -| **E2E tests** | 2 | tests/smoke/e2e-smoke.mjs (40 assertions), tests/e2e/e2e-driver.mjs (corpus driver) | -| **Per-level tests** | 10 | tests/levels/L1.mjs .. L10.mjs (56 assertions total) | -| **Aspect tests** | 2 | tests/aspect/claim-envelope.mjs (53 assertions — added 2026-05, bumped 49→53 in PR #60 for §8 drift detection), tests/aspect/security-envelope.mjs (10 assertions — added 2026-05-24) | -| **Property-based tests** | 1 | tests/property/property_test.mjs (29 assertions across 6 invariants P1-P6) | -| **Proof regression** | 1 | tests/proof/regression.mjs (107 named-theorem presence assertions + optional idris2 `--build` layer; bumped 25→58→107 across 2026-05-24, PR #79 +33, PR #80 +49) | -| **Benchmarks** | 1 | benchmarks/parser-bench.mjs (per-example wallclock; median/p95/min/throughput; JSON summary on stderr; added 2026-05) | -| **ECHIDNA harness** | 1 | tests/echidna/echidna-harness.mjs (659 LOC, 124 local assertions, remote prover-wars submission) | - -## What's Missing - -### P2P Tests -- [x] **DONE 2026-05-24**: `tests/property/property_test.mjs` exists with - 29 assertions across 6 invariants (parser determinism, comment - stability, diagnostic positional consistency, example-corpus - liveness, level-fixture coverage, 5-trial stability). Wired into - Justfile `test-property` and CI smoke job. Closes the revoked - 2026-04-04 ghost entry. -- [ ] No tests for Idris2 ABI type checking with Zig FFI -- [ ] No tests for AffineScript parser feeding into Idris2 type checker - -### E2E Tests -- [x] **DONE 2026-05**: `tests/e2e/e2e-driver.mjs` exercises every - example through parse + check with skip/expect-clean/expect-diagnostic - pragmas. Smoke test still narrow (40 assertions) but now augmented - by the per-level suite (56 more) and the aspect test (49 more). -- [ ] No WASM module compilation and execution test (blocked on codegen) -- [ ] No multi-module linking test (MultiModule.idr untested at runtime) - -### Aspect Tests -- [x] **DONE 2026-05**: `tests/aspect/claim-envelope.mjs` — 49 checks that - cross-document claims (README/ROADMAP/LEVEL-STATUS/EXPLAINME) stay - consistent with actual artefacts (ipkg, Rust constants, CI pins, - example corpus, RSR surface). Built in response to a deep audit - finding five drifts the test now catches. -- [x] **DONE 2026-05-24** (security claim-envelope dimension): - `tests/aspect/security-envelope.mjs` — 10 assertions covering - SECURITY.md ↔ .well-known/security.txt contact alignment, - disclosure-timeline concreteness, SPDX-header presence on all - git-tracked source files, README badge-claim-vs-reality (parses - Idris2 comments out before substring matching), no committed - credential patterns, LICENSE-vs-SPDX consistency. Caught two real - bugs in the same commit it was added: template residue in - `.well-known/security.txt` and missing SPDX on three files. -- [ ] **Security (behavioural)**: No memory safety violation detection - tests at the verifier-rejects-bad-program level beyond what - `tests/levels/L*.mjs` covers (10/10 per-level negative cases - exist). Reaching full safety-violation coverage is a Phase 1 - deliverable since it requires end-to-end codegen. -- [ ] **Performance**: see Benchmarks below -- [ ] **Concurrency**: No concurrent WASM module compilation tests -- [ ] **Error handling**: 10/10 per-level test suites (`tests/levels/L*.mjs`) - include negative cases — partial coverage - -### Build & Execution -- [x] **PARTIAL 2026-05-24**: `tests/proof/regression.mjs` provides - Layer 1 (named-theorem presence) — 25 assertions covering Region, - TypedAccess, Levels, Linear, Lifetime, Effects, Pointer, - MultiModule, Layout, Proofs. Catches silent theorem deletion or - rename. Layer 2 (`idris2 --check typed-wasm.ipkg`) runs only when - idris2 is on PATH, falls back to skip otherwise; pass `--strict` - to require idris2. The strong test still depends on the toolchain - being installable in CI, which is its own Phase 0 item. -- [ ] Zig FFI integration_test.zig likely a template placeholder - -### Benchmarks -- [x] **DONE 2026-05**: `benchmarks/parser-bench.mjs` — per-example parse + - check wallclock with median / p95 / min / throughput and JSON summary - for trend tracking. Only the parser is end-to-end today, so that's - where benchmark evidence has to start. -- [ ] Type-checking overhead per WASM instruction (blocked on codegen + - Zig FFI runtime path) -- [ ] Memory region tracking performance (blocked on codegen) -- [ ] Lifetime analysis scaling with module size (blocked on codegen) -- [ ] Comparison: typed-wasm overhead vs raw WASM execution - (blocked on codegen) - -### Self-Tests -- [ ] No type system self-consistency check - -## FLAGGED ISSUES -- **Type safety system with no safety-level-specific tests** -- 10 levels claimed, 0 level-specific test suites (IN PROGRESS 2026-04-18 — L1-L3 pilot + agent handoff for L4-L10) -- **11 Idris2 proof modules with 0 proof verification tests** -- "proven" is unproven. Update 2026-04-18: A3-A9 theorems landed in commits 987930c, c896a44, 3097b50, 9ebe867 (injectivity, level-achievement monotonicity, erasure P3.1, QTT witness, witness-requiring attestations). L7-L10 preorder + composition lemmas now live. Full per-level Idris2 test files still absent. -- **Tropical.idr and Epistemic.idr (novel type features) have 0 tests** -- research features untested (L11 semiring closure proven A2 2026-04-18 but no dedicated test suite) -- ~~**ECHIDNA harness is 7 assertions** -- token gesture, not real verification~~ SUPERSEDED 2026-04-18: tests/echidna/echidna-harness.mjs is now 659 LOC with a random-program generator, 36 proof obligations per run, and parse-rate measurement. -- **arXiv potential claimed** -- paper-worthy claims need paper-worthy evidence - -## Priority: P0 (CRITICAL) - -## FAKE-FUZZ ALERT — RESOLVED 2026-04-18 - -- ~~`tests/fuzz/placeholder.txt` is a scorecard placeholder inherited from rsr-template-repo — it does NOT provide real fuzz testing~~ RESOLVED. The placeholder file is gone; `tests/fuzz/README.adoc` is now an honest status marker pointing at `tests/echidna/echidna-harness.mjs` (659 LOC, real random-program fuzz) and `ffi/zig/test/`. A dedicated retained fuzz corpus is still future work. -- Replace with an actual fuzz harness (see rsr-template-repo/tests/fuzz/README.adoc) or remove the file -- Priority: P2 — creates false impression of fuzz coverage diff --git a/crates/typed-wasm-codegen/README.adoc b/crates/typed-wasm-codegen/README.adoc new file mode 100644 index 0000000..01a25f8 --- /dev/null +++ b/crates/typed-wasm-codegen/README.adoc @@ -0,0 +1,94 @@ +== typed-wasm-codegen + +The first in-tree `+.twasm → .wasm+` *producer* (codegen *v0*). + +Before this crate the toolchain stopped at +`+source → Lexer → Parser → Checker → diagnostics+`; the only wasm-aware +code was the _verifier_ (`+typed-wasm-verify+`). This crate closes Phase +0’s gate 2 (issue #48) and seeds Phase 1 (issue #49, deliverable 1). + +=== What it does + +Lowers a typed region IR (link:src/lib.rs[`+Module+`]) to: + +* a *well-formed wasm module* (linear memory + type-correct function +bodies), and +* the L2–L6 carrier sections *`+typedwasm.regions+`* (ADR-0002) and +*`+typedwasm.access-sites+`* (ADR-0003), + +using `+typed-wasm-verify+`’s _own_ carrier encoders, so the emitted +bytes cannot drift from the decoder the verifier runs. The output +round-trips through `+verify_from_module+` + +`+verify_access_sites_from_module+` in-process — see +`+tests/roundtrip.rs+`. + +It also emits *multi-module* pairs — a Linear-exporting callee (with a +`+typedwasm.ownership+` carrier) and an importing caller — that +round-trip through `+extract_exports+` + `+verify_cross_module+` (#128); +see `+tests/multimodule.rs+`. + +=== Usage + +[source,sh] +---- +# build the example to wasm +cargo run -p typed-wasm-codegen --bin tw -- build examples/01-single-module.twasm -o /tmp/ex01.wasm + +# emit the WAT (text) debug view, or both binary + text +cargo run -p typed-wasm-codegen --bin tw -- build examples/01-single-module.twasm -o /tmp/ex01 --emit wat +cargo run -p typed-wasm-codegen --bin tw -- build examples/01-single-module.twasm -o /tmp/ex01 --emit both + +# the round-trip + WAT tests (emit → validate → verify) +cargo test -p typed-wasm-codegen +---- + +=== Scope of v0 (see `+docs/decisions/0004-codegen-host-language.adoc+`) + +[width="100%",cols="50%,50%",options="header",] +|=== +|Aspect |v0 status +|Host language / location |Rust crate, sibling of `+typed-wasm-verify+`, +emits via `+wasm-encoder+` + +|Front-end (`+.twasm+`) → IR |*in-process Rust parser* +(`+src/parser.rs+`) — all six `+examples/*.twasm+` parse → emit → verify +(`+tests/corpus.rs+`), incl. ownership qualifiers → +`+typedwasm.ownership+` (ADR-0006) + +|`+typedwasm.regions+` + `+typedwasm.access-sites+` |*emitted*, +verifier-accepted + +|WAT (text) emission |*emitted* via `+--emit wat\|both+` (#125) + +|`+typedwasm.ownership+` (L7/L10) |*emitted* for any +`+own+`/`+&mut+`/`+&+` source discipline (parser-recorded, incl. Linear +returns) and for the multi-module callee (#128) + +|Multi-module (linear boundary) |*emitted* — callee export + caller +import round-trip through `+verify_cross_module+` (#128) + +|Function-body lowering |*real statement lowering* — `+let+`, +assignment, `+if+`/`+else+`, `+while+`, indexed access, `+cast<>+`, +`+region.scan … -> \|e\| { … }+` with `+where+` predicates, +`+is_null+`/`+opt+` (v0 null = 0) — wasmi-executed +(`+tests/example04.rs+`, `+tests/scan_lowering.rs+`); remaining stubs: +handle-typed locals, embedded-region paths +|=== + +=== Where this goes next + +* *#127* — codegen coverage across all 10 levels × all 6 examples (and +the front-end → IR JSON seam). +* *#130* — promote the round-trip tests into the ECHIDNA property +corpus. +* *Per-module split* — *done*: `+module Name { … }+` blocks parse into +separate modules (`+parse_modules+`; importers seeded with the +producer’s actual schema), `+tw build --split+` emits one wasm per +module, `+tw link+` certifies the graph (`+tests/multimodule_split.rs+`, +`+tests/fixtures/multimodule/game.twasm+`). +* *L13 positive-form / region-imports* — *done* (issue #140): +`+import region … from "…" { … }+` parses into +`+Module::region_imports+`, emits the `+typedwasm.region-imports+` +carrier (proposal 0003 `+[accepted]+` / ADR-0007), and +`+verify_link_graph+` certifies cross-module schema agreement +(`+tests/example02.rs+`). diff --git a/crates/typed-wasm-codegen/README.md b/crates/typed-wasm-codegen/README.md deleted file mode 100644 index 7f8cb41..0000000 --- a/crates/typed-wasm-codegen/README.md +++ /dev/null @@ -1,62 +0,0 @@ - - -# typed-wasm-codegen - -The first in-tree `.twasm → .wasm` **producer** (codegen **v0**). - -Before this crate the toolchain stopped at `source → Lexer → Parser → -Checker → diagnostics`; the only wasm-aware code was the *verifier* -(`typed-wasm-verify`). This crate closes Phase 0's gate 2 (issue #48) and -seeds Phase 1 (issue #49, deliverable 1). - -## What it does - -Lowers a typed region IR ([`Module`](src/lib.rs)) to: - -- a **well-formed wasm module** (linear memory + type-correct function - bodies), and -- the L2–L6 carrier sections **`typedwasm.regions`** (ADR-0002) and - **`typedwasm.access-sites`** (ADR-0003), - -using `typed-wasm-verify`'s *own* carrier encoders, so the emitted bytes -cannot drift from the decoder the verifier runs. The output round-trips -through `verify_from_module` + `verify_access_sites_from_module` -in-process — see `tests/roundtrip.rs`. - -It also emits **multi-module** pairs — a Linear-exporting callee (with a -`typedwasm.ownership` carrier) and an importing caller — that round-trip -through `extract_exports` + `verify_cross_module` (#128); see -`tests/multimodule.rs`. - -## Usage - -```sh -# build the example to wasm -cargo run -p typed-wasm-codegen --bin tw -- build examples/01-single-module.twasm -o /tmp/ex01.wasm - -# emit the WAT (text) debug view, or both binary + text -cargo run -p typed-wasm-codegen --bin tw -- build examples/01-single-module.twasm -o /tmp/ex01 --emit wat -cargo run -p typed-wasm-codegen --bin tw -- build examples/01-single-module.twasm -o /tmp/ex01 --emit both - -# the round-trip + WAT tests (emit → validate → verify) -cargo test -p typed-wasm-codegen -``` - -## Scope of v0 (see `docs/decisions/0004-codegen-host-language.adoc`) - -| Aspect | v0 status | -|---|---| -| Host language / location | Rust crate, sibling of `typed-wasm-verify`, emits via `wasm-encoder` | -| Front-end (`.twasm`) → IR | **in-process Rust parser** (`src/parser.rs`) — all six `examples/*.twasm` parse → emit → verify (`tests/corpus.rs`), incl. ownership qualifiers → `typedwasm.ownership` (ADR-0006) | -| `typedwasm.regions` + `typedwasm.access-sites` | **emitted**, verifier-accepted | -| WAT (text) emission | **emitted** via `--emit wat\|both` (#125) | -| `typedwasm.ownership` (L7/L10) | **emitted** for any `own`/`&mut`/`&` source discipline (parser-recorded, incl. Linear returns) and for the multi-module callee (#128) | -| Multi-module (linear boundary) | **emitted** — callee export + caller import round-trip through `verify_cross_module` (#128) | -| Function-body lowering | **real statement lowering** — `let`, assignment, `if`/`else`, `while`, indexed access, `cast<>`, `region.scan … -> \|e\| { … }` with `where` predicates, `is_null`/`opt` (v0 null = 0) — wasmi-executed (`tests/example04.rs`, `tests/scan_lowering.rs`); remaining stubs: handle-typed locals, embedded-region paths | - -## Where this goes next - -- **#127** — codegen coverage across all 10 levels × all 6 examples (and the front-end → IR JSON seam). -- **#130** — promote the round-trip tests into the ECHIDNA property corpus. -- **Per-module split** — **done**: `module Name { … }` blocks parse into separate modules (`parse_modules`; importers seeded with the producer's actual schema), `tw build --split` emits one wasm per module, `tw link` certifies the graph (`tests/multimodule_split.rs`, `tests/fixtures/multimodule/game.twasm`). -- **L13 positive-form / region-imports** — **done** (issue #140): `import region … from "…" { … }` parses into `Module::region_imports`, emits the `typedwasm.region-imports` carrier (proposal 0003 `[accepted]` / ADR-0007), and `verify_link_graph` certifies cross-module schema agreement (`tests/example02.rs`). diff --git a/crates/typed-wasm-gate/README.adoc b/crates/typed-wasm-gate/README.adoc new file mode 100644 index 0000000..8cc5501 --- /dev/null +++ b/crates/typed-wasm-gate/README.adoc @@ -0,0 +1,25 @@ +== typed-wasm-gate + +Load-time enforcement for typed-wasm — the Phase 3 slice (runtime-side +enforcement). Build-time verification trusts whoever ran the build; the +gate moves the trust boundary to the *loader*: + +[source,rust] +---- +let verified = typed_wasm_gate::gate_module(&bytes)?; // full verifier stack +let instance = wasmi_runtime::instantiate_verified(&engine, &mut store, &linker, &verified)?; +---- + +`+VerifiedModule+` is a witness type: its only constructors are +`+gate_module+` / `+gate_link_graph+`, which run structural validation, +L7/L10 ownership/linearity, L2 carrier bounds + access typing, and L13 +region-import consistency (plus cross-module `+SchemaSub+` certification +for graphs, ADR-0007). The instantiation adapters accept only +`+&VerifiedModule+` — a violating module cannot reach a runtime through +this API because its witness never exists. + +The gate itself is runtime-agnostic (bytes in, witness + `+GateReport+` +out). The `+wasmi-runtime+` feature (default) ships a pure-Rust +in-process adapter that CI executes end-to-end; a *wasmtime adapter* is +the intended follow-up and needs nothing beyond what the wasmi one uses +— compile the module from `+VerifiedModule::bytes()+` and instantiate. diff --git a/crates/typed-wasm-gate/README.md b/crates/typed-wasm-gate/README.md deleted file mode 100644 index 85e1c1b..0000000 --- a/crates/typed-wasm-gate/README.md +++ /dev/null @@ -1,26 +0,0 @@ - - -# typed-wasm-gate - -Load-time enforcement for typed-wasm — the Phase 3 slice (runtime-side -enforcement). Build-time verification trusts whoever ran the build; the -gate moves the trust boundary to the **loader**: - -```rust -let verified = typed_wasm_gate::gate_module(&bytes)?; // full verifier stack -let instance = wasmi_runtime::instantiate_verified(&engine, &mut store, &linker, &verified)?; -``` - -`VerifiedModule` is a witness type: its only constructors are -`gate_module` / `gate_link_graph`, which run structural validation, -L7/L10 ownership/linearity, L2 carrier bounds + access typing, and L13 -region-import consistency (plus cross-module `SchemaSub` certification -for graphs, ADR-0007). The instantiation adapters accept only -`&VerifiedModule` — a violating module cannot reach a runtime through -this API because its witness never exists. - -The gate itself is runtime-agnostic (bytes in, witness + `GateReport` -out). The `wasmi-runtime` feature (default) ships a pure-Rust in-process -adapter that CI executes end-to-end; a **wasmtime adapter** is the -intended follow-up and needs nothing beyond what the wasmi one uses — -compile the module from `VerifiedModule::bytes()` and instantiate. diff --git a/crates/typed-wasm-verify/README.adoc b/crates/typed-wasm-verify/README.adoc new file mode 100644 index 0000000..04d98d7 --- /dev/null +++ b/crates/typed-wasm-verify/README.adoc @@ -0,0 +1,70 @@ +== typed-wasm-verify + +Post-codegen verifier for typed-wasm *L7 (aliasing safety)* and *L10 +(linearity)* constraints on emitted wasm modules. + +=== What it does + +Given a wasm module that carries an `+typedwasm.ownership+` custom +section, this crate: + +[arabic] +. *Intra-function check* — walks every function body and computes +per-path `+(min_uses, max_uses)+` for each parameter. Linear params must +be `+(1, 1)+` on every path; ExclBorrow params must have +`+max_uses ≤ 1+`. +. *Cross-module check* — given a callee’s exported ownership interface +plus a caller module that imports those functions, verifies that +Linear-param imports are invoked exactly once per execution path. + +The custom-section binary format: + +.... +u32le count +for each entry: + u32le func_idx + u8 n_params + u8[n] param_kinds (0=Unrestricted, 1=Linear, 2=SharedBorrow, 3=ExclBorrow) + u8 ret_kind +.... + +=== Spec of record + +*This crate + the Idris2 `+VerifierSpec.idr+` ARE the spec of record* +(ADR-0008, 2026-07-07). The crate began as a Rust port of +`+hyperpolymath/affinescript+`’s `+lib/tw_verify.ml+` / +`+lib/tw_interface.ml+`; the parity criterion those files were pinned +behind (workspace task C5) was met by `+tests/cross_compat.rs+` +(synthetic table) + `+tests/cross_compat_real.rs+` (real producer +bytes), and the crate has since grown past the OCaml reference (L13 both +forms, L2/L15 carriers, link-graph certification, third-producer +conformance). The OCaml files are a conforming implementation; on +divergence, they are presumed wrong unless +`+src/abi/TypedWasm/ABI/VerifierSpec.idr+` says otherwise. + +=== Consumers + +* `+hyperpolymath/ephapax+` — calls into this crate as a Cargo +dependency to verify its compile-eph output. +* `+hyperpolymath/affinescript+` — invokes the built binary as a +subprocess, eventually replacing its OCaml verifier. +* *Third producer (Zig)* — `+ffi/zig/src/twasm_producer.zig+` +hand-assembles wasm + the ownership carrier with no shared code; its +committed fixtures (`+tests/fixtures/zig_producer/+`) are the +producer-neutrality proof (`+tests/third_producer_zig.rs+`). + +=== Status + +* [x] C1 — Scaffold (types, error enums, public entry stubs) +* [x] C2 — Custom-section parser (`+src/section.rs+`) +* [x] C3 — Per-path use-range analysis (L7+L10 intra-function, +`+src/verify.rs+`; includes L13 negative-form module isolation) +* [x] C4 — Cross-module boundary verifier (`+src/cross.rs+`) +* [x] C5 — Cross-compat test against affinescript-emitted wasm +(`+tests/cross_compat.rs+` synthetic parity table + +`+tests/cross_compat_real.rs+` real fixtures under +`+tests/fixtures/c5_real/+`) + +Still open: L13 positive-form region-imports agreement (typed-wasm#140, +proposal 0003) and carrier-backed L2–L6/L15 passes graduating from the +`+unstable-l2+`/`+unstable-l15+` features. diff --git a/crates/typed-wasm-verify/README.md b/crates/typed-wasm-verify/README.md deleted file mode 100644 index 09c8a64..0000000 --- a/crates/typed-wasm-verify/README.md +++ /dev/null @@ -1,43 +0,0 @@ - - -# typed-wasm-verify - -Post-codegen verifier for typed-wasm **L7 (aliasing safety)** and **L10 (linearity)** constraints on emitted wasm modules. - -## What it does - -Given a wasm module that carries an `typedwasm.ownership` custom section, this crate: - -1. **Intra-function check** — walks every function body and computes per-path `(min_uses, max_uses)` for each parameter. Linear params must be `(1, 1)` on every path; ExclBorrow params must have `max_uses ≤ 1`. -2. **Cross-module check** — given a callee's exported ownership interface plus a caller module that imports those functions, verifies that Linear-param imports are invoked exactly once per execution path. - -The custom-section binary format: - -``` -u32le count -for each entry: - u32le func_idx - u8 n_params - u8[n] param_kinds (0=Unrestricted, 1=Linear, 2=SharedBorrow, 3=ExclBorrow) - u8 ret_kind -``` - -## Spec of record - -**This crate + the Idris2 `VerifierSpec.idr` ARE the spec of record** (ADR-0008, 2026-07-07). The crate began as a Rust port of `hyperpolymath/affinescript`'s `lib/tw_verify.ml` / `lib/tw_interface.ml`; the parity criterion those files were pinned behind (workspace task C5) was met by `tests/cross_compat.rs` (synthetic table) + `tests/cross_compat_real.rs` (real producer bytes), and the crate has since grown past the OCaml reference (L13 both forms, L2/L15 carriers, link-graph certification, third-producer conformance). The OCaml files are a conforming implementation; on divergence, they are presumed wrong unless `src/abi/TypedWasm/ABI/VerifierSpec.idr` says otherwise. - -## Consumers - -- `hyperpolymath/ephapax` — calls into this crate as a Cargo dependency to verify its compile-eph output. -- `hyperpolymath/affinescript` — invokes the built binary as a subprocess, eventually replacing its OCaml verifier. -- **Third producer (Zig)** — `ffi/zig/src/twasm_producer.zig` hand-assembles wasm + the ownership carrier with no shared code; its committed fixtures (`tests/fixtures/zig_producer/`) are the producer-neutrality proof (`tests/third_producer_zig.rs`). - -## Status - -- [x] C1 — Scaffold (types, error enums, public entry stubs) -- [x] C2 — Custom-section parser (`src/section.rs`) -- [x] C3 — Per-path use-range analysis (L7+L10 intra-function, `src/verify.rs`; includes L13 negative-form module isolation) -- [x] C4 — Cross-module boundary verifier (`src/cross.rs`) -- [x] C5 — Cross-compat test against affinescript-emitted wasm (`tests/cross_compat.rs` synthetic parity table + `tests/cross_compat_real.rs` real fixtures under `tests/fixtures/c5_real/`) - -Still open: L13 positive-form region-imports agreement (typed-wasm#140, proposal 0003) and carrier-backed L2–L6/L15 passes graduating from the `unstable-l2`/`unstable-l15` features. diff --git a/crates/typed-wasm-verify/tests/fixtures/producer_pair/README.adoc b/crates/typed-wasm-verify/tests/fixtures/producer_pair/README.adoc new file mode 100644 index 0000000..d4ddc1e --- /dev/null +++ b/crates/typed-wasm-verify/tests/fixtures/producer_pair/README.adoc @@ -0,0 +1,35 @@ +== producer_pair fixtures — producer-emitted cross-module ownership boundary + +The producer-emitted callee/caller differential pair issue #140 asked +for: `+typed-wasm-codegen+`’s `+multimodule_callee()+` / +`+multimodule_caller(n)+` IR emitted to real bytes and committed, +exercised by `+tests/producer_pair.rs+` against `+extract_exports+` + +`+verify_cross_module+`. + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|File |Content |Expected verdict +|`+callee.wasm+` |exports `+consume(x: Linear)+` with an ownership +carrier |interface extracts: `+[Linear] → Unrestricted+` + +|`+caller_ok.wasm+` |imports `+consume+`, calls it exactly once +|*accepted* + +|`+caller_double.wasm+` |imports `+consume+`, calls it twice |*rejected* +(`+LinearImportCalledMultiple+`) +|=== + +Captured 2026-07-07. Regenerate after producer changes with the one-shot +generator (deterministic — an unchanged producer regenerates +byte-identical files): + +[source,bash] +---- +cargo run -p typed-wasm-codegen --example gen_producer_pair # (recreate from git history if pruned) +---- + +The in-crate parity oracle remains +`+typed-wasm-codegen/tests/multimodule.rs+`; this pair pins the emitted +*bytes* so byte-level drift in either the producer or the verifier shows +up as a fixture diff, mirroring `+c5_real/+` (AffineScript) and +`+zig_producer/+` (Zig). diff --git a/crates/typed-wasm-verify/tests/fixtures/producer_pair/README.md b/crates/typed-wasm-verify/tests/fixtures/producer_pair/README.md deleted file mode 100644 index 7249542..0000000 --- a/crates/typed-wasm-verify/tests/fixtures/producer_pair/README.md +++ /dev/null @@ -1,27 +0,0 @@ - - -# producer_pair fixtures — producer-emitted cross-module ownership boundary - -The producer-emitted callee/caller differential pair issue #140 asked -for: `typed-wasm-codegen`'s `multimodule_callee()` / `multimodule_caller(n)` -IR emitted to real bytes and committed, exercised by -`tests/producer_pair.rs` against `extract_exports` + `verify_cross_module`. - -| File | Content | Expected verdict | -|---|---|---| -| `callee.wasm` | exports `consume(x: Linear)` with an ownership carrier | interface extracts: `[Linear] → Unrestricted` | -| `caller_ok.wasm` | imports `consume`, calls it exactly once | **accepted** | -| `caller_double.wasm` | imports `consume`, calls it twice | **rejected** (`LinearImportCalledMultiple`) | - -Captured 2026-07-07. Regenerate after producer changes with the -one-shot generator (deterministic — an unchanged producer regenerates -byte-identical files): - -```bash -cargo run -p typed-wasm-codegen --example gen_producer_pair # (recreate from git history if pruned) -``` - -The in-crate parity oracle remains `typed-wasm-codegen/tests/multimodule.rs`; -this pair pins the emitted **bytes** so byte-level drift in either the -producer or the verifier shows up as a fixture diff, mirroring -`c5_real/` (AffineScript) and `zig_producer/` (Zig). diff --git a/crates/typed-wasm-verify/tests/fixtures/zig_producer/README.adoc b/crates/typed-wasm-verify/tests/fixtures/zig_producer/README.adoc new file mode 100644 index 0000000..3f6f8d0 --- /dev/null +++ b/crates/typed-wasm-verify/tests/fixtures/zig_producer/README.adoc @@ -0,0 +1,29 @@ +== zig_producer fixtures — the third `+typedwasm.ownership+` producer + +Wasm modules hand-assembled byte-by-byte by +`+ffi/zig/src/twasm_producer.zig+` — a producer sharing *no ancestry* +with AffineScript (OCaml), Ephapax (Rust), or the in-tree Rust codegen. +Their acceptance/rejection by `+typed-wasm-verify+` +(`+tests/third_producer_zig.rs+`) demonstrates the carrier contract is +producer-neutral: any toolchain in any language that writes the +documented bytes participates in L7/L10 verification. + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|File |Body of `+consume(x: Linear i32)+` |Expected verdict +|`+zig_clean_linear.wasm+` |`+local.get 0; drop+` (once) |*accepted* + +|`+zig_double_use.wasm+` |`+local.get 0; drop+` twice |*rejected* +(`+UsedMoreThanOnce+` — a wasm-level double-free) +|=== + +Captured 2026-07-07 with Zig 0.15.2. Regenerate after changing the +generator with: + +[source,bash] +---- +cd ffi/zig && zig build gen-fixtures +---- + +The generator is deterministic (asserted by its own `+zig build test+` +suite), so a regeneration with an unchanged generator is byte-identical. diff --git a/crates/typed-wasm-verify/tests/fixtures/zig_producer/README.md b/crates/typed-wasm-verify/tests/fixtures/zig_producer/README.md deleted file mode 100644 index a0bd7da..0000000 --- a/crates/typed-wasm-verify/tests/fixtures/zig_producer/README.md +++ /dev/null @@ -1,26 +0,0 @@ - - -# zig_producer fixtures — the third `typedwasm.ownership` producer - -Wasm modules hand-assembled byte-by-byte by -`ffi/zig/src/twasm_producer.zig` — a producer sharing **no ancestry** -with AffineScript (OCaml), Ephapax (Rust), or the in-tree Rust codegen. -Their acceptance/rejection by `typed-wasm-verify` -(`tests/third_producer_zig.rs`) demonstrates the carrier contract is -producer-neutral: any toolchain in any language that writes the -documented bytes participates in L7/L10 verification. - -| File | Body of `consume(x: Linear i32)` | Expected verdict | -|---|---|---| -| `zig_clean_linear.wasm` | `local.get 0; drop` (once) | **accepted** | -| `zig_double_use.wasm` | `local.get 0; drop` twice | **rejected** (`UsedMoreThanOnce` — a wasm-level double-free) | - -Captured 2026-07-07 with Zig 0.15.2. Regenerate after changing the -generator with: - -```bash -cd ffi/zig && zig build gen-fixtures -``` - -The generator is deterministic (asserted by its own `zig build test` -suite), so a regeneration with an unchanged generator is byte-identical. diff --git a/docs/WHITEPAPER.adoc b/docs/WHITEPAPER.adoc new file mode 100644 index 0000000..1e90297 --- /dev/null +++ b/docs/WHITEPAPER.adoc @@ -0,0 +1,765 @@ +== typed-wasm: Applying Database Query Type Safety to WebAssembly Linear Memory + +*Jonathan D.A. Jewell* The Open University, Milton Keynes, UK +`+j.d.a.jewell@open.ac.uk+` + +*Draft — March 2026* + +''''' + +*Keywords:* WebAssembly, type safety, dependent types, linear memory, +multi-module verification, quantitative type theory, memory safety + +*Categories:* D.3.1 [Programming Languages]: Formal Definitions and +Theory; D.2.4 [Software Engineering]: Software/Program Verification; +F.3.1 [Logics and Meanings of Programs]: Specifying and Verifying +Programs + +''''' + +=== Abstract + +WebAssembly (Wasm) linear memory is an untyped byte array shared across +module boundaries. When independently compiled modules — potentially +from different source languages — read and write the same memory +regions, no existing type system covers the cross-module interface. We +present *typed-wasm*, a type system that applies a 10-level type safety +framework, originally developed for database query languages, to Wasm +linear memory. The system treats contiguous memory segments as _typed +region schemas_ and load/store operations as _typed projections_ +verified against those schemas at compile time. We formalise the system +in Idris 2 using Quantitative Type Theory (QTT), providing proofs of +bounds safety, aliasing freedom, effect purity, lifetime validity, and +linearity — all erased before code generation, yielding zero runtime +overhead. Our principal contribution is *multi-module schema agreement*: +a static verification that independently compiled Wasm modules agree on +the layout, types, alignment, and invariants of shared memory regions — +a property that no source-level type system, and no existing Wasm +proposal, can express. + +''''' + +=== 1. Introduction + +The WebAssembly specification [Haas et al. 2017] defines a stack-based +virtual machine with strong instruction-level type safety: the validator +rejects programs whose stack operations are type-incorrect, and the +structured control flow ensures that branches target valid labels. These +properties make Wasm a safe compilation target for individual languages. + +However, Wasm’s linear memory — the flat byte array that serves as the +heap for compiled C, Rust, and other systems languages — is entirely +untyped. An `+i32.load offset=0+` and an `+f64.load offset=0+` targeting +the same address are both valid instructions, regardless of what was +actually stored there. The Wasm validator checks that the instruction +encoding is correct, not that the memory access is semantically +meaningful. + +This gap becomes a safety hazard when multiple independently compiled +modules share linear memory — an increasingly common pattern in plugin +architectures, game engines, and polyglot Wasm compositions. If Module A +(compiled from Rust) writes a struct to shared memory and Module B +(compiled from C or AffineScript) reads the same memory with a different +layout assumption, the result is silent data corruption undetectable by +either source-level type system. + +We observe that this problem has the same structure as untyped database +access: programs issue "`queries`" (load/store instructions) against a +"`schema`" (memory layout) with no static guarantee that the query is +compatible with the schema. The database query language community has +developed mature solutions to this problem, culminating in progressive +type safety frameworks that verify queries against schemas at compile +time. + +This paper presents typed-wasm, which applies this approach to Wasm +linear memory. Our contributions are: + +[arabic] +. *The database-memory analogy as a design principle* (Section 3): a +structural correspondence between database schemas and memory region +declarations, between queries and typed memory access, that yields a +concrete grammar and type system. +. *A 10-level progressive type safety framework for Wasm memory* +(Section 4): adapting established levels (parse-time validity, schema +binding, type compatibility, null safety, bounds proofs, result typing) +and research levels (aliasing safety, effect tracking, lifetime safety, +linearity) from the database domain to the memory domain. +. *Multi-module schema agreement* (Section 5): a static verification +that independently compiled Wasm modules agree on shared memory layout — +the principal contribution, addressing a class of bugs that no existing +tool can detect. +. *A formalisation in Idris 2 with QTT* (Section 7): dependent types +that prove safety properties at compile time, with proof erasure +yielding identical runtime code to hand-written Wasm. + +''''' + +=== 2. Problem Statement + +==== 2.1 The Untyped Byte Array + +Wasm’s linear memory model [WebAssembly Specification 2024, §5.3] +exposes a resizable byte array to all code within an instance. Memory +access instructions (`+i32.load+`, `+f64.store+`, etc.) take an integer +offset and an alignment hint. The Wasm validator ensures that the +alignment is valid for the instruction and that the access falls within +the allocated page range, but it imposes no constraints on the _semantic +content_ at the accessed offset. + +Formally, if latexmath:[M] is the linear memory (a function from byte +offsets to bytes), then `+i32.load offset=k+` computes +latexmath:[M[k] | (M[k+1] \ll 8) | +(M[k+2] \ll 16) | (M[k+3] \ll 24)] regardless of what was stored at +offsets latexmath:[k] through latexmath:[k+3]. The instruction cannot +fail for type reasons — only for out-of-bounds access beyond the +memory’s page limit. + +==== 2.2 The Cross-Module Boundary Problem + +When multiple modules share linear memory, each module compiles with its +own struct layout assumptions. Consider: + +* *Module A* (Rust, `+#[repr(C)]+`): +`+Player { hp: i32 @ 0, _pad: [u8;4] @ 4, speed: f64 @ 8, name: [u8;32] @ 16 }+` +— 48 bytes, 8-byte aligned. +* *Module B* (C, packed): +`+player_t { int hp @ 0, double speed @ 4, char name[32] @ 12 }+` — 44 +bytes, unaligned. + +Module B reads `+speed+` from offset 4, which in Module A’s layout is +padding. Module B writes `+name+` starting at offset 12, which overlaps +Module A’s `+speed+` field. Neither module’s type checker detects this: +Rust’s borrow checker validates within Rust; C’s type system validates +within C. The mismatch exists at the Wasm level, below both. + +==== 2.3 Bug Taxonomy + +We identify five classes of cross-module memory bugs: + +[width="100%",cols="22%,39%,39%",options="header",] +|=== +|Class |Description |Consequence +|*B1. Type reinterpretation* |Load type differs from store type at same +offset |Silent value corruption + +|*B2. Layout disagreement* |Modules assume different field offsets |All +fields after the first are misread + +|*B3. Null sentinel divergence* |Modules disagree on the null +representation |Valid pointers treated as null, or vice versa + +|*B4. Lifetime mismatch* |One module frees memory another still +references |Use-after-free, data from reallocated memory + +|*B5. Ownership confusion* |Multiple modules believe they own the +allocation |Double-free, heap corruption +|=== + +These bugs share a common root: the absence of a shared schema that all +modules agree upon and that a static checker can verify. + +==== 2.4 Insufficiency of Existing Approaches + +[width="100%",cols="25%,36%,39%",options="header",] +|=== +|Approach |What it covers |What it misses +|Rust borrow checker |Ownership within Rust |Cross-module access from +non-Rust code + +|Wasm validation |Instruction encoding, page bounds |Semantic +correctness within pages + +|Wasm GC proposal |Managed reference types |Linear memory (unmanaged) + +|Typed Assembly Language [Morrisett et al. 1999] |Register/stack types +|Structured regions, cross-module schemas + +|MSWasm [Disselkoen et al. 2022] |Segment bounds checking |Field-level +types, schema agreement + +|Component Model [WebAssembly CG 2024] |Function call interfaces |Shared +mutable memory +|=== + +''''' + +=== 3. The Database-Memory Analogy + +==== 3.1 Structural Correspondence + +The TypedQL framework [Jewell 2026] provides 10 progressive levels of +type safety for database query languages. Its central mechanism is +verifying _query projections_ against a _declared schema_ at compile +time. We observe that Wasm memory access has identical structure: + +[width="100%",cols="26%,32%,42%",options="header",] +|=== +|Database |Wasm Memory |Structural Role +|Table |Region |Named container of typed records + +|Row |Region instance |Single record at a computed offset + +|Column |Field |Named, typed datum within a record + +|Schema |Region declaration |Compile-time layout specification + +|`+SELECT col FROM table+` |`+region.get $r .field+` |Read projection + +|`+UPDATE table SET col = v+` |`+region.set $r .field, v+` |Write +projection + +|Foreign key |`+ptr<@OtherRegion>+` |Cross-region typed reference + +|`+CHECK+` constraint |`+invariant { ... }+` |Domain validity rule +|=== + +==== 3.2 Why the Analogy Is Load-Bearing + +This is not a surface-level metaphor. The correspondence determines +concrete design decisions: + +[arabic] +. *Region declarations* use declarative syntax isomorphic to +`+CREATE TABLE+`: +`+region Players[100] { hp: i32; speed: f64; align 8; }+`. +. *Import/export of region schemas* mirrors shared database schemas +across services. Module A exports; Module B imports; the checker +verifies structural compatibility. +. *Cross-region invariants* are foreign key constraints over memory: +`+invariant { across: Enemies, Players; holds: forall e. 0 <= e.target_id < 4096; }+`. +. *`+region.scan+` with `+where+`* is +`+SELECT * FROM region WHERE predicate+`, extending naturally to +iteration, filtering, and aggregation over array regions. + +The 10-level framework transfers directly because the safety properties +are properties of _projections against schemas_, independent of whether +the schema describes a database table or a memory region. + +==== 3.3 Where the Analogy Diverges + +Three aspects of Wasm memory have no direct database counterpart: + +* *Alignment and padding.* Memory fields require alignment to natural +boundaries. typed-wasm makes alignment explicit in declarations and +includes it in the type-checking contract. +* *Pointer arithmetic.* Wasm linear memory is addressed by integer +offsets. typed-wasm introduces pointer types (`+ptr+`, `+ref+`, +`+unique+`) with ownership semantics borrowed from substructural type +theory. +* *Concurrency.* Database transactions provide isolation; Wasm shared +memory provides none. typed-wasm’s aliasing safety (Level 7) addresses +single-threaded aliasing; concurrent access is deferred to future work. + +''''' + +=== 4. The 10 Levels of Type Safety for Wasm Memory + +TypeLL defines a progressive stack of 10 type safety levels. Each level +addresses a specific class of failure. Levels are cumulative: a program +cannot achieve Level latexmath:[n] without satisfying Levels 1 through +latexmath:[n-1]. Simple operations exit early — a read from a singleton +region achieves Level 6 with no ownership, effect, lifetime, or +linearity analysis. + +==== 4.1 Established Levels (1–6) + +*Level 1 — Instruction Validity.* The access expression conforms to the +typed-wasm grammar. Analogous to parse-time safety for queries. Wasm +itself validates instruction encoding but not higher-level access +structure. + +*Level 2 — Region-Binding.* Every `+region.get $target .field+` resolves +`+$target+` to a declared region and `+.field+` to a declared field. +Analogous to schema binding. Wasm has no concept of named regions or +fields. + +*Level 3 — Type-Compatible Access.* The result type of a memory access +is determined by the field declaration, not by the programmer’s choice +of load instruction. If `+hp: i32+`, then `+region.get $p .hp+` produces +`+i32+` and compiles to `+i32.load+` — never `+f64.load+`. Analogous to +type-compatible operations in queries. + +*Level 4 — Null Safety.* The type system distinguishes `+ptr+` +(non-nullable) from `+opt>+` (nullable). Accessing a nullable +value requires explicit unwrapping. Analogous to null safety in query +result handling. + +*Level 5 — Bounds-Proof.* Every memory access is provably within the +region’s bounds. For static indices, the Idris 2 prover verifies the +bound at compile time. For dynamic indices, a minimal runtime check is +inserted only where the prover cannot discharge the obligation. +Analogous to injection-proof safety (separation of structure from data). + +*Level 6 — Result-Type.* The return type of every memory access +expression is statically known and propagated through bindings and +function returns. Analogous to result-type safety in queries. + +==== 4.2 Research Levels (7–10) + +*Level 7 — Aliasing Safety.* Mutable references (`+&mut+`) to the same +region do not alias. typed-wasm provides three pointer kinds: + +* `+&+` (shared borrow): unlimited concurrent readers, no mutation. +* `+&mut+` (exclusive borrow): exactly one mutable reference, no +concurrent readers. +* `+own+` (owning): single owner, must transfer or free (Level 10). + +The prover verifies exclusivity at every program point. This is +structurally analogous to Rust’s borrow discipline, but operates at the +Wasm region schema level rather than the source language level. + +*Level 8 — Effect Tracking.* Functions declare their memory effects: +`+effects { ReadRegion(Players), WriteRegion(Config) }+`. A function +declared read-only cannot perform writes. Effects are checked by +subsumption: latexmath:[\mathit{actual} \subseteq \mathit{declared}]. +Analogous to distinguishing `+SELECT+` from `+UPDATE+` in queries. + +*Level 9 — Lifetime Safety.* References carry lifetime annotations +scoping their validity. A reference with lifetime latexmath:[\ell] is +valid only while latexmath:[\ell] is live. The prover verifies that no +reference is used after the memory it points to has been freed. +Analogous to temporal freshness in queries. + +*Level 10 — Linearity.* Owning handles are bound with QTT quantity 1, +enforcing exactly-once consumption. An allocation must be freed exactly +once: the type checker rejects programs with zero uses (leak) or two +uses (double-free) of the handle. This composes with Level 9: freeing +invalidates the lifetime, making all references with that lifetime +unusable. Analogous to connection linearity in database access. + +==== 4.3 Cross-Level Composition + +The levels compose to provide compound guarantees: + +* *L5 ∧ L7:* Bounds-proof plus aliasing safety proves that two exclusive +references never overlap in memory, even for different fields within the +same region. +* *L8 ∧ L9:* Effect tracking plus lifetime safety proves that a +read-only reference cannot observe a free effect on its target region. +* *L7 ∧ L10:* Aliasing safety plus linearity yields the full ownership +model at the Wasm memory level. +* *L2 ∧ L3 ∧ multi-module:* Region-binding plus type-compatibility +across module boundaries is the composition unique to typed-wasm. + +''''' + +=== 5. Multi-Module Schema Agreement + +==== 5.1 The Verification Problem + +Given Module A exporting region latexmath:[R_A] with schema +latexmath:[S_A] and Module B importing region latexmath:[R_B] (claiming +to correspond to latexmath:[R_A]) with schema latexmath:[S_B], verify +that latexmath:[S_B] is structurally compatible with latexmath:[S_A]. + +==== 5.2 Compatibility Relation + +We define structural compatibility latexmath:[S_B \preceq S_A] (import +compatible with export) as follows: + +*Definition 1 (Field Compatibility).* Fields latexmath:[f_A] and +latexmath:[f_B] are compatible, written latexmath:[f_B \sim f_A], iff: - +latexmath:[f_B.\mathit{name} = f_A.\mathit{name}] - +latexmath:[f_B.\mathit{type} = f_A.\mathit{type}] (strict equality, no +implicit conversions) - +latexmath:[f_B.\mathit{offset} = f_A.\mathit{offset}] (computed from +types and alignment) + +*Definition 2 (Schema Compatibility).* latexmath:[S_B \preceq S_A] iff: +- For every field latexmath:[f_B \in S_B], there exists +latexmath:[f_A \in S_A] such that latexmath:[f_B \sim f_A]. - +latexmath:[S_B.\mathit{alignment} = S_A.\mathit{alignment}] - +latexmath:[S_B.\mathit{instance\_count} = S_A.\mathit{instance\_count}] + +Note that latexmath:[\preceq] permits latexmath:[S_B] to be a _subset_ +of latexmath:[S_A]: Module B may import fewer fields than Module A +exports. Module B simply cannot access the omitted fields. This is +analogous to a database view that projects a subset of columns. + +*Definition 3 (Multi-Module Agreement).* A set of modules +latexmath:[\{M_1, \ldots, M_n\}] sharing region latexmath:[R] satisfies +multi-module agreement iff exactly one module latexmath:[M_e] exports +latexmath:[R] with schema latexmath:[S_e], and for every importing +module latexmath:[M_i] with schema latexmath:[S_i], +latexmath:[S_i \preceq S_e]. + +==== 5.3 Formalisation + +In the Idris 2 ABI layer, schema agreement is a dependent type: + +[source,idris] +---- +data CompatCertificate : Type where + MkCompat : (agreement : SchemaAgreement) + -> (alignment : AlignmentAgrees ea ia) + -> (instances : InstanceCountAgrees ec ic) + -> CompatCertificate +---- + +Constructing a `+CompatCertificate+` requires providing proofs of each +component. If any proof cannot be constructed — a field name mismatch, a +type difference, an alignment disagreement — the certificate cannot be +produced, and the program is rejected at compile time. + +==== 5.4 Diagnostic Reporting + +When verification fails, the checker produces structured diagnostics: + +.... +Schema mismatch for region 'Player' imported by module_b from module_a: + Field 'speed': type mismatch + Expected (from module_a): f64 + Found (in module_b): f32 + Field 'name': offset mismatch + Expected (from module_a): offset 16 (8-byte aligned) + Found (in module_b): offset 12 (assumes packed layout) +.... + +==== 5.5 Practical Applications + +Multi-module schema agreement enables: + +* *Plugin architectures* where the host exports region schemas and +plugins import them. Schema-breaking changes are caught at plugin +compile time. +* *Polyglot Wasm compositions* where Rust, C, and AffineScript modules +share structured data with compile-time layout verification. +* *Hot-reloadable modules* where a new module version is checked for +schema compatibility with existing modules before deployment. + +''''' + +=== 6. Implications for GraalVM + +GraalVM’s Truffle framework [Würthinger et al. 2017] enables +cross-language interoperation through `+InteropLibrary+`, which +dispatches member reads, writes, and invocations at runtime. When a +JavaScript object is accessed from Python code, +`+InteropLibrary.readMember()+` performs runtime type checking and +conversion. + +This has two costs: runtime dispatch overhead and the absence of +compile-time guarantees. typed-wasm’s region schemas could serve as a +compile-time contract between Truffle languages: + +[arabic] +. Language A exports a region schema describing shared state. +. Language B imports the schema. +. The checker verifies agreement at AOT compilation time. +. The Truffle partial evaluator replaces `+InteropLibrary+` dispatch +with direct memory access at known offsets, justified by the schema +proof. + +This applies specifically to GraalVM’s native interop paths (Sulong, +shared memory). Adapting the approach to Truffle’s object-based interop +for managed languages requires mapping object shapes to region schemas, +which is feasible given Truffle’s `+DynamicObject+` shape tracking but +remains future work. + +''''' + +=== 7. Formal Foundations + +==== 7.1 Idris 2 and Dependent Types + +typed-wasm’s proofs are written in Idris 2 [Brady 2021], a dependently +typed language where types may depend on values. This is necessary +because memory safety properties inherently depend on values: "`index +latexmath:[i] is within the bounds of array of size latexmath:[n]`" is a +proposition over the value of latexmath:[i]. + +A region schema is a value-level record: + +[source,idris] +---- +data Schema : List (String, FieldType) -> Type where + Nil : Schema [] + (::) : Field name ty -> Schema rest -> Schema ((name, ty) :: rest) +---- + +A typed access is indexed by the schema: + +[source,idris] +---- +data TypedGet : Schema fields -> (name : String) -> FieldType -> Type where + GetHere : TypedGet (MkField {name} {ty} :: rest) name ty + GetThere : TypedGet rest name ty -> TypedGet (f :: rest) name ty +---- + +The result type of `+region.get $r .name+` is _computed_ from the +schema, not declared by the programmer. + +==== 7.2 Quantitative Type Theory + +Idris 2’s QTT [Atkey 2018; McBride 2016] assigns quantities to bindings: + +[width="100%",cols="25%,17%,58%",options="header",] +|=== +|Quantity |Usage |typed-wasm application +|0 (erased) |Compile-time only |Proof witnesses, schema metadata, bounds +evidence + +|1 (linear) |Exactly once at runtime |Owning handles, allocation tokens + +|latexmath:[\omega] (unrestricted) |Any number of times |Normal values, +shared references +|=== + +Level 10 is implemented by binding allocation handles with quantity 1: + +[source,idris] +---- +freeRegion : (1 _ : LinHandle token) -> RegionLive token -> FreeResult +---- + +The `+(1 _)+` annotation means the type checker rejects any program +where the handle is used zero times (leak) or more than once +(double-free). + +==== 7.3 Proof Erasure + +All quantity-0 terms — which includes all proof witnesses, bounds +evidence, schema metadata, compatibility certificates, and lifetime +annotations — are erased by the Idris 2 compiler before code generation. + +*Theorem (informal).* The runtime representation of a well-typed +typed-wasm program is identical to the Wasm instructions that a +hand-written program would produce. The type safety is a compile-time +property with no runtime manifestation. + +This is the zero-overhead guarantee: `+region.get $player .hp+` compiles +to exactly `+i32.load offset=0+`, with the proof that this instruction +is correct existing only during compilation. + +==== 7.4 Soundness Sketch + +We conjecture the following soundness property: + +*Conjecture 1 (typed-wasm soundness).* If a typed-wasm program +type-checks at all 10 levels, then the compiled Wasm program: - (a) +never performs a type-confused memory read (L3), - (b) never accesses +memory outside a declared region (L5), - (c) never holds aliased mutable +references (L7), - (d) never performs an undeclared memory effect (L8), +- (e) never dereferences a freed region (L9), and - (f) never leaks or +double-frees an allocation (L10). + +A full mechanised proof is future work. The current Idris 2 +formalisation provides dependent-type-level evidence for properties +(a)–(f), verified by the totality checker, but does not yet connect to a +formal Wasm operational semantics. + +''''' + +=== 8. Implementation Architecture + +[width="100%",cols="31%,43%,26%",options="header",] +|=== +|Layer |Language |Role +|ABI definitions |Idris 2 |Dependent types: region schemas, access +rules, proof obligations + +|FFI bridge |Zig |C-ABI runtime: region management, typed load/store, +WASM codegen + +|Surface parser |AffineScript |Parse `+.twasm+` syntax to typed AST + +|Proof engine |Idris 2 totality checker |Discharge levels 5–10 +obligations + +|Code generator |Zig → Wasm |Emit raw Wasm instructions from verified +typed access + +|Ecosystem plugin |Rust (TypedQLiser) |Integration as a TypedQLiser +target language +|=== + +*Zig FFI.* Zig provides native C ABI compatibility, built-in +`+wasm32-freestanding+` target support, cross-compilation without +runtime dependencies, and memory-safe defaults. Region handles encode +base offset, schema ID, generation counter (for lifetime tracking), and +ownership flag in a 64-bit value. + +*AffineScript parser.* The surface syntax parser is written in +AffineScript, consistent with the VCL-total parser in the TypedQL +ecosystem. AffineScript compiles to JavaScript/Wasm via Deno. + +*TypedQLiser integration.* typed-wasm implements the +`+QueryLanguagePlugin+` trait from TypedQLiser, making Wasm memory a +target alongside SQL, GraphQL, and VCL. This enables end-to-end +verification: a database query is type-checked by TypedQLiser, and the +memory region holding its results is type-checked by typed-wasm. + +''''' + +=== 9. Related Work + +*Typed Assembly Language.* Morrisett et al. [1999] introduced TAL, +assigning types to registers and stack slots to prove progress and +preservation for assembly programs. typed-wasm extends this approach +with structured region schemas, cross-module import/export, and a +10-level progressive framework. TAL types individual memory cells; +typed-wasm types structured multi-field regions. + +*MSWasm.* Disselkoen et al. [2022] add memory segments with bounds +checking to Wasm, enforcing spatial safety. typed-wasm builds on this by +adding field-level types within bounded regions, cross-module schema +agreement, effect tracking, and linearity. The two are complementary: +MSWasm ensures access is within bounds; typed-wasm ensures access is +also type-correct within those bounds. + +*Wasm GC Proposal.* The GC proposal [WebAssembly CG 2024a] introduces +managed struct and array types. These are type-safe by construction but +apply only to GC-managed objects, not to linear memory. Systems +languages (C, Rust) that manage their own memory cannot benefit. +typed-wasm and Wasm GC are complementary. + +*Wasm Component Model.* The Component Model [WebAssembly CG 2024b] types +function call interfaces with automatic marshalling. It addresses +isolation-based composition (copying data across boundaries). typed-wasm +addresses shared-memory composition (typing in-place access). Both are +valid architectural choices; typed-wasm covers the case where copying is +too expensive. + +*Rust Ownership.* Rust’s affine type system [Jung et al. 2018] prevents +use-after-free, double-free, and data races within Rust code. +typed-wasm’s Levels 7, 9, and 10 are deliberately analogous but operate +at the Wasm level, covering cross-language boundaries that Rust cannot +reach. + +*Checked C and Typed LLVM.* Checked C [Elliott et al. 2018] adds +bounds-checked pointers to C. Typed LLVM [Lee et al.] adds types to LLVM +IR. Both improve single-language compilation pipelines. typed-wasm +operates at the Wasm convergence point, where multiple source languages +meet. + +*Substructural Type Systems.* Linear types [Wadler 1990], uniqueness +types [Barendsen and Smetsers 1996], and quantitative type theory [Atkey +2018] provide the theoretical foundation for typed-wasm’s Levels 7–10. +Our contribution is not new type theory but rather the application of +these ideas to the specific problem of cross-module Wasm memory safety. + +''''' + +=== 10. Limitations and Future Work + +*Concurrency.* typed-wasm v0.1 does not address Wasm shared memory with +atomics. Concurrent access to shared regions requires session types or +fractional permissions, which are explored in the TypeQL-Experimental +project but not yet integrated. + +*GC interaction.* The boundary between linear memory and GC-managed +objects is currently untyped. A `+gcref+` field type is conceivable +but requires runtime cooperation beyond static checking. + +*Dynamic layouts.* Programs that determine memory layout at runtime (JIT +compilers, dynamic object models) cannot use static region declarations +without an adaptation layer. + +*Adoption barrier.* All participating modules must carry typed-wasm +annotations. Automatic schema inference from `+#[repr(C)]+` attributes, +C headers, and Wasm debug custom sections could lower this barrier. + +*Proof completeness.* Levels 5–10 depend on the Idris 2 totality +checker. Complex arithmetic bounds may require manual proof assistance. +The practical frequency of this in real Wasm modules is an empirical +question. + +*Mechanised soundness.* The soundness conjecture (Section 7.4) is not +yet mechanically verified against a formal Wasm operational semantics. +Connecting the Idris 2 formalisation to an existing Wasm mechanisation +(e.g., WasmCert [Watt 2018]) is a priority. + +''''' + +=== 11. Conclusion + +Wasm’s linear memory is the largest untyped shared mutable state surface +in modern software. Multiple languages compile to Wasm; multiple modules +share linear memory; no existing type system covers the boundary between +them. + +typed-wasm addresses this by recognising that Wasm memory access has the +same structure as database queries — projections against a declared +schema. By applying a 10-level type safety framework to memory regions, +typed-wasm provides: + +[arabic] +. *Region schemas* that declare memory layout with field names, types, +alignment, and invariants. +. *Multi-module schema agreement* that statically verifies layout +compatibility across independently compiled modules. +. *10 levels of progressive type safety* from instruction validity +through linearity, with formal proofs in Idris 2 and zero runtime +overhead through proof erasure. +. *A practical architecture* integrating Idris 2, Zig, AffineScript, and +the TypedQLiser ecosystem. + +The implication extends beyond Wasm. Any system where multiple languages +share untyped mutable state — GraalVM Truffle interop, JNI, FFI bridges, +shared memory IPC — faces the same class of bugs. typed-wasm +demonstrates that database query type safety is a transferable framework +for these domains. + +''''' + +=== References + +Atkey, R. (2018). Syntax and Semantics of Quantitative Type Theory. +_ACM/IEEE Symposium on Logic in Computer Science (LICS)_. + +Barendsen, E. and Smetsers, S. (1996). Uniqueness Typing for Functional +Languages with Graph Rewriting Semantics. _Mathematical Structures in +Computer Science_, 6(6):579–612. + +Brady, E. (2021). Idris 2: Quantitative Type Theory in Practice. +_European Conference on Object-Oriented Programming (ECOOP)_. + +Disselkoen, C., Renner, J., Watt, C., Garber, T., Cauligi, S., and +Stefan, D. (2022). MSWasm: Soundly Enforcing Memory-Safe Execution of +Unsafe Code. _IEEE Symposium on Security and Privacy_. + +Elliott, A.S., Ruef, A., Hicks, M., and Tarditi, D. (2018). Checked C: +Making C Safe by Extension. _IEEE Cybersecurity Development (SecDev)_. + +Haas, A., Rossberg, A., Schuff, D.L., et al. (2017). Bringing the Web up +to Speed with WebAssembly. _ACM SIGPLAN Conference on Programming +Language Design and Implementation (PLDI)_. + +Jewell, J.D.A. (2026). TypedQL: A 10-Level Type Safety Framework for +Database Query Languages. _Technical Report_, hyperpolymath. + +Jung, R., Jourdan, J.-H., Krebbers, R., and Dreyer, D. (2018). RustBelt: +Securing the Foundations of the Rust Programming Language. _Proceedings +of the ACM on Programming Languages (POPL)_, 2(POPL):66. + +McBride, C. (2016). I Got Plenty o’ Nuttin’. _A List of Successes That +Can Change the World_, LNCS 9600:207–233. + +Morrisett, G., Walker, D., Crary, K., and Glew, N. (1999). From System F +to Typed Assembly Language. _ACM Transactions on Programming Languages +and Systems_, 21(3):527–568. + +Wadler, P. (1990). Linear Types Can Change the World! _Programming +Concepts and Methods_. + +Watt, C. (2018). Mechanising and Verifying the WebAssembly +Specification. _ACM SIGPLAN Conference on Certified Programs and Proofs +(CPP)_. + +WebAssembly Community Group. (2024a). GC Proposal. +https://github.com/WebAssembly/gc + +WebAssembly Community Group. (2024b). Component Model. +https://github.com/WebAssembly/component-model + +WebAssembly Community Group. (2024c). WebAssembly Specification. +https://webassembly.github.io/spec/ + +Würthinger, T., Wimmer, C., Humer, C., et al. (2017). Practical Partial +Evaluation for High-Performance Dynamic Language Runtimes. _ACM SIGPLAN +Conference on Programming Language Design and Implementation (PLDI)_. + +''''' + +_typed-wasm is part of the hyperpolymath TypeLL ecosystem._ _Repository: +https://github.com/hyperpolymath/typed-wasm_ diff --git a/docs/WHITEPAPER.md b/docs/WHITEPAPER.md deleted file mode 100644 index efd748b..0000000 --- a/docs/WHITEPAPER.md +++ /dev/null @@ -1,696 +0,0 @@ - - - -# typed-wasm: Applying Database Query Type Safety to WebAssembly Linear Memory - -**Jonathan D.A. Jewell** -The Open University, Milton Keynes, UK -`j.d.a.jewell@open.ac.uk` - -**Draft — March 2026** - ---- - -**Keywords:** WebAssembly, type safety, dependent types, linear memory, -multi-module verification, quantitative type theory, memory safety - -**Categories:** D.3.1 [Programming Languages]: Formal Definitions and Theory; -D.2.4 [Software Engineering]: Software/Program Verification; -F.3.1 [Logics and Meanings of Programs]: Specifying and Verifying Programs - ---- - -## Abstract - -WebAssembly (Wasm) linear memory is an untyped byte array shared across -module boundaries. When independently compiled modules — potentially from -different source languages — read and write the same memory regions, no -existing type system covers the cross-module interface. We present -**typed-wasm**, a type system that applies a 10-level type safety -framework, originally developed for database query languages, to Wasm -linear memory. The system treats contiguous memory segments as *typed -region schemas* and load/store operations as *typed projections* verified -against those schemas at compile time. We formalise the system in Idris 2 -using Quantitative Type Theory (QTT), providing proofs of bounds safety, -aliasing freedom, effect purity, lifetime validity, and linearity — all -erased before code generation, yielding zero runtime overhead. Our -principal contribution is **multi-module schema agreement**: a static -verification that independently compiled Wasm modules agree on the -layout, types, alignment, and invariants of shared memory regions — a -property that no source-level type system, and no existing Wasm proposal, -can express. - ---- - -## 1. Introduction - -The WebAssembly specification [Haas et al. 2017] defines a stack-based -virtual machine with strong instruction-level type safety: the validator -rejects programs whose stack operations are type-incorrect, and the -structured control flow ensures that branches target valid labels. These -properties make Wasm a safe compilation target for individual languages. - -However, Wasm's linear memory — the flat byte array that serves as the -heap for compiled C, Rust, and other systems languages — is entirely -untyped. An `i32.load offset=0` and an `f64.load offset=0` targeting the -same address are both valid instructions, regardless of what was actually -stored there. The Wasm validator checks that the instruction encoding is -correct, not that the memory access is semantically meaningful. - -This gap becomes a safety hazard when multiple independently compiled -modules share linear memory — an increasingly common pattern in plugin -architectures, game engines, and polyglot Wasm compositions. If Module A -(compiled from Rust) writes a struct to shared memory and Module B -(compiled from C or AffineScript) reads the same memory with a different -layout assumption, the result is silent data corruption undetectable by -either source-level type system. - -We observe that this problem has the same structure as untyped database -access: programs issue "queries" (load/store instructions) against a -"schema" (memory layout) with no static guarantee that the query is -compatible with the schema. The database query language community has -developed mature solutions to this problem, culminating in progressive -type safety frameworks that verify queries against schemas at compile time. - -This paper presents typed-wasm, which applies this approach to Wasm -linear memory. Our contributions are: - -1. **The database-memory analogy as a design principle** (Section 3): - a structural correspondence between database schemas and memory - region declarations, between queries and typed memory access, that - yields a concrete grammar and type system. - -2. **A 10-level progressive type safety framework for Wasm memory** - (Section 4): adapting established levels (parse-time validity, - schema binding, type compatibility, null safety, bounds proofs, - result typing) and research levels (aliasing safety, effect - tracking, lifetime safety, linearity) from the database domain - to the memory domain. - -3. **Multi-module schema agreement** (Section 5): a static verification - that independently compiled Wasm modules agree on shared memory - layout — the principal contribution, addressing a class of bugs - that no existing tool can detect. - -4. **A formalisation in Idris 2 with QTT** (Section 7): dependent types - that prove safety properties at compile time, with proof erasure - yielding identical runtime code to hand-written Wasm. - ---- - -## 2. Problem Statement - -### 2.1 The Untyped Byte Array - -Wasm's linear memory model [WebAssembly Specification 2024, §5.3] -exposes a resizable byte array to all code within an instance. Memory -access instructions (`i32.load`, `f64.store`, etc.) take an integer -offset and an alignment hint. The Wasm validator ensures that the -alignment is valid for the instruction and that the access falls within -the allocated page range, but it imposes no constraints on the -*semantic content* at the accessed offset. - -Formally, if $M$ is the linear memory (a function from byte offsets to -bytes), then `i32.load offset=k` computes $M[k] | (M[k+1] \ll 8) | -(M[k+2] \ll 16) | (M[k+3] \ll 24)$ regardless of what was stored at -offsets $k$ through $k+3$. The instruction cannot fail for type reasons -— only for out-of-bounds access beyond the memory's page limit. - -### 2.2 The Cross-Module Boundary Problem - -When multiple modules share linear memory, each module compiles with its -own struct layout assumptions. Consider: - -- **Module A** (Rust, `#[repr(C)]`): `Player { hp: i32 @ 0, _pad: [u8;4] @ 4, speed: f64 @ 8, name: [u8;32] @ 16 }` — 48 bytes, 8-byte aligned. -- **Module B** (C, packed): `player_t { int hp @ 0, double speed @ 4, char name[32] @ 12 }` — 44 bytes, unaligned. - -Module B reads `speed` from offset 4, which in Module A's layout is -padding. Module B writes `name` starting at offset 12, which overlaps -Module A's `speed` field. Neither module's type checker detects this: -Rust's borrow checker validates within Rust; C's type system validates -within C. The mismatch exists at the Wasm level, below both. - -### 2.3 Bug Taxonomy - -We identify five classes of cross-module memory bugs: - -| Class | Description | Consequence | -|-------|-------------|-------------| -| **B1. Type reinterpretation** | Load type differs from store type at same offset | Silent value corruption | -| **B2. Layout disagreement** | Modules assume different field offsets | All fields after the first are misread | -| **B3. Null sentinel divergence** | Modules disagree on the null representation | Valid pointers treated as null, or vice versa | -| **B4. Lifetime mismatch** | One module frees memory another still references | Use-after-free, data from reallocated memory | -| **B5. Ownership confusion** | Multiple modules believe they own the allocation | Double-free, heap corruption | - -These bugs share a common root: the absence of a shared schema that all -modules agree upon and that a static checker can verify. - -### 2.4 Insufficiency of Existing Approaches - -| Approach | What it covers | What it misses | -|----------|---------------|----------------| -| Rust borrow checker | Ownership within Rust | Cross-module access from non-Rust code | -| Wasm validation | Instruction encoding, page bounds | Semantic correctness within pages | -| Wasm GC proposal | Managed reference types | Linear memory (unmanaged) | -| Typed Assembly Language [Morrisett et al. 1999] | Register/stack types | Structured regions, cross-module schemas | -| MSWasm [Disselkoen et al. 2022] | Segment bounds checking | Field-level types, schema agreement | -| Component Model [WebAssembly CG 2024] | Function call interfaces | Shared mutable memory | - ---- - -## 3. The Database-Memory Analogy - -### 3.1 Structural Correspondence - -The TypedQL framework [Jewell 2026] provides 10 progressive levels of -type safety for database query languages. Its central mechanism is -verifying *query projections* against a *declared schema* at compile -time. We observe that Wasm memory access has identical structure: - -| Database | Wasm Memory | Structural Role | -|----------|-------------|-----------------| -| Table | Region | Named container of typed records | -| Row | Region instance | Single record at a computed offset | -| Column | Field | Named, typed datum within a record | -| Schema | Region declaration | Compile-time layout specification | -| `SELECT col FROM table` | `region.get $r .field` | Read projection | -| `UPDATE table SET col = v` | `region.set $r .field, v` | Write projection | -| Foreign key | `ptr<@OtherRegion>` | Cross-region typed reference | -| `CHECK` constraint | `invariant { ... }` | Domain validity rule | - -### 3.2 Why the Analogy Is Load-Bearing - -This is not a surface-level metaphor. The correspondence determines -concrete design decisions: - -1. **Region declarations** use declarative syntax isomorphic to `CREATE TABLE`: - `region Players[100] { hp: i32; speed: f64; align 8; }`. - -2. **Import/export of region schemas** mirrors shared database schemas - across services. Module A exports; Module B imports; the checker - verifies structural compatibility. - -3. **Cross-region invariants** are foreign key constraints over memory: - `invariant { across: Enemies, Players; holds: forall e. 0 <= e.target_id < 4096; }`. - -4. **`region.scan` with `where`** is `SELECT * FROM region WHERE predicate`, - extending naturally to iteration, filtering, and aggregation over - array regions. - -The 10-level framework transfers directly because the safety properties -are properties of *projections against schemas*, independent of whether -the schema describes a database table or a memory region. - -### 3.3 Where the Analogy Diverges - -Three aspects of Wasm memory have no direct database counterpart: - -- **Alignment and padding.** Memory fields require alignment to - natural boundaries. typed-wasm makes alignment explicit in - declarations and includes it in the type-checking contract. - -- **Pointer arithmetic.** Wasm linear memory is addressed by integer - offsets. typed-wasm introduces pointer types (`ptr`, `ref`, `unique`) - with ownership semantics borrowed from substructural type theory. - -- **Concurrency.** Database transactions provide isolation; Wasm shared - memory provides none. typed-wasm's aliasing safety (Level 7) addresses - single-threaded aliasing; concurrent access is deferred to future work. - ---- - -## 4. The 10 Levels of Type Safety for Wasm Memory - -TypeLL defines a progressive stack of 10 type safety levels. Each level -addresses a specific class of failure. Levels are cumulative: a program -cannot achieve Level $n$ without satisfying Levels 1 through $n-1$. -Simple operations exit early — a read from a singleton region achieves -Level 6 with no ownership, effect, lifetime, or linearity analysis. - -### 4.1 Established Levels (1–6) - -**Level 1 — Instruction Validity.** The access expression conforms to the -typed-wasm grammar. Analogous to parse-time safety for queries. Wasm -itself validates instruction encoding but not higher-level access structure. - -**Level 2 — Region-Binding.** Every `region.get $target .field` resolves -`$target` to a declared region and `.field` to a declared field. Analogous -to schema binding. Wasm has no concept of named regions or fields. - -**Level 3 — Type-Compatible Access.** The result type of a memory access -is determined by the field declaration, not by the programmer's choice of -load instruction. If `hp: i32`, then `region.get $p .hp` produces `i32` -and compiles to `i32.load` — never `f64.load`. Analogous to -type-compatible operations in queries. - -**Level 4 — Null Safety.** The type system distinguishes `ptr` -(non-nullable) from `opt>` (nullable). Accessing a nullable -value requires explicit unwrapping. Analogous to null safety in query -result handling. - -**Level 5 — Bounds-Proof.** Every memory access is provably within the -region's bounds. For static indices, the Idris 2 prover verifies the -bound at compile time. For dynamic indices, a minimal runtime check is -inserted only where the prover cannot discharge the obligation. Analogous -to injection-proof safety (separation of structure from data). - -**Level 6 — Result-Type.** The return type of every memory access -expression is statically known and propagated through bindings and -function returns. Analogous to result-type safety in queries. - -### 4.2 Research Levels (7–10) - -**Level 7 — Aliasing Safety.** Mutable references (`&mut`) to the same -region do not alias. typed-wasm provides three pointer kinds: - -- `&` (shared borrow): unlimited concurrent readers, no mutation. -- `&mut` (exclusive borrow): exactly one mutable reference, no concurrent readers. -- `own` (owning): single owner, must transfer or free (Level 10). - -The prover verifies exclusivity at every program point. This is -structurally analogous to Rust's borrow discipline, but operates at the -Wasm region schema level rather than the source language level. - -**Level 8 — Effect Tracking.** Functions declare their memory effects: -`effects { ReadRegion(Players), WriteRegion(Config) }`. A function -declared read-only cannot perform writes. Effects are checked by -subsumption: $\mathit{actual} \subseteq \mathit{declared}$. Analogous to -distinguishing `SELECT` from `UPDATE` in queries. - -**Level 9 — Lifetime Safety.** References carry lifetime annotations -scoping their validity. A reference with lifetime $\ell$ is valid only -while $\ell$ is live. The prover verifies that no reference is used after -the memory it points to has been freed. Analogous to temporal freshness -in queries. - -**Level 10 — Linearity.** Owning handles are bound with QTT quantity 1, -enforcing exactly-once consumption. An allocation must be freed exactly -once: the type checker rejects programs with zero uses (leak) or two uses -(double-free) of the handle. This composes with Level 9: freeing -invalidates the lifetime, making all references with that lifetime -unusable. Analogous to connection linearity in database access. - -### 4.3 Cross-Level Composition - -The levels compose to provide compound guarantees: - -- **L5 ∧ L7:** Bounds-proof plus aliasing safety proves that two exclusive - references never overlap in memory, even for different fields within the - same region. -- **L8 ∧ L9:** Effect tracking plus lifetime safety proves that a - read-only reference cannot observe a free effect on its target region. -- **L7 ∧ L10:** Aliasing safety plus linearity yields the full ownership - model at the Wasm memory level. -- **L2 ∧ L3 ∧ multi-module:** Region-binding plus type-compatibility - across module boundaries is the composition unique to typed-wasm. - ---- - -## 5. Multi-Module Schema Agreement - -### 5.1 The Verification Problem - -Given Module A exporting region $R_A$ with schema $S_A$ and Module B -importing region $R_B$ (claiming to correspond to $R_A$) with schema -$S_B$, verify that $S_B$ is structurally compatible with $S_A$. - -### 5.2 Compatibility Relation - -We define structural compatibility $S_B \preceq S_A$ (import compatible -with export) as follows: - -**Definition 1 (Field Compatibility).** Fields $f_A$ and $f_B$ are -compatible, written $f_B \sim f_A$, iff: -- $f_B.\mathit{name} = f_A.\mathit{name}$ -- $f_B.\mathit{type} = f_A.\mathit{type}$ (strict equality, no implicit conversions) -- $f_B.\mathit{offset} = f_A.\mathit{offset}$ (computed from types and alignment) - -**Definition 2 (Schema Compatibility).** $S_B \preceq S_A$ iff: -- For every field $f_B \in S_B$, there exists $f_A \in S_A$ such that $f_B \sim f_A$. -- $S_B.\mathit{alignment} = S_A.\mathit{alignment}$ -- $S_B.\mathit{instance\_count} = S_A.\mathit{instance\_count}$ - -Note that $\preceq$ permits $S_B$ to be a *subset* of $S_A$: Module B -may import fewer fields than Module A exports. Module B simply cannot -access the omitted fields. This is analogous to a database view that -projects a subset of columns. - -**Definition 3 (Multi-Module Agreement).** A set of modules -$\{M_1, \ldots, M_n\}$ sharing region $R$ satisfies multi-module -agreement iff exactly one module $M_e$ exports $R$ with schema $S_e$, -and for every importing module $M_i$ with schema $S_i$, $S_i \preceq S_e$. - -### 5.3 Formalisation - -In the Idris 2 ABI layer, schema agreement is a dependent type: - -```idris -data CompatCertificate : Type where - MkCompat : (agreement : SchemaAgreement) - -> (alignment : AlignmentAgrees ea ia) - -> (instances : InstanceCountAgrees ec ic) - -> CompatCertificate -``` - -Constructing a `CompatCertificate` requires providing proofs of each -component. If any proof cannot be constructed — a field name mismatch, -a type difference, an alignment disagreement — the certificate cannot -be produced, and the program is rejected at compile time. - -### 5.4 Diagnostic Reporting - -When verification fails, the checker produces structured diagnostics: - -``` -Schema mismatch for region 'Player' imported by module_b from module_a: - Field 'speed': type mismatch - Expected (from module_a): f64 - Found (in module_b): f32 - Field 'name': offset mismatch - Expected (from module_a): offset 16 (8-byte aligned) - Found (in module_b): offset 12 (assumes packed layout) -``` - -### 5.5 Practical Applications - -Multi-module schema agreement enables: - -- **Plugin architectures** where the host exports region schemas and - plugins import them. Schema-breaking changes are caught at plugin - compile time. - -- **Polyglot Wasm compositions** where Rust, C, and AffineScript modules - share structured data with compile-time layout verification. - -- **Hot-reloadable modules** where a new module version is checked for - schema compatibility with existing modules before deployment. - ---- - -## 6. Implications for GraalVM - -GraalVM's Truffle framework [Würthinger et al. 2017] enables -cross-language interoperation through `InteropLibrary`, which dispatches -member reads, writes, and invocations at runtime. When a JavaScript -object is accessed from Python code, `InteropLibrary.readMember()` performs -runtime type checking and conversion. - -This has two costs: runtime dispatch overhead and the absence of -compile-time guarantees. typed-wasm's region schemas could serve as a -compile-time contract between Truffle languages: - -1. Language A exports a region schema describing shared state. -2. Language B imports the schema. -3. The checker verifies agreement at AOT compilation time. -4. The Truffle partial evaluator replaces `InteropLibrary` dispatch with - direct memory access at known offsets, justified by the schema proof. - -This applies specifically to GraalVM's native interop paths (Sulong, -shared memory). Adapting the approach to Truffle's object-based interop -for managed languages requires mapping object shapes to region schemas, -which is feasible given Truffle's `DynamicObject` shape tracking but -remains future work. - ---- - -## 7. Formal Foundations - -### 7.1 Idris 2 and Dependent Types - -typed-wasm's proofs are written in Idris 2 [Brady 2021], a dependently -typed language where types may depend on values. This is necessary -because memory safety properties inherently depend on values: "index $i$ -is within the bounds of array of size $n$" is a proposition over the -value of $i$. - -A region schema is a value-level record: - -```idris -data Schema : List (String, FieldType) -> Type where - Nil : Schema [] - (::) : Field name ty -> Schema rest -> Schema ((name, ty) :: rest) -``` - -A typed access is indexed by the schema: - -```idris -data TypedGet : Schema fields -> (name : String) -> FieldType -> Type where - GetHere : TypedGet (MkField {name} {ty} :: rest) name ty - GetThere : TypedGet rest name ty -> TypedGet (f :: rest) name ty -``` - -The result type of `region.get $r .name` is *computed* from the schema, -not declared by the programmer. - -### 7.2 Quantitative Type Theory - -Idris 2's QTT [Atkey 2018; McBride 2016] assigns quantities to bindings: - -| Quantity | Usage | typed-wasm application | -|----------|-------|------------------------| -| 0 (erased) | Compile-time only | Proof witnesses, schema metadata, bounds evidence | -| 1 (linear) | Exactly once at runtime | Owning handles, allocation tokens | -| $\omega$ (unrestricted) | Any number of times | Normal values, shared references | - -Level 10 is implemented by binding allocation handles with quantity 1: - -```idris -freeRegion : (1 _ : LinHandle token) -> RegionLive token -> FreeResult -``` - -The `(1 _)` annotation means the type checker rejects any program where -the handle is used zero times (leak) or more than once (double-free). - -### 7.3 Proof Erasure - -All quantity-0 terms — which includes all proof witnesses, bounds -evidence, schema metadata, compatibility certificates, and lifetime -annotations — are erased by the Idris 2 compiler before code generation. - -**Theorem (informal).** The runtime representation of a well-typed -typed-wasm program is identical to the Wasm instructions that a -hand-written program would produce. The type safety is a compile-time -property with no runtime manifestation. - -This is the zero-overhead guarantee: `region.get $player .hp` compiles -to exactly `i32.load offset=0`, with the proof that this instruction -is correct existing only during compilation. - -### 7.4 Soundness Sketch - -We conjecture the following soundness property: - -**Conjecture 1 (typed-wasm soundness).** If a typed-wasm program -type-checks at all 10 levels, then the compiled Wasm program: -- (a) never performs a type-confused memory read (L3), -- (b) never accesses memory outside a declared region (L5), -- (c) never holds aliased mutable references (L7), -- (d) never performs an undeclared memory effect (L8), -- (e) never dereferences a freed region (L9), and -- (f) never leaks or double-frees an allocation (L10). - -A full mechanised proof is future work. The current Idris 2 formalisation -provides dependent-type-level evidence for properties (a)–(f), verified -by the totality checker, but does not yet connect to a formal Wasm -operational semantics. - ---- - -## 8. Implementation Architecture - -| Layer | Language | Role | -|-------|----------|------| -| ABI definitions | Idris 2 | Dependent types: region schemas, access rules, proof obligations | -| FFI bridge | Zig | C-ABI runtime: region management, typed load/store, WASM codegen | -| Surface parser | AffineScript | Parse `.twasm` syntax to typed AST | -| Proof engine | Idris 2 totality checker | Discharge levels 5–10 obligations | -| Code generator | Zig → Wasm | Emit raw Wasm instructions from verified typed access | -| Ecosystem plugin | Rust (TypedQLiser) | Integration as a TypedQLiser target language | - -**Zig FFI.** Zig provides native C ABI compatibility, built-in -`wasm32-freestanding` target support, cross-compilation without runtime -dependencies, and memory-safe defaults. Region handles encode base -offset, schema ID, generation counter (for lifetime tracking), and -ownership flag in a 64-bit value. - -**AffineScript parser.** The surface syntax parser is written in AffineScript, -consistent with the VCL-total parser in the TypedQL ecosystem. AffineScript -compiles to JavaScript/Wasm via Deno. - -**TypedQLiser integration.** typed-wasm implements the `QueryLanguagePlugin` -trait from TypedQLiser, making Wasm memory a target alongside SQL, -GraphQL, and VCL. This enables end-to-end verification: a database query -is type-checked by TypedQLiser, and the memory region holding its results -is type-checked by typed-wasm. - ---- - -## 9. Related Work - -**Typed Assembly Language.** Morrisett et al. [1999] introduced TAL, -assigning types to registers and stack slots to prove progress and -preservation for assembly programs. typed-wasm extends this approach -with structured region schemas, cross-module import/export, and a -10-level progressive framework. TAL types individual memory cells; -typed-wasm types structured multi-field regions. - -**MSWasm.** Disselkoen et al. [2022] add memory segments with bounds -checking to Wasm, enforcing spatial safety. typed-wasm builds on this -by adding field-level types within bounded regions, cross-module schema -agreement, effect tracking, and linearity. The two are complementary: -MSWasm ensures access is within bounds; typed-wasm ensures access is -also type-correct within those bounds. - -**Wasm GC Proposal.** The GC proposal [WebAssembly CG 2024a] introduces -managed struct and array types. These are type-safe by construction but -apply only to GC-managed objects, not to linear memory. Systems languages -(C, Rust) that manage their own memory cannot benefit. typed-wasm and -Wasm GC are complementary. - -**Wasm Component Model.** The Component Model [WebAssembly CG 2024b] -types function call interfaces with automatic marshalling. It addresses -isolation-based composition (copying data across boundaries). typed-wasm -addresses shared-memory composition (typing in-place access). Both are -valid architectural choices; typed-wasm covers the case where copying is -too expensive. - -**Rust Ownership.** Rust's affine type system [Jung et al. 2018] -prevents use-after-free, double-free, and data races within Rust code. -typed-wasm's Levels 7, 9, and 10 are deliberately analogous but operate -at the Wasm level, covering cross-language boundaries that Rust cannot reach. - -**Checked C and Typed LLVM.** Checked C [Elliott et al. 2018] adds -bounds-checked pointers to C. Typed LLVM [Lee et al.] adds types to LLVM -IR. Both improve single-language compilation pipelines. typed-wasm -operates at the Wasm convergence point, where multiple source languages meet. - -**Substructural Type Systems.** Linear types [Wadler 1990], uniqueness -types [Barendsen and Smetsers 1996], and quantitative type theory -[Atkey 2018] provide the theoretical foundation for typed-wasm's Levels -7–10. Our contribution is not new type theory but rather the application -of these ideas to the specific problem of cross-module Wasm memory safety. - ---- - -## 10. Limitations and Future Work - -**Concurrency.** typed-wasm v0.1 does not address Wasm shared memory -with atomics. Concurrent access to shared regions requires session types -or fractional permissions, which are explored in the TypeQL-Experimental -project but not yet integrated. - -**GC interaction.** The boundary between linear memory and GC-managed -objects is currently untyped. A `gcref` field type is conceivable but -requires runtime cooperation beyond static checking. - -**Dynamic layouts.** Programs that determine memory layout at runtime -(JIT compilers, dynamic object models) cannot use static region -declarations without an adaptation layer. - -**Adoption barrier.** All participating modules must carry typed-wasm -annotations. Automatic schema inference from `#[repr(C)]` attributes, -C headers, and Wasm debug custom sections could lower this barrier. - -**Proof completeness.** Levels 5–10 depend on the Idris 2 totality -checker. Complex arithmetic bounds may require manual proof assistance. -The practical frequency of this in real Wasm modules is an empirical -question. - -**Mechanised soundness.** The soundness conjecture (Section 7.4) is -not yet mechanically verified against a formal Wasm operational -semantics. Connecting the Idris 2 formalisation to an existing Wasm -mechanisation (e.g., WasmCert [Watt 2018]) is a priority. - ---- - -## 11. Conclusion - -Wasm's linear memory is the largest untyped shared mutable state surface -in modern software. Multiple languages compile to Wasm; multiple modules -share linear memory; no existing type system covers the boundary between -them. - -typed-wasm addresses this by recognising that Wasm memory access has the -same structure as database queries — projections against a declared -schema. By applying a 10-level type safety framework to memory regions, -typed-wasm provides: - -1. **Region schemas** that declare memory layout with field names, types, - alignment, and invariants. -2. **Multi-module schema agreement** that statically verifies layout - compatibility across independently compiled modules. -3. **10 levels of progressive type safety** from instruction validity - through linearity, with formal proofs in Idris 2 and zero runtime - overhead through proof erasure. -4. **A practical architecture** integrating Idris 2, Zig, AffineScript, and - the TypedQLiser ecosystem. - -The implication extends beyond Wasm. Any system where multiple languages -share untyped mutable state — GraalVM Truffle interop, JNI, FFI bridges, -shared memory IPC — faces the same class of bugs. typed-wasm -demonstrates that database query type safety is a transferable framework -for these domains. - ---- - -## References - -Atkey, R. (2018). Syntax and Semantics of Quantitative Type Theory. -*ACM/IEEE Symposium on Logic in Computer Science (LICS)*. - -Barendsen, E. and Smetsers, S. (1996). Uniqueness Typing for Functional -Languages with Graph Rewriting Semantics. *Mathematical Structures in -Computer Science*, 6(6):579–612. - -Brady, E. (2021). Idris 2: Quantitative Type Theory in Practice. -*European Conference on Object-Oriented Programming (ECOOP)*. - -Disselkoen, C., Renner, J., Watt, C., Garber, T., Cauligi, S., and -Stefan, D. (2022). MSWasm: Soundly Enforcing Memory-Safe Execution of -Unsafe Code. *IEEE Symposium on Security and Privacy*. - -Elliott, A.S., Ruef, A., Hicks, M., and Tarditi, D. (2018). Checked C: -Making C Safe by Extension. *IEEE Cybersecurity Development (SecDev)*. - -Haas, A., Rossberg, A., Schuff, D.L., et al. (2017). Bringing the Web -up to Speed with WebAssembly. *ACM SIGPLAN Conference on Programming -Language Design and Implementation (PLDI)*. - -Jewell, J.D.A. (2026). TypedQL: A 10-Level Type Safety Framework for -Database Query Languages. *Technical Report*, hyperpolymath. - -Jung, R., Jourdan, J.-H., Krebbers, R., and Dreyer, D. (2018). -RustBelt: Securing the Foundations of the Rust Programming Language. -*Proceedings of the ACM on Programming Languages (POPL)*, 2(POPL):66. - -McBride, C. (2016). I Got Plenty o' Nuttin'. *A List of Successes That -Can Change the World*, LNCS 9600:207–233. - -Morrisett, G., Walker, D., Crary, K., and Glew, N. (1999). From System F -to Typed Assembly Language. *ACM Transactions on Programming Languages -and Systems*, 21(3):527–568. - -Wadler, P. (1990). Linear Types Can Change the World! *Programming -Concepts and Methods*. - -Watt, C. (2018). Mechanising and Verifying the WebAssembly -Specification. *ACM SIGPLAN Conference on Certified Programs and Proofs -(CPP)*. - -WebAssembly Community Group. (2024a). GC Proposal. -https://github.com/WebAssembly/gc - -WebAssembly Community Group. (2024b). Component Model. -https://github.com/WebAssembly/component-model - -WebAssembly Community Group. (2024c). WebAssembly Specification. -https://webassembly.github.io/spec/ - -Würthinger, T., Wimmer, C., Humer, C., et al. (2017). Practical Partial -Evaluation for High-Performance Dynamic Language Runtimes. *ACM SIGPLAN -Conference on Programming Language Design and Implementation (PLDI)*. - ---- - -*typed-wasm is part of the hyperpolymath TypeLL ecosystem.* -*Repository: https://github.com/hyperpolymath/typed-wasm* diff --git a/docs/investigations/maa-framework-issue-84/ARTIFACTS.adoc b/docs/investigations/maa-framework-issue-84/ARTIFACTS.adoc new file mode 100644 index 0000000..7f500dd --- /dev/null +++ b/docs/investigations/maa-framework-issue-84/ARTIFACTS.adoc @@ -0,0 +1,60 @@ +== Prebuilt conversion artifacts — maa-framework #84 + +This was generated from a *dry-run of `+convert-to-submodule.sh+` +against a fresh `+hyperpolymath/maa-framework+` clone* (base +`+main @ 9dbf56b+`) and *test-applied onto a pristine clone* before +being committed here. It lets a maa-framework-scoped session land the +#84 submodule conversion without re-running the script. + +=== What the conversion commit does + +`+refactor(absolute-zero): convert vendored subtree to submodule pinned upstream (#84)+` + +* replaces the vendored `+absolute-zero/+` subtree (230 files) with a +*submodule gitlink* +`+160000 commit 7da92b360deacb31d6fc8a2121da57ed6f47f4f9+` (upstream +`+absolute-zero+` main HEAD at audit) +* adds `+.gitmodules+` → +`+https://github.com/hyperpolymath/absolute-zero.git+` +* net diffstat: *232 files changed, 4 insertions(+), 36046 deletions(-)* + +=== File + +[width="100%",cols="25%,25%,25%,25%",options="header",] +|=== +|Artifact |Size |Apply with |Tested +|`+issue-84-submodule.bundle+` |683 B +|`+git fetch refs/heads/claude/issue-84-submodule-dryrun && git merge --ff-only FETCH_HEAD+` +|✓ applied onto fresh `+main @ 9dbf56b+`; gitlink + `+.gitmodules+` +verified +|=== + +It’s a 683-byte thin pack (the deletions need no new objects) and +applies as a fast-forward onto maa `+main @ 9dbf56b+` (the ref it +`+requires+`). A full `+git am+` patch was deliberately omitted to keep +this docs folder free of large blobs; if you prefer `+git am+`, +regenerate it in the maa checkout with `+git format-patch -1 +` +after fetching the bundle, or just re-run `+convert-to-submodule.sh+`. + +=== After applying (still required — needs write access to maa-framework) + +[arabic] +. `+git submodule update --init --recursive+` +. Wire `+git submodule update --init --recursive+` into CI/checkout; fix +any `+Justfile+`/CI/build paths that referenced `+absolute-zero/…+`. +. Keep maa-framework’s repo-root `+docs/proof-debt.md+` (PR #82); note +the 150 markers’ canonical home is now the submodule. +. If branch protection requires signed commits, re-commit with your +signer (the artifact commit is unsigned — the dry-run’s signing server +rejected an out-of-scope `+/tmp+` repo with a 400). +. Open a *draft PR*; post the §5 comment from `+ISSUE-84-RESOLUTION.md+` +on #84 and close it. + +=== Provenance / re-verify + +* Base: `+maa-framework+` main +`+9dbf56b53cbbd600b9de589a85521645eca18c2f+` +* Submodule pin: `+absolute-zero+` +`+7da92b360deacb31d6fc8a2121da57ed6f47f4f9+` +* Verify the bundle before trusting it: +`+git bundle verify issue-84-submodule.bundle+` diff --git a/docs/investigations/maa-framework-issue-84/ARTIFACTS.md b/docs/investigations/maa-framework-issue-84/ARTIFACTS.md deleted file mode 100644 index 3adf6d5..0000000 --- a/docs/investigations/maa-framework-issue-84/ARTIFACTS.md +++ /dev/null @@ -1,46 +0,0 @@ - - - -# Prebuilt conversion artifacts — maa-framework #84 - -This was generated from a **dry-run of `convert-to-submodule.sh` against a fresh -`hyperpolymath/maa-framework` clone** (base `main @ 9dbf56b`) and **test-applied onto a pristine -clone** before being committed here. It lets a maa-framework-scoped session land the #84 submodule -conversion without re-running the script. - -## What the conversion commit does - -`refactor(absolute-zero): convert vendored subtree to submodule pinned upstream (#84)` - -- replaces the vendored `absolute-zero/` subtree (230 files) with a **submodule gitlink** - `160000 commit 7da92b360deacb31d6fc8a2121da57ed6f47f4f9` (upstream `absolute-zero` main HEAD at audit) -- adds `.gitmodules` → `https://github.com/hyperpolymath/absolute-zero.git` -- net diffstat: **232 files changed, 4 insertions(+), 36046 deletions(-)** - -## File - -| Artifact | Size | Apply with | Tested | -|---|---|---|---| -| `issue-84-submodule.bundle` | 683 B | `git fetch refs/heads/claude/issue-84-submodule-dryrun && git merge --ff-only FETCH_HEAD` | ✓ applied onto fresh `main @ 9dbf56b`; gitlink + `.gitmodules` verified | - -It's a 683-byte thin pack (the deletions need no new objects) and applies as a fast-forward onto maa -`main @ 9dbf56b` (the ref it `requires`). A full `git am` patch was deliberately omitted to keep this -docs folder free of large blobs; if you prefer `git am`, regenerate it in the maa checkout with -`git format-patch -1 ` after fetching the bundle, or just re-run `convert-to-submodule.sh`. - -## After applying (still required — needs write access to maa-framework) - -1. `git submodule update --init --recursive` -2. Wire `git submodule update --init --recursive` into CI/checkout; fix any `Justfile`/CI/build paths - that referenced `absolute-zero/…`. -3. Keep maa-framework's repo-root `docs/proof-debt.md` (PR #82); note the 150 markers' canonical home - is now the submodule. -4. If branch protection requires signed commits, re-commit with your signer (the artifact commit is - unsigned — the dry-run's signing server rejected an out-of-scope `/tmp` repo with a 400). -5. Open a **draft PR**; post the §5 comment from `ISSUE-84-RESOLUTION.md` on #84 and close it. - -## Provenance / re-verify - -- Base: `maa-framework` main `9dbf56b53cbbd600b9de589a85521645eca18c2f` -- Submodule pin: `absolute-zero` `7da92b360deacb31d6fc8a2121da57ed6f47f4f9` -- Verify the bundle before trusting it: `git bundle verify issue-84-submodule.bundle` diff --git a/docs/investigations/maa-framework-issue-84/HANDOFF-maa-framework-session.adoc b/docs/investigations/maa-framework-issue-84/HANDOFF-maa-framework-session.adoc new file mode 100644 index 0000000..4b7872f --- /dev/null +++ b/docs/investigations/maa-framework-issue-84/HANDOFF-maa-framework-session.adoc @@ -0,0 +1,65 @@ +== Handoff — paste into a Claude Code session scoped to hyperpolymath/maa-framework + +Resolve issue #84 ("`is `+absolute-zero/+` a deliberate fork or stale +vendor copy?`"). + +DECISION (made, HIGH confidence, verified by real `+git diff+` of both +clones): *(B) stale vendor copy — convert `+absolute-zero/+` to a git +submodule. NO extraction needed.* + +Authoritative findings — maa@9dbf56b subtree vs upstream +`+absolute-zero+`@7da92b360deacb31d6fc8a2121da57ed6f47f4f9: - 1 file +only in maa: `+.github/workflows/jekyll-gh-pages.yml+` (inert nested +Pages workflow → drop) - 15 differing files: 6 proof files + 9 stale +infra files. ALL 6 proof files are UPSTREAM-AHEAD: 0 maa-only theorems, +0 maa-only proofs, 0 sorry/admit/Admitted either side. maa just has more +inlined axioms because it predates upstream’s refactor of +kB/temperature/Shannon axioms into the new shared modules +proofs/coq/common/PhysicsConstants.v + StatMechBasis.v. - 2 files only +upstream: those two new common/ modules. => No maa-only proof work +anywhere. Submodule swap loses nothing but the inert CI file. + +#84’s premise is STALE (pre-PR #83 "`re-vendor to upstream HEAD`"). The +files it calls "`unique to maa`" (EchoBridge__.agda, ECHIDNA___, +examples/go, proofs/coq/quantum/) are now byte-identical to upstream +(sha256-verified). maa is simply behind. + +DRY-RUN ALREADY PROVEN (2026-05-30): the conversion was executed against +a fresh maa clone and the guarded script exited 0. Result commit: +`+absolute-zero+` becomes a gitlink `+160000 commit 7da92b3…+`, +`+.gitmodules+` added, *232 files changed, 4 insertions(+), 36046 +deletions(-)*. The safety guard confirmed `+jekyll-gh-pages.yml+` is the +ONLY maa-only path before deleting anything. All proof files (incl. the +two new `+common/+` modules + EchoBridge/quantum) are restored via the +submodule. So you can trust the mechanics; this handoff just needs the +WRITE access this analysis session lacked. + +FASTEST PATH — apply the prebuilt, pre-tested bundle (recommended), then +do steps 4–5 only. From a maa checkout on a fresh branch (bundle is 683 +B, proven to fast-forward onto main @ 9dbf56b): git fetch +docs/investigations/maa-framework-issue-84/issue-84-submodule.bundle + +refs/heads/claude/issue-84-submodule-dryrun git merge –ff-only +FETCH_HEAD git submodule update –init –recursive NOTE: if your +environment signs commits, the bundle’s commit is unsigned — re-commit +with your signer if branch protection requires it (the dry-run hit a +signing-server 400 in /tmp; –no-gpg-sign was used there only). Then jump +to step 4. + +DO THIS (from scratch — equivalent to the artifact above): 1. Re-verify +(gates everything): git clone +https://github.com/hyperpolymath/absolute-zero /tmp/az git -C /tmp/az +checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9 diff -rq –exclude=.git +absolute-zero /tmp/az # expect 1 only-in-maa (jekyll), 15 differ, 2 +only-upstream Eyeball jekyll-gh-pages.yml; if stock Pages deploy, drop +it. 2. git rm -r absolute-zero 3. git submodule add +https://github.com/hyperpolymath/absolute-zero absolute-zero git -C +absolute-zero checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9 +(optional: sparse-checkout set proofs/coq proofs/lean4 proofs/agda) 4. +Add `+git submodule update --init --recursive+` to CI/checkout; fix any +Justfile/CI/build paths. Keep repo-root docs/proof-debt.md (PR #82); +note the 150 markers’ canonical home is now the submodule. 5. Open a +DRAFT PR; post the prepared comment on #84 (it’s in §5 of +ISSUE-84-RESOLUTION.md) and close #84 referencing the PR. + +Guarded script for steps 1–3: convert-to-submodule.sh (has a hard stop +if any unexpected maa-only path appears). diff --git a/docs/investigations/maa-framework-issue-84/HANDOFF-maa-framework-session.md b/docs/investigations/maa-framework-issue-84/HANDOFF-maa-framework-session.md deleted file mode 100644 index 3626038..0000000 --- a/docs/investigations/maa-framework-issue-84/HANDOFF-maa-framework-session.md +++ /dev/null @@ -1,56 +0,0 @@ - - - -# Handoff — paste into a Claude Code session scoped to hyperpolymath/maa-framework - -Resolve issue #84 ("is `absolute-zero/` a deliberate fork or stale vendor copy?"). - -DECISION (made, HIGH confidence, verified by real `git diff` of both clones): -**(B) stale vendor copy — convert `absolute-zero/` to a git submodule. NO extraction needed.** - -Authoritative findings — maa@9dbf56b subtree vs upstream `absolute-zero`@7da92b360deacb31d6fc8a2121da57ed6f47f4f9: -- 1 file only in maa: `.github/workflows/jekyll-gh-pages.yml` (inert nested Pages workflow → drop) -- 15 differing files: 6 proof files + 9 stale infra files. ALL 6 proof files are UPSTREAM-AHEAD: - 0 maa-only theorems, 0 maa-only proofs, 0 sorry/admit/Admitted either side. maa just has more - inlined axioms because it predates upstream's refactor of kB/temperature/Shannon axioms into the - new shared modules proofs/coq/common/PhysicsConstants.v + StatMechBasis.v. -- 2 files only upstream: those two new common/ modules. -=> No maa-only proof work anywhere. Submodule swap loses nothing but the inert CI file. - -#84's premise is STALE (pre-PR #83 "re-vendor to upstream HEAD"). The files it calls "unique to maa" -(EchoBridge*.agda, ECHIDNA_*, examples/go, proofs/coq/quantum/) are now byte-identical to upstream -(sha256-verified). maa is simply behind. - -DRY-RUN ALREADY PROVEN (2026-05-30): the conversion was executed against a fresh maa clone and the -guarded script exited 0. Result commit: `absolute-zero` becomes a gitlink `160000 commit 7da92b3…`, -`.gitmodules` added, **232 files changed, 4 insertions(+), 36046 deletions(-)**. The safety guard -confirmed `jekyll-gh-pages.yml` is the ONLY maa-only path before deleting anything. All proof files -(incl. the two new `common/` modules + EchoBridge/quantum) are restored via the submodule. So you can -trust the mechanics; this handoff just needs the WRITE access this analysis session lacked. - -FASTEST PATH — apply the prebuilt, pre-tested bundle (recommended), then do steps 4–5 only. -From a maa checkout on a fresh branch (bundle is 683 B, proven to fast-forward onto main @ 9dbf56b): - git fetch docs/investigations/maa-framework-issue-84/issue-84-submodule.bundle \ - refs/heads/claude/issue-84-submodule-dryrun - git merge --ff-only FETCH_HEAD - git submodule update --init --recursive -NOTE: if your environment signs commits, the bundle's commit is unsigned — re-commit with your signer -if branch protection requires it (the dry-run hit a signing-server 400 in /tmp; --no-gpg-sign was used -there only). Then jump to step 4. - -DO THIS (from scratch — equivalent to the artifact above): -1. Re-verify (gates everything): - git clone https://github.com/hyperpolymath/absolute-zero /tmp/az - git -C /tmp/az checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9 - diff -rq --exclude=.git absolute-zero /tmp/az # expect 1 only-in-maa (jekyll), 15 differ, 2 only-upstream - Eyeball jekyll-gh-pages.yml; if stock Pages deploy, drop it. -2. git rm -r absolute-zero -3. git submodule add https://github.com/hyperpolymath/absolute-zero absolute-zero - git -C absolute-zero checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9 - (optional: sparse-checkout set proofs/coq proofs/lean4 proofs/agda) -4. Add `git submodule update --init --recursive` to CI/checkout; fix any Justfile/CI/build paths. - Keep repo-root docs/proof-debt.md (PR #82); note the 150 markers' canonical home is now the submodule. -5. Open a DRAFT PR; post the prepared comment on #84 (it's in §5 of ISSUE-84-RESOLUTION.md) and close #84 - referencing the PR. - -Guarded script for steps 1–3: convert-to-submodule.sh (has a hard stop if any unexpected maa-only path appears). diff --git a/docs/investigations/maa-framework-issue-84/ISSUE-84-RESOLUTION.adoc b/docs/investigations/maa-framework-issue-84/ISSUE-84-RESOLUTION.adoc new file mode 100644 index 0000000..cc08af0 --- /dev/null +++ b/docs/investigations/maa-framework-issue-84/ISSUE-84-RESOLUTION.adoc @@ -0,0 +1,202 @@ +== Issue #84 — Resolution: `+absolute-zero/+` is a STALE VENDOR COPY (Option B, pure submodule) + +*Repo:* hyperpolymath/maa-framework · *Issue:* #84 · *Related:* PR #82 +(merged, classifies markers), PR #83 (re-vendor to upstream) *Decision:* +*(B) Stale vendor copy.* Replace the in-tree `+absolute-zero/+` subtree +with a git submodule pinned to upstream `+hyperpolymath/absolute-zero+`. +*Nothing needs to be extracted first.* + +____ +*Evidence basis = authoritative.* Both repos were `+git clone+`d and +compared with real `+diff+` on local disk. Earlier figures in this +thread that came from the WebFetch summariser / async sub-agents were +unreliable (one hallucinated a 1047-line `+QuantumCNO.v+`; another +invented a `+ci.yml+`). *Ignore those. Only the numbers below — from +`+diff+` against the clones — are real.* +____ + +Compared: `+maa @ 9dbf56b+` (subtree `+absolute-zero/+`) vs +`+upstream @ 7da92b360deacb31d6fc8a2121da57ed6f47f4f9+` (2026-05-30). + +''''' + +=== 1. Decision & rationale (one paragraph) + +maa-framework’s `+absolute-zero/+` is a *clean, slightly-stale subset of +upstream* — a vendor copy, *not a fork, not a hybrid*. A full recursive +diff of the whole subtree shows only *1 maa-unique file* (an inert +nested CI workflow), *15 differing files* (every one of which is +_upstream-ahead_), and *2 upstream-only files*. Critically, *no proof +file contains any maa-only theorem or any proof that upstream leaves +open* — so converting the subtree to a submodule *destroys no proof +work*. This keeps PR #82’s `+§(e) VENDORED+` classification correct and +makes "`resolution path = upstream`" structurally true. Hybrid (C) is +ruled out because there is no fork component anywhere in the tree. + +*#84’s premise is stale.* Its "`files unique to maa / missing from maa / +3 drifted proof files`" lists describe the state *before PR #83* +("`re-vendor absolute-zero/ subtree to upstream HEAD`", 27 May). The +files it calls "`unique to maa`" (`+EchoBridgeCNO.agda+`, +`+EchoBridgeScaffold.agda+`, `+ECHIDNA_*+`, `+examples/go+`, …) are now +*byte-identical to upstream* (verified by sha256) — they are _not_ +maa-only. #83 already did the convergence; the submodule swap is the +clean finish. + +''''' + +=== 2. Authoritative whole-subtree diff + +[width="100%",cols="30%,>40%,30%",options="header",] +|=== +|Category |Count |Detail +|*Only in maa* |*1* |`+.github/workflows/jekyll-gh-pages.yml+` — a Pages +workflow in the _nested_ vendored `+.github/+` (inert: nested workflows +don’t run). The only human-glance item; near-certainly disposable. + +|*Differ* |*15* |6 proof files (all upstream-ahead, §3) + 9 infra files: +`+.github/workflows/{governance,hypatia-scan,rust-ci,scorecard}.yml+`, +`+.gitignore+`, `+.machine_readable/META.scm+`, +`+docs/proof-debt-triage.md+`, `+docs/proof-debt.md+`, +`+proofs/coq/_CoqProject+`. All are stale vendored-copy infra, not maa +customisations. + +|*Only in upstream* |*2* |`+proofs/coq/common/PhysicsConstants.v+`, +`+proofs/coq/common/StatMechBasis.v+` — the refactored shared-axiom +modules maa predates (see §3). +|=== + +`+docs/proof-debt.md+` note: the _differing_ one here is the copy +*inside* `+absolute-zero/+` (upstream’s own, maa’s is the 246-line +pre-refactor version vs upstream’s 423-line current; neither mentions +"`maa-framework`"). maa-framework’s *own* repo-root +`+docs/proof-debt.md+` from PR #82 lives *outside* the subtree and is +*not touched* by the swap. + +''''' + +=== 3. The 6 differing proof files — direction = upstream-ahead (safe) + +Open-goal counts (`+Admitted/admit/Axiom/Parameter/sorry+`) and maa-only +proven-theorem counts, both sides, from `+grep+`/`+diff+` on the clones: + +[width="99%",cols="15%,15%,15%,>20%,>20%,15%",options="header",] +|=== +|File |maa (Ax/Param, lines) |upstream (Ax/Param, lines) |maa-only +theorems |maa-only proofs |Verdict +|coq/physics/LandauerDerivation.v |14 / 7, 353 |7 / 4, 349 |0 |0 +|*BEHIND* + +|coq/physics/StatMech.v |10 / 4, 411 |3 / 1, 385 |0 |0 |*BEHIND* + +|coq/quantum/QuantumCNO.v |29 / 16, 622 |27 / 14, 691 |0 |0 |*BEHIND* + +|coq/quantum/QuantumMechanicsExact.v |3 / 1, 423 |1 / 1, 428 |0 |0 +|*BEHIND* + +|lean4/QuantumCNO.lean |0 / 0, 260 |0 / 0, 292 |0 |0 |*BEHIND* + +|lean4/StatMech.lean |0 / 0, 203 |0 / 0, 237 |0 |0 |*BEHIND* (strict +subset: 0 maa-only lines) +|=== + +* *0 sorry / 0 admit / 0 Admitted* on either side, every file. +* maa shows _more_ axioms only because it’s *pre-refactor*: maa inlines +`+kB+`, `+temperature+`, `+prob_nonneg+`, `+shannon_entropy_*+`, etc.; +upstream factored these into the new shared modules +`+common/PhysicsConstants.v+` ("`Single source of truth for [kB] and +[temperature]`") and `+common/StatMechBasis.v+` ("`Shared Probability + +Entropy Axioms`"), wired via upstream’s `+_CoqProject+` +(`++common/PhysicsConstants.v+`, `++common/StatMechBasis.v+`). The 2 +maa-only quantum axioms (`+kB_positive+`, `+temperature_positive+`) are +ABSENT upstream for exactly this reason. +* maa’s only unique lines in the two flagged quantum files are +*comments* ("`X gate is NOT a CNO`", "`Hadamard gate is NOT a CNO`") — +no proof content. + +→ *Every overlapping proof is equal-or-behind upstream. The submodule +swap loses nothing.* This is the disambiguator #84 requested ("`inspect +the drifted files`") — it resolves cleanly to *vendor*. + +Corroborating intent-to-track (not fork): PR #82 (merged) labels all 150 +markers `+§(e) VENDORED+`; history goes +`+"Fix stale submodule pointers after repo cleanup"+` (3 Mar) → +`+"re-vendor … to upstream HEAD"+` (#83, 27 May); vendored files still +carry `+Project: Absolute Zero+` + original author (no rebrand). + +''''' + +=== 4. Plan (pure submodule conversion — no extraction step) + +[arabic] +. *Re-verify in the maa checkout* (the one command that gates +everything): ++ +[source,bash] +---- +git clone https://github.com/hyperpolymath/absolute-zero /tmp/az +git -C /tmp/az checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9 +diff -rq --exclude=.git absolute-zero /tmp/az +# expect: 1 "Only in absolute-zero" (jekyll-gh-pages.yml), 15 "differ", 2 "Only in /tmp/az" +---- ++ +Eyeball `+jekyll-gh-pages.yml+`; if it’s a stock Pages deploy (it is), +let it go. +. `+git rm -r absolute-zero+` +. `+git submodule add https://github.com/hyperpolymath/absolute-zero absolute-zero+` +then +`+git -C absolute-zero checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9+`. +Optional `+sparse-checkout set proofs/coq proofs/lean4 proofs/agda+` if +only the proof subset is wanted (default recommendation: take the whole +sibling — that’s the point of an estate-sibling submodule). +. Wire `+git submodule update --init --recursive+` into checkout/CI; +update any `+Justfile+`/CI/build paths that referenced +`+absolute-zero/…+`. Keep maa-framework’s repo-root +`+docs/proof-debt.md+` (#82) as-is; add a note that the 150 markers’ +canonical home is now the submodule. +. Open a *draft PR* for the conversion; *close #84* with the §5 comment. + +Guarded script for steps 1–3: `+convert-to-submodule.sh+`. + +''''' + +=== 5. Paste-ready comment for #84 + +____ +*Decision: (B) — stale vendor copy. Convert `+absolute-zero/+` to a +submodule. No extraction needed.* + +Cloned both repos and diffed the whole subtree against upstream +`+absolute-zero@7da92b3+` (current HEAD). Authoritative result: + +[width="100%",cols="30%,>40%,30%",options="header",] +|=== +|category |count |what +|only in maa’s `+absolute-zero/+` |1 +|`+.github/workflows/jekyll-gh-pages.yml+` (inert nested Pages workflow) + +|differ |15 |6 proof files + 9 stale infra files + +|only upstream |2 +|`+proofs/coq/common/{PhysicsConstants,StatMechBasis}.v+` +|=== + +*All 6 differing proof files are upstream-ahead* — 0 maa-only theorems, +0 maa-only proofs, 0 `+sorry+`/`+admit+`/`+Admitted+` on either side. +maa simply carries _more inlined axioms_ because it predates upstream’s +refactor of `+kB+`/`+temperature+`/Shannon axioms into the two new +shared `+common/+` modules. So there’s *no maa-only proof work and no +fork* — a submodule swap loses nothing but an inert CI file. + +Heads-up: this issue’s unique/missing-file lists are *stale* — they +predate PR #83 ("`re-vendor to upstream HEAD`"). The files it calls +"`unique to maa`" (`+EchoBridge*.agda+`, `+ECHIDNA_*+`, `+examples/go+`, +`+proofs/coq/quantum/+`) are now byte-identical to upstream +(sha256-verified); maa is just behind. + +*Plan:* (1) `+git rm -r absolute-zero+`; (2) re-add as a submodule +pinned to `+7da92b3+`; (3) wire `+git submodule update --init+` into CI; +(4) keep PR #82’s `+§(e) VENDORED+` classification — the submodule makes +"`resolve upstream`" structurally true. + +Resolves #84 (completing what #83 started). +____ diff --git a/docs/investigations/maa-framework-issue-84/ISSUE-84-RESOLUTION.md b/docs/investigations/maa-framework-issue-84/ISSUE-84-RESOLUTION.md deleted file mode 100644 index 642433c..0000000 --- a/docs/investigations/maa-framework-issue-84/ISSUE-84-RESOLUTION.md +++ /dev/null @@ -1,135 +0,0 @@ - - - -# Issue #84 — Resolution: `absolute-zero/` is a STALE VENDOR COPY (Option B, pure submodule) - -**Repo:** hyperpolymath/maa-framework · **Issue:** #84 · **Related:** PR #82 (merged, classifies markers), PR #83 (re-vendor to upstream) -**Decision:** **(B) Stale vendor copy.** Replace the in-tree `absolute-zero/` subtree with a git -submodule pinned to upstream `hyperpolymath/absolute-zero`. **Nothing needs to be extracted first.** - -> **Evidence basis = authoritative.** Both repos were `git clone`d and compared with real `diff` on -> local disk. Earlier figures in this thread that came from the WebFetch summariser / async sub-agents -> were unreliable (one hallucinated a 1047-line `QuantumCNO.v`; another invented a `ci.yml`). **Ignore -> those. Only the numbers below — from `diff` against the clones — are real.** - -Compared: `maa @ 9dbf56b` (subtree `absolute-zero/`) vs `upstream @ 7da92b360deacb31d6fc8a2121da57ed6f47f4f9` (2026-05-30). - ---- - -## 1. Decision & rationale (one paragraph) - -maa-framework's `absolute-zero/` is a **clean, slightly-stale subset of upstream** — a vendor copy, -**not a fork, not a hybrid**. A full recursive diff of the whole subtree shows only **1 maa-unique -file** (an inert nested CI workflow), **15 differing files** (every one of which is *upstream-ahead*), -and **2 upstream-only files**. Critically, **no proof file contains any maa-only theorem or any proof -that upstream leaves open** — so converting the subtree to a submodule **destroys no proof work**. This -keeps PR #82's `§(e) VENDORED` classification correct and makes "resolution path = upstream" -structurally true. Hybrid (C) is ruled out because there is no fork component anywhere in the tree. - -**#84's premise is stale.** Its "files unique to maa / missing from maa / 3 drifted proof files" lists -describe the state **before PR #83** ("re-vendor absolute-zero/ subtree to upstream HEAD", 27 May). The -files it calls "unique to maa" (`EchoBridgeCNO.agda`, `EchoBridgeScaffold.agda`, `ECHIDNA_*`, -`examples/go`, …) are now **byte-identical to upstream** (verified by sha256) — they are *not* maa-only. -#83 already did the convergence; the submodule swap is the clean finish. - ---- - -## 2. Authoritative whole-subtree diff - -| Category | Count | Detail | -|---|---:|---| -| **Only in maa** | **1** | `.github/workflows/jekyll-gh-pages.yml` — a Pages workflow in the *nested* vendored `.github/` (inert: nested workflows don't run). The only human-glance item; near-certainly disposable. | -| **Differ** | **15** | 6 proof files (all upstream-ahead, §3) + 9 infra files: `.github/workflows/{governance,hypatia-scan,rust-ci,scorecard}.yml`, `.gitignore`, `.machine_readable/META.scm`, `docs/proof-debt-triage.md`, `docs/proof-debt.md`, `proofs/coq/_CoqProject`. All are stale vendored-copy infra, not maa customisations. | -| **Only in upstream** | **2** | `proofs/coq/common/PhysicsConstants.v`, `proofs/coq/common/StatMechBasis.v` — the refactored shared-axiom modules maa predates (see §3). | - -`docs/proof-debt.md` note: the *differing* one here is the copy **inside** `absolute-zero/` (upstream's -own, maa's is the 246-line pre-refactor version vs upstream's 423-line current; neither mentions -"maa-framework"). maa-framework's **own** repo-root `docs/proof-debt.md` from PR #82 lives **outside** -the subtree and is **not touched** by the swap. - ---- - -## 3. The 6 differing proof files — direction = upstream-ahead (safe) - -Open-goal counts (`Admitted/admit/Axiom/Parameter/sorry`) and maa-only proven-theorem counts, both -sides, from `grep`/`diff` on the clones: - -| File | maa (Ax/Param, lines) | upstream (Ax/Param, lines) | maa-only theorems | maa-only proofs | Verdict | -|---|---|---|---:|---:|---| -| coq/physics/LandauerDerivation.v | 14 / 7, 353 | 7 / 4, 349 | 0 | 0 | **BEHIND** | -| coq/physics/StatMech.v | 10 / 4, 411 | 3 / 1, 385 | 0 | 0 | **BEHIND** | -| coq/quantum/QuantumCNO.v | 29 / 16, 622 | 27 / 14, 691 | 0 | 0 | **BEHIND** | -| coq/quantum/QuantumMechanicsExact.v | 3 / 1, 423 | 1 / 1, 428 | 0 | 0 | **BEHIND** | -| lean4/QuantumCNO.lean | 0 / 0, 260 | 0 / 0, 292 | 0 | 0 | **BEHIND** | -| lean4/StatMech.lean | 0 / 0, 203 | 0 / 0, 237 | 0 | 0 | **BEHIND** (strict subset: 0 maa-only lines) | - -- **0 sorry / 0 admit / 0 Admitted** on either side, every file. -- maa shows *more* axioms only because it's **pre-refactor**: maa inlines `kB`, `temperature`, - `prob_nonneg`, `shannon_entropy_*`, etc.; upstream factored these into the new shared modules - `common/PhysicsConstants.v` ("Single source of truth for [kB] and [temperature]") and - `common/StatMechBasis.v` ("Shared Probability + Entropy Axioms"), wired via upstream's `_CoqProject` - (`+common/PhysicsConstants.v`, `+common/StatMechBasis.v`). The 2 maa-only quantum axioms - (`kB_positive`, `temperature_positive`) are ABSENT upstream for exactly this reason. -- maa's only unique lines in the two flagged quantum files are **comments** ("X gate is NOT a CNO", - "Hadamard gate is NOT a CNO") — no proof content. - -→ **Every overlapping proof is equal-or-behind upstream. The submodule swap loses nothing.** This is -the disambiguator #84 requested ("inspect the drifted files") — it resolves cleanly to **vendor**. - -Corroborating intent-to-track (not fork): PR #82 (merged) labels all 150 markers `§(e) VENDORED`; -history goes `"Fix stale submodule pointers after repo cleanup"` (3 Mar) → `"re-vendor … to upstream -HEAD"` (#83, 27 May); vendored files still carry `Project: Absolute Zero` + original author (no rebrand). - ---- - -## 4. Plan (pure submodule conversion — no extraction step) - -1. **Re-verify in the maa checkout** (the one command that gates everything): - ```bash - git clone https://github.com/hyperpolymath/absolute-zero /tmp/az - git -C /tmp/az checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9 - diff -rq --exclude=.git absolute-zero /tmp/az - # expect: 1 "Only in absolute-zero" (jekyll-gh-pages.yml), 15 "differ", 2 "Only in /tmp/az" - ``` - Eyeball `jekyll-gh-pages.yml`; if it's a stock Pages deploy (it is), let it go. -2. `git rm -r absolute-zero` -3. `git submodule add https://github.com/hyperpolymath/absolute-zero absolute-zero` then - `git -C absolute-zero checkout 7da92b360deacb31d6fc8a2121da57ed6f47f4f9`. - Optional `sparse-checkout set proofs/coq proofs/lean4 proofs/agda` if only the proof subset is wanted - (default recommendation: take the whole sibling — that's the point of an estate-sibling submodule). -4. Wire `git submodule update --init --recursive` into checkout/CI; update any `Justfile`/CI/build paths - that referenced `absolute-zero/…`. Keep maa-framework's repo-root `docs/proof-debt.md` (#82) as-is; - add a note that the 150 markers' canonical home is now the submodule. -5. Open a **draft PR** for the conversion; **close #84** with the §5 comment. - -Guarded script for steps 1–3: `convert-to-submodule.sh`. - ---- - -## 5. Paste-ready comment for #84 - -> **Decision: (B) — stale vendor copy. Convert `absolute-zero/` to a submodule. No extraction needed.** -> -> Cloned both repos and diffed the whole subtree against upstream `absolute-zero@7da92b3` (current -> HEAD). Authoritative result: -> -> | category | count | what | -> |---|---:|---| -> | only in maa's `absolute-zero/` | 1 | `.github/workflows/jekyll-gh-pages.yml` (inert nested Pages workflow) | -> | differ | 15 | 6 proof files + 9 stale infra files | -> | only upstream | 2 | `proofs/coq/common/{PhysicsConstants,StatMechBasis}.v` | -> -> **All 6 differing proof files are upstream-ahead** — 0 maa-only theorems, 0 maa-only proofs, 0 -> `sorry`/`admit`/`Admitted` on either side. maa simply carries *more inlined axioms* because it predates -> upstream's refactor of `kB`/`temperature`/Shannon axioms into the two new shared `common/` modules. -> So there's **no maa-only proof work and no fork** — a submodule swap loses nothing but an inert CI file. -> -> Heads-up: this issue's unique/missing-file lists are **stale** — they predate PR #83 ("re-vendor to -> upstream HEAD"). The files it calls "unique to maa" (`EchoBridge*.agda`, `ECHIDNA_*`, `examples/go`, -> `proofs/coq/quantum/`) are now byte-identical to upstream (sha256-verified); maa is just behind. -> -> **Plan:** (1) `git rm -r absolute-zero`; (2) re-add as a submodule pinned to `7da92b3`; (3) wire -> `git submodule update --init` into CI; (4) keep PR #82's `§(e) VENDORED` classification — the submodule -> makes "resolve upstream" structurally true. -> -> Resolves #84 (completing what #83 started). diff --git a/docs/investigations/maa-framework-issue-84/README.adoc b/docs/investigations/maa-framework-issue-84/README.adoc new file mode 100644 index 0000000..f2ee7e9 --- /dev/null +++ b/docs/investigations/maa-framework-issue-84/README.adoc @@ -0,0 +1,41 @@ +== Investigation: maa-framework issue #84 (cross-repo) + +These documents resolve *`+hyperpolymath/maa-framework+` issue #84* — +"`Decide: is `+absolute-zero/+` a deliberate fork or stale vendor +copy?`". They are parked here in `+typed-wasm+` only because the +analysis session was scoped to this repo; the actual changes land in +`+maa-framework+` (see the handoff). + +*Sibling-estate context:* typed-wasm, maa-framework, and +`+absolute-zero+` are sibling projects in the hyperpolymath estate +(ECHIDNA property-based testing of proof soundness is a shared +integration point per this repo’s CLAUDE.md). + +=== Verdict + +*(B) stale vendor copy* — convert `+maa-framework/absolute-zero/+` to a +git submodule pinned to upstream `+hyperpolymath/absolute-zero+`. No +extraction needed; no maa-only proof work exists. Established via real +`+git diff+` of both clones (not summaries). + +=== Contents + +[width="100%",cols="50%,50%",options="header",] +|=== +|File |Purpose +|`+ISSUE-84-RESOLUTION.md+` |Full decision, authoritative diff tables, +paste-ready #84 comment + +|`+convert-to-submodule.sh+` |Guarded conversion script (re-verifies the +diff; hard-stops on any unexpected maa-only path). Run inside a +maa-framework checkout. + +|`+HANDOFF-maa-framework-session.md+` |Drop-in prompt for a Claude Code +session scoped to maa-framework to execute the conversion + close #84 +|=== + +=== Status + +Analysis complete. Execution (PR + closing #84) must run from a +maa-framework-scoped session — this typed-wasm session lacks write +access to that repo. diff --git a/docs/investigations/maa-framework-issue-84/README.md b/docs/investigations/maa-framework-issue-84/README.md deleted file mode 100644 index 5684db3..0000000 --- a/docs/investigations/maa-framework-issue-84/README.md +++ /dev/null @@ -1,32 +0,0 @@ - - - -# Investigation: maa-framework issue #84 (cross-repo) - -These documents resolve **`hyperpolymath/maa-framework` issue #84** — "Decide: is -`absolute-zero/` a deliberate fork or stale vendor copy?". They are parked here in -`typed-wasm` only because the analysis session was scoped to this repo; the actual -changes land in `maa-framework` (see the handoff). - -**Sibling-estate context:** typed-wasm, maa-framework, and `absolute-zero` are sibling -projects in the hyperpolymath estate (ECHIDNA property-based testing of proof soundness -is a shared integration point per this repo's CLAUDE.md). - -## Verdict - -**(B) stale vendor copy** — convert `maa-framework/absolute-zero/` to a git submodule -pinned to upstream `hyperpolymath/absolute-zero`. No extraction needed; no maa-only proof -work exists. Established via real `git diff` of both clones (not summaries). - -## Contents - -| File | Purpose | -|---|---| -| `ISSUE-84-RESOLUTION.md` | Full decision, authoritative diff tables, paste-ready #84 comment | -| `convert-to-submodule.sh` | Guarded conversion script (re-verifies the diff; hard-stops on any unexpected maa-only path). Run inside a maa-framework checkout. | -| `HANDOFF-maa-framework-session.md` | Drop-in prompt for a Claude Code session scoped to maa-framework to execute the conversion + close #84 | - -## Status - -Analysis complete. Execution (PR + closing #84) must run from a maa-framework-scoped -session — this typed-wasm session lacks write access to that repo. diff --git a/docs/proof-debt.adoc b/docs/proof-debt.adoc new file mode 100644 index 0000000..6989fb6 --- /dev/null +++ b/docs/proof-debt.adoc @@ -0,0 +1,73 @@ +== Proof Debt — typed-wasm + +*Schema*: +https://github.com/hyperpolymath/standards/blob/main/docs/TRUSTED-BASE-REDUCTION-POLICY.adoc[hyperpolymath/standards +`+TRUSTED-BASE-REDUCTION-POLICY.adoc+`] (standards#203). + +=== Current state + +*Zero soundness-relevant escape hatches* in this repo as of 2026-05-26; +*re-confirmed 2026-06-16* (`+idris2 --build src/abi/typed-wasm.ipkg+` → +exit 0, 24/24 modules; marker grep for `+believe_me+` / `+assert_total+` +/ `+postulate+` / `+sorry+` / `+Admitted+` / `+assert_smaller+` / holes +returns only docstring disclaimers). + +Verified by `+scripts/check-trusted-base.sh+` from +https://github.com/hyperpolymath/standards[hyperpolymath/standards] — +all matches found by syntactic scan were inside docstrings explicitly +stating the file does NOT use `+believe_me+` / `+assert_total+` / +`+postulate+` / `+sorry+` / `+Admitted+` (the "`no escape hatches`" +discipline pattern). + +____ +*Scope note.* This ledger covers the _Idris-model_ proof axis +(escape-hatch freedom in `+src/abi/+`). The complementary +_codegen→verified-wasm_ assurance axis (T1 execution gate … T5 +wasm-semantics tie-back) is tracked in +link:../PROOF-NEEDS.md[`+PROOF-NEEDS.md+`] §"`RECONCILIATION 2026-06-16 +(codegen climb)`". Those tiers are tests / decode-time checks in the +Rust trusted base, not Idris proof obligations, so they introduce no +escape-hatch debt here. +____ + +=== (a) DISCHARGED in this repo + +_(None — never any to discharge.)_ + +=== (b) BUDGETED — tested with a refutation budget + +_(None.)_ + +=== (c) NECESSARY AXIOM + +_(None.)_ + +=== (d) DEBT — actively to be closed + +_(None.)_ + +=== Preservation contract + +This file exists to assert the *zero-debt invariant* for the +`+scripts/check-trusted-base.sh+` CI gate (standards#211). Any future PR +that introduces a soundness-relevant escape hatch MUST either: + +[arabic] +. annotate the call site with a leading `+TRUSTED:+` / `+AXIOM:+` +comment, OR +. add an entry to this file under §(b) / §(c) / §(d). + +PRs that introduce un-annotated escape hatches will fail CI. + +=== Companion documents + +* https://github.com/hyperpolymath/standards/pull/195[standards#195] — +estate proof-debt audit. +* https://github.com/hyperpolymath/standards/pull/203[standards#203] — +trusted-base reduction policy (the schema this file follows). +* https://github.com/hyperpolymath/standards/pull/211[standards#211] — +`+check-trusted-base.sh+` CI enforcement. + +''''' + +🤖 Initial seed by Claude Code, 2026-05-26. diff --git a/docs/proof-debt.md b/docs/proof-debt.md deleted file mode 100644 index bf3dc8b..0000000 --- a/docs/proof-debt.md +++ /dev/null @@ -1,69 +0,0 @@ - - -# Proof Debt — typed-wasm - -**Schema**: [hyperpolymath/standards `TRUSTED-BASE-REDUCTION-POLICY.adoc`](https://github.com/hyperpolymath/standards/blob/main/docs/TRUSTED-BASE-REDUCTION-POLICY.adoc) (standards#203). - -## Current state - -**Zero soundness-relevant escape hatches** in this repo as of 2026-05-26; -**re-confirmed 2026-06-16** (`idris2 --build src/abi/typed-wasm.ipkg` → exit 0, -24/24 modules; marker grep for `believe_me` / `assert_total` / `postulate` / -`sorry` / `Admitted` / `assert_smaller` / holes returns only docstring -disclaimers). - -Verified by `scripts/check-trusted-base.sh` from -[hyperpolymath/standards](https://github.com/hyperpolymath/standards) — -all matches found by syntactic scan were inside docstrings explicitly -stating the file does NOT use `believe_me` / `assert_total` / -`postulate` / `sorry` / `Admitted` (the "no escape hatches" -discipline pattern). - -> **Scope note.** This ledger covers the _Idris-model_ proof axis (escape-hatch -> freedom in `src/abi/`). The complementary _codegen→verified-wasm_ assurance -> axis (T1 execution gate … T5 wasm-semantics tie-back) is tracked in -> [`PROOF-NEEDS.md`](../PROOF-NEEDS.md) §"RECONCILIATION 2026-06-16 (codegen -> climb)". Those tiers are tests / decode-time checks in the Rust trusted base, -> not Idris proof obligations, so they introduce no escape-hatch debt here. - -## (a) DISCHARGED in this repo - -*(None — never any to discharge.)* - -## (b) BUDGETED — tested with a refutation budget - -*(None.)* - -## (c) NECESSARY AXIOM - -*(None.)* - -## (d) DEBT — actively to be closed - -*(None.)* - -## Preservation contract - -This file exists to assert the **zero-debt invariant** for the -`scripts/check-trusted-base.sh` CI gate (standards#211). Any future PR -that introduces a soundness-relevant escape hatch MUST either: - -1. annotate the call site with a leading `TRUSTED:` / `AXIOM:` - comment, OR -2. add an entry to this file under §(b) / §(c) / §(d). - -PRs that introduce un-annotated escape hatches will fail CI. - -## Companion documents - -- [standards#195](https://github.com/hyperpolymath/standards/pull/195) — estate proof-debt audit. -- [standards#203](https://github.com/hyperpolymath/standards/pull/203) — trusted-base reduction policy (the schema this file follows). -- [standards#211](https://github.com/hyperpolymath/standards/pull/211) — `check-trusted-base.sh` CI enforcement. - ---- - -🤖 Initial seed by Claude Code, 2026-05-26. diff --git a/docs/tech-debt-2026-05-26.adoc b/docs/tech-debt-2026-05-26.adoc new file mode 100644 index 0000000..70af6be --- /dev/null +++ b/docs/tech-debt-2026-05-26.adoc @@ -0,0 +1,80 @@ +== Tech-Debt Audit — typed-wasm — 2026-05-26 + +*Source:* estate-wide automated scan 2026-05-26. *Companion:* +https://github.com/hyperpolymath/standards/tree/main/docs/audits[`+hyperpolymath/standards+` +2026-05-26-estate-*-debt audits]. *Combined severity:* `+LOW+`. + +This file records the _raw findings_ — it does not by itself fix the +debt. Each section ends with a '`Recommended next move`' line; closing +the debt is follow-up work. + +=== 1. Proof debt + +Scanner counted the following markers in proof-bearing files of this +repo: + +.... +files= 21 | Coq-Axm/Adm= 0 | Lean-srry/ax= 0 | Agda-pst= 0 | Idr-blv= 5 | Idr-prtl= 0 | Fstr-asm= 0 | TODO= 0 | Unsafe= 0 +.... + +*Total markers:* 5. *Severity:* `+>05+`. + +*Marker types* (any non-zero counts above): - Coq `+Axiom+`/`+Admitted+` +— unconditional proof escapes. - Lean `+sorry+`/`+axiom+` — Lean’s +equivalent. - Agda `+postulate+` — accepted axiomatically. - Idris2 +`+believe_me+`/`+assert_total+` — runtime-safe coercion / totality +assumption. - Idris2 top-level `+partial+` — totality-check waived. - F* +`+assume val+`/`+admit_p+` — F* admit. - `+TODO PROOF+` / `+OWED:+` — +self-documented debt markers. - `+unsafePerformIO+`/`+unsafeCoerce+` — +soundness-relevant escape hatches in Haskell/Rust source. + +*Recommended next move:* triage each finding into one of: (a) discharge +by proof, (b) cover with property-tests + a documented refutation +budget, or (c) annotate as a known/necessary axiom (e.g. `+funExt+`) in +`+docs/proof-debt.md+`. + +=== 2. Licence debt + +[cols=",",options="header",] +|=== +|Field |Value +|LICENSE file |`+LICENSE+` +|SPDX header |`+MPL-2.0+` +|Manifest licence |`+NONE+` +|Body classifier |`+Palimp-MPL-2.0+` +|Severity |`+ok+` +|=== + +*Recommended next move:* none for licence. + +=== 3. Documentation debt + +[cols=",",options="header",] +|=== +|Field |Value +|README lines |212 +|`+docs/+` files |59 +|`+docs/+` LoC |3405 +|CHANGELOG.md |Y +|CONTRIBUTING.md |Y +|CODE_OF_CONDUCT.md |Y +|SECURITY.md |Y +|Severity |`+OK+` +|=== + +*Recommended next move:* none for docs. + +=== Cross-references + +* Estate proof-debt audit: +`+hyperpolymath/standards/docs/audits/2026-05-26-estate-proof-debt.md+` +* Estate licence-debt audit: +`+hyperpolymath/standards/docs/audits/2026-05-26-estate-licence-debt.md+` +* Estate documentation-debt audit: +`+hyperpolymath/standards/docs/audits/2026-05-26-estate-documentation-debt.md+` + +''''' + +🤖 Generated by Claude Code estate-wide tech-debt scan (2026-05-26). +This file is informational — closing the debt is follow-up work owned by +the maintainer. diff --git a/docs/tech-debt-2026-05-26.md b/docs/tech-debt-2026-05-26.md deleted file mode 100644 index d8e48d9..0000000 --- a/docs/tech-debt-2026-05-26.md +++ /dev/null @@ -1,71 +0,0 @@ - - -# Tech-Debt Audit — typed-wasm — 2026-05-26 - -**Source:** estate-wide automated scan 2026-05-26. -**Companion:** [`hyperpolymath/standards` 2026-05-26-estate-*-debt audits](https://github.com/hyperpolymath/standards/tree/main/docs/audits). -**Combined severity:** `LOW`. - -This file records the *raw findings* — it does not by itself fix the debt. Each section ends with a 'Recommended next move' line; closing the debt is follow-up work. - -## 1. Proof debt - -Scanner counted the following markers in proof-bearing files of this repo: - -``` -files= 21 | Coq-Axm/Adm= 0 | Lean-srry/ax= 0 | Agda-pst= 0 | Idr-blv= 5 | Idr-prtl= 0 | Fstr-asm= 0 | TODO= 0 | Unsafe= 0 -``` - -**Total markers:** 5. **Severity:** `>05`. - -**Marker types** (any non-zero counts above): -- Coq `Axiom`/`Admitted` — unconditional proof escapes. -- Lean `sorry`/`axiom` — Lean's equivalent. -- Agda `postulate` — accepted axiomatically. -- Idris2 `believe_me`/`assert_total` — runtime-safe coercion / totality assumption. -- Idris2 top-level `partial` — totality-check waived. -- F\* `assume val`/`admit_p` — F\* admit. -- `TODO PROOF` / `OWED:` — self-documented debt markers. -- `unsafePerformIO`/`unsafeCoerce` — soundness-relevant escape hatches in Haskell/Rust source. - -**Recommended next move:** triage each finding into one of: (a) discharge by proof, (b) cover with property-tests + a documented refutation budget, or (c) annotate as a known/necessary axiom (e.g. `funExt`) in `docs/proof-debt.md`. - -## 2. Licence debt - -| Field | Value | -|---|---| -| LICENSE file | `LICENSE` | -| SPDX header | `MPL-2.0` | -| Manifest licence | `NONE` | -| Body classifier | `Palimp-MPL-2.0` | -| Severity | `ok` | - -**Recommended next move:** none for licence. - -## 3. Documentation debt - -| Field | Value | -|---|---| -| README lines | 212 | -| `docs/` files | 59 | -| `docs/` LoC | 3405 | -| CHANGELOG.md | Y | -| CONTRIBUTING.md | Y | -| CODE_OF_CONDUCT.md | Y | -| SECURITY.md | Y | -| Severity | `OK` | - -**Recommended next move:** none for docs. - -## Cross-references - -- Estate proof-debt audit: `hyperpolymath/standards/docs/audits/2026-05-26-estate-proof-debt.md` -- Estate licence-debt audit: `hyperpolymath/standards/docs/audits/2026-05-26-estate-licence-debt.md` -- Estate documentation-debt audit: `hyperpolymath/standards/docs/audits/2026-05-26-estate-documentation-debt.md` - ---- - -🤖 Generated by Claude Code estate-wide tech-debt scan (2026-05-26). This file is informational — closing the debt is follow-up work owned by the maintainer. diff --git a/llm-warmup-dev.adoc b/llm-warmup-dev.adoc new file mode 100644 index 0000000..27674ba --- /dev/null +++ b/llm-warmup-dev.adoc @@ -0,0 +1,19 @@ +== LLM Warmup — typed-wasm (Developer) + +=== What is typed-wasm? + +See README.adoc for overview. + +=== Key Commands + +* `+just setup+` — set up development environment +* `+just build+` — build the project +* `+just test+` — run tests +* `+just doctor+` — diagnose issues +* `+just heal+` — attempt auto-repair + +=== Quick Context + +* License: MPL-2.0 +* Part of hyperpolymath ecosystem +* See EXPLAINME.adoc for architecture diff --git a/llm-warmup-dev.md b/llm-warmup-dev.md deleted file mode 100644 index b79b6d5..0000000 --- a/llm-warmup-dev.md +++ /dev/null @@ -1,16 +0,0 @@ -# LLM Warmup — typed-wasm (Developer) - -## What is typed-wasm? -See README.adoc for overview. - -## Key Commands -- `just setup` — set up development environment -- `just build` — build the project -- `just test` — run tests -- `just doctor` — diagnose issues -- `just heal` — attempt auto-repair - -## Quick Context -- License: MPL-2.0 -- Part of hyperpolymath ecosystem -- See EXPLAINME.adoc for architecture diff --git a/llm-warmup-user.adoc b/llm-warmup-user.adoc new file mode 100644 index 0000000..884ed6c --- /dev/null +++ b/llm-warmup-user.adoc @@ -0,0 +1,19 @@ +== LLM Warmup — typed-wasm (User) + +=== What is typed-wasm? + +See README.adoc for overview. + +=== Key Commands + +* `+just setup+` — set up development environment +* `+just build+` — build the project +* `+just test+` — run tests +* `+just doctor+` — diagnose issues +* `+just heal+` — attempt auto-repair + +=== Quick Context + +* License: MPL-2.0 +* Part of hyperpolymath ecosystem +* See EXPLAINME.adoc for architecture diff --git a/llm-warmup-user.md b/llm-warmup-user.md deleted file mode 100644 index 64b7d4a..0000000 --- a/llm-warmup-user.md +++ /dev/null @@ -1,16 +0,0 @@ -# LLM Warmup — typed-wasm (User) - -## What is typed-wasm? -See README.adoc for overview. - -## Key Commands -- `just setup` — set up development environment -- `just build` — build the project -- `just test` — run tests -- `just doctor` — diagnose issues -- `just heal` — attempt auto-repair - -## Quick Context -- License: MPL-2.0 -- Part of hyperpolymath ecosystem -- See EXPLAINME.adoc for architecture diff --git a/src/abi/README.md b/src/abi/README.adoc similarity index 54% rename from src/abi/README.md rename to src/abi/README.adoc index 81a9065..1e5005c 100644 --- a/src/abi/README.md +++ b/src/abi/README.adoc @@ -1,16 +1,11 @@ - +== src/abi — Idris2 ABI Layer -# src/abi — Idris2 ABI Layer +This directory contains the Idris2 formal proofs for both roles of +`+typed-wasm+` (see ADR-004 in `+.machine_readable/6a2/META.a2ml+`). -This directory contains the Idris2 formal proofs for both roles of `typed-wasm` -(see ADR-004 in `.machine_readable/6a2/META.a2ml`). +=== Directory Layout -## Directory Layout - -``` +.... src/abi/ ├── TypedWasm/ABI/ ← Role 1: TypeLL type safety for WasmGC linear memory │ ├── Levels.idr Type safety level hierarchy (L1-L10 initial mapping) @@ -30,29 +25,32 @@ src/abi/ │ └── ABI.idr Cross-language calling conventions │ └── typed-wasm.ipkg Idris2 package file (covers TypedWasm/ABI/ only) -``` +.... -## Role Separation +=== Role Separation -**`TypedWasm/ABI/`** is the primary role: the TypeLL progressive type safety proofs -for WasmGC linear memory. These proofs are part of the default checked package -(`typed-wasm.ipkg`). No `believe_me` is permitted here. +*`+TypedWasm/ABI/+`* is the primary role: the TypeLL progressive type +safety proofs for WasmGC linear memory. These proofs are part of the +default checked package (`+typed-wasm.ipkg+`). No `+believe_me+` is +permitted here. -**`layout/`** is the secondary role: formally verified type layout and ABI -conventions for languages that compile to typed WasmGC (AffineScript, Ephapax). -These proofs are developed separately from the TypeLL level hierarchy because -the two concerns — WASM memory safety and cross-language interop — are -independent. They share the same Idris2 tooling but are not logically coupled. +*`+layout/+`* is the secondary role: formally verified type layout and +ABI conventions for languages that compile to typed WasmGC +(AffineScript, Ephapax). These proofs are developed separately from the +TypeLL level hierarchy because the two concerns — WASM memory safety and +cross-language interop — are independent. They share the same Idris2 +tooling but are not logically coupled. -## Pipeline Position +=== Pipeline Position -``` +.... katagoria → typell → typed-wasm → PanLL ↑ both subtrees live here -``` +.... -Type theory ideas originate in `katagoria` (research), are promoted to `typell` -(the open-ended progressive verification kernel), and applied here: -- `TypedWasm/ABI/` applies TypeLL to WASM memory safety -- `layout/` applies Idris2 ABI methodology to cross-language binary conventions +Type theory ideas originate in `+katagoria+` (research), are promoted to +`+typell+` (the open-ended progressive verification kernel), and applied +here: - `+TypedWasm/ABI/+` applies TypeLL to WASM memory safety - +`+layout/+` applies Idris2 ABI methodology to cross-language binary +conventions diff --git a/tools/tree-sitter-twasm/README.adoc b/tools/tree-sitter-twasm/README.adoc new file mode 100644 index 0000000..085b69b --- /dev/null +++ b/tools/tree-sitter-twasm/README.adoc @@ -0,0 +1,96 @@ +== tree-sitter-twasm + +Tree-sitter grammar for `+.twasm+` (typed-wasm surface syntax). + +=== Status: v1 grammar (Phase 0 grammar extension) + +The grammar now covers enough of `+examples/01-single-module.twasm+` to +parse the full file: region declarations, memory declarations, function +declarations (parameters / return types / effects), and the statement +and expression forms used in example 01. + +==== What works today + +* *Region declarations* — `+region Name { ... }+`, array quantifiers +`+[N]+`, primitives, region refs (`+@T+`), `+opt+`, fixed-size arrays +(`+u8[24]+`), `+align N;+`, `+where+` range constraints +* *Memory declarations* — +`+memory Name { initial: N; maximum: N; place X at N; ... }+` +* *Function declarations* — +`+fn name(params) -> ret effects { ... } { body }+` +** parameter modes: `+®ion+`, `+&mut region+`, +`+own region+`, and bare typed parameters +** effects: `+Read+`, `+Write+`, `+Alloc+`, `+Free+`, `+ReadRegion(R)+`, +`+WriteRegion(R)+` +* *Statements* — `+region.get+`, `+region.set+`, `+region.scan+`, +`+let [mut] name [: type] = expr;+`, assignment, `+if ... else+`, +`+return+` +* *Expressions* — literals (`+int+`, `+float+`, `+true+`, `+false+`, +`+null+`), identifiers, `+$region_var+`, binary ops (`++ - * / %+`, +`+== != < > <= >=+`, `+&& ||+`), unary (`+-+`, `+!+`), +`+is_null(expr)+`, parenthesised +* *Field paths* — single and nested (`+.pos.x+`) +* *`+//+` line comments* + +==== What does NOT work yet (next Track A PR) + +* Imports / exports (`+import region X from "mod"+`, +`+export region X+`) +* Invariant declarations and `+proof+` statements +* `+const+` declarations +* Block-expression `+if ... yield+` +* Match on union regions +* L13–L16 surface (`+isolated+`, `+session+`, `+capability+`, +`+choreography+`) +* L11/L12 surface (`+cost_bound+`, `+fresh+`, `+version_of+`, +`+region.sync+`) +* Lifetime annotations on function decls +* `+striated+` region layout + +Scope-wise the v1 grammar covers maybe 60–70% of `+spec/grammar.ebnf+` +by production count. The remainder is sequenced for the next Track A PR. + +=== Why in-tree first + +Production-path Phase 0 §Track A specifies "`in-tree at +`+tools/tree-sitter-twasm/+`, extract later`". Rationale: changes to +`+spec/grammar.ebnf+` and the tree-sitter grammar move in lockstep +during the migration; cross-repo coordination overhead while iterating +would slow Phase 1. When the grammar reaches full EBNF coverage and +stabilises, it gets extracted to `+hyperpolymath/tree-sitter-twasm+` for +the Linguist + npm publication step (Phase 4 deliverable). + +=== Building and testing + +Requires `+tree-sitter-cli+` (install via +`+npm install -g tree-sitter-cli+` or +`+cargo install tree-sitter-cli+`): + +[source,bash] +---- +cd tools/tree-sitter-twasm +tree-sitter generate # generate parser from grammar.js +tree-sitter test # run corpus tests +tree-sitter parse ../../examples/01-single-module.twasm # parse a real example +---- + +The generated `+src/parser.c+` and `+src/grammar.json+` are gitignored; +regenerate locally via `+tree-sitter generate+`. + +=== How this fits the production path + +[width="100%",cols="25%,75%",options="header",] +|=== +|Phase |This grammar’s role +|*0* (current) |v1 grammar — parses `+examples/01-single-module.twasm+` +fully + +|*1* |Extend to remaining `+spec/grammar.ebnf+` productions (imports, +L11-L16, match, proof); back the Idris2 parser + +|*4* |Extract to `+hyperpolymath/tree-sitter-twasm+`; publish to npm; +submit to Linguist +|=== + +Tracked under issue +https://github.com/hyperpolymath/typed-wasm/issues/48[#48 (Phase 0)]. diff --git a/tools/tree-sitter-twasm/README.md b/tools/tree-sitter-twasm/README.md deleted file mode 100644 index 117f6a5..0000000 --- a/tools/tree-sitter-twasm/README.md +++ /dev/null @@ -1,78 +0,0 @@ -# tree-sitter-twasm - -Tree-sitter grammar for `.twasm` (typed-wasm surface syntax). - -## Status: v1 grammar (Phase 0 grammar extension) - -The grammar now covers enough of `examples/01-single-module.twasm` to -parse the full file: region declarations, memory declarations, -function declarations (parameters / return types / effects), and the -statement and expression forms used in example 01. - -### What works today - -- **Region declarations** — `region Name { ... }`, array quantifiers `[N]`, - primitives, region refs (`@T`), `opt`, fixed-size arrays (`u8[24]`), - `align N;`, `where` range constraints -- **Memory declarations** — `memory Name { initial: N; maximum: N; place X at N; ... }` -- **Function declarations** — `fn name(params) -> ret effects { ... } { body }` - - parameter modes: `®ion`, `&mut region`, `own region`, and bare typed parameters - - effects: `Read`, `Write`, `Alloc`, `Free`, `ReadRegion(R)`, `WriteRegion(R)` -- **Statements** — `region.get`, `region.set`, `region.scan`, `let [mut] name [: type] = expr;`, - assignment, `if ... else`, `return` -- **Expressions** — literals (`int`, `float`, `true`, `false`, `null`), - identifiers, `$region_var`, binary ops (`+ - * / %`, `== != < > <= >=`, `&& ||`), - unary (`-`, `!`), `is_null(expr)`, parenthesised -- **Field paths** — single and nested (`.pos.x`) -- **`//` line comments** - -### What does NOT work yet (next Track A PR) - -- Imports / exports (`import region X from "mod"`, `export region X`) -- Invariant declarations and `proof` statements -- `const` declarations -- Block-expression `if ... yield` -- Match on union regions -- L13–L16 surface (`isolated`, `session`, `capability`, `choreography`) -- L11/L12 surface (`cost_bound`, `fresh`, `version_of`, `region.sync`) -- Lifetime annotations on function decls -- `striated` region layout - -Scope-wise the v1 grammar covers maybe 60–70% of `spec/grammar.ebnf` -by production count. The remainder is sequenced for the next Track A -PR. - -## Why in-tree first - -Production-path Phase 0 §Track A specifies "in-tree at -`tools/tree-sitter-twasm/`, extract later". Rationale: changes to -`spec/grammar.ebnf` and the tree-sitter grammar move in lockstep during -the migration; cross-repo coordination overhead while iterating would -slow Phase 1. When the grammar reaches full EBNF coverage and stabilises, -it gets extracted to `hyperpolymath/tree-sitter-twasm` for the Linguist -+ npm publication step (Phase 4 deliverable). - -## Building and testing - -Requires `tree-sitter-cli` (install via `npm install -g tree-sitter-cli` -or `cargo install tree-sitter-cli`): - -```bash -cd tools/tree-sitter-twasm -tree-sitter generate # generate parser from grammar.js -tree-sitter test # run corpus tests -tree-sitter parse ../../examples/01-single-module.twasm # parse a real example -``` - -The generated `src/parser.c` and `src/grammar.json` are gitignored; -regenerate locally via `tree-sitter generate`. - -## How this fits the production path - -| Phase | This grammar's role | -|-------|---------------------| -| **0** (current) | v1 grammar — parses `examples/01-single-module.twasm` fully | -| **1** | Extend to remaining `spec/grammar.ebnf` productions (imports, L11-L16, match, proof); back the Idris2 parser | -| **4** | Extract to `hyperpolymath/tree-sitter-twasm`; publish to npm; submit to Linguist | - -Tracked under issue [#48 (Phase 0)](https://github.com/hyperpolymath/typed-wasm/issues/48).