Skip to content

feat(abi): add Rust/SPARK ABI seam + abi-verify CI gate (Refs standards#134) - #95

Merged
hyperpolymath merged 2 commits into
mainfrom
proof-debt/standards-134-spark-seam
May 20, 2026
Merged

feat(abi): add Rust/SPARK ABI seam + abi-verify CI gate (Refs standards#134)#95
hyperpolymath merged 2 commits into
mainfrom
proof-debt/standards-134-spark-seam

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Estate language policy (standards/rhodium-standard-repositories/spec/LANGUAGE-POLICY.adoc §Terminology) requires Rust projects to be "designed to admit SPARK/Ada modules across a stable Idris2-typed boundary, with Zig as the FFI layer." Ephapax has a Coq formal/ metatheory and an Idris2 src/formal/ region/linearity metatheory but no named SPARK admission seam — standards#134 flags this as residual proof debt.

This PR is the scaffolding pass: name the obligations, give them a machine-checked file, gate them in CI. No new discharges — existing ones (splitLinearCoverage, noEscapeTheorem) are CITED from the seam; the vacuous-wrapper problem in regionSafetyExtract / noGCExtract is FLAGGED honestly (it's vacuous: body is the input unchanged, ROADMAP claiming them "complete" is misleading).

What's added

FileRole
src/abi/Ephapax/ABI/Types.idrBoundary types: Qual, Ty, Term, CtxEntry/TypeCtx, SExpr, WasmExpr, RegionId. Constructor order ABI-significant, matches Rust enums in src/ephapax-{syntax,typing,ir,wasm}/.
src/abi/Ephapax/ABI/Invariants.idrE1–E6 register (see table below).
src/abi/Ephapax/ABI/Foreign.idrZig/WASM-FFI boundary: InU32/InI32Magnitude (Integer-bounded, not Nat — carries the proof-of-work#63 unhang lesson), CompileResult C-ABI codes with round-trip discharge, and compileOkImpliesWasmTyped tying CompileOk to an E5 certificate.
src/abi/ephapax-abi.ipkgIdris2 package for the Ephapax.ABI.* namespace.
.github/workflows/abi-verify.ymlHARD GATE — rebuilds the seam on every PR/push touching src/abi/** (snazzybucket/idris2 container). Mirrors proof-of-work's abi-verify.yml.
RUST-SPARK-STANCE.adocTop-level stance doc, structurally identical to proof-of-work's.

Invariant register

IDPropertyStatus
E1Type preservationOWED — Coq preservationAdmitted (ephapax#92)
E2Linear consumptionPARTIAL — head form DISCHARGED via splitLinearCoverage (PR#85); control-flow form OWED
E3Region no-escapePARTIAL — narrow form DISCHARGED via noEscapeTheorem; operational form OWED
E4No-runtime-GCOWEDnoGCExtract is vacuous (returns input pair)
E5WASM compilation correctnessOWED — no formalisation today
E6IR lowering correctnessOWED — no formalisation today

Verification (local, Idris2 0.8.0)

cd src/abi && idris2 --build ephapax-abi.ipkg
# → EXIT 0, 3/3 modules built

Honest gaps surfaced by this audit

  • regionSafetyExtract / noGCExtract in src/formal/Ephapax/Formal/RegionLinear.idr are vacuous — bodies are = ne and = (ne, lc) (return inputs unchanged). The proofs are sound (no escape hatches) but content-free. ROADMAP citing them as "regionSafetyTheorem" / "noGCTheorem" complete is therefore overstated — flagged in seam (E3, E4) and stance doc.
  • No WASM compilation formalisation exists anywhere in the repo. E5 is the highest-leverage compiler-correctness gap.
  • ephapax-parse-tests.ipkg fails on origin/main (testLexPositions/parseWithBuf undefined) — independent of the seam, flagged for awareness.

Bounds encoding (Integer not Nat)

Foreign.idr uses Integer for the u32/i32 bounds, not Nat, deliberately carrying the proof-of-work#63 lesson: a Nat constant of 2^32 under LT n bound in a constructor type forces the Idris2 0.8.0 elaborator to reduce the literal (~4×10⁹ S ctors) and hangs --build. The boundary predicate is So (natToInteger n < bound) instead — propositionally equivalent, no unary expansion. Don't rewrite back.

Refs

Refs standards#134 (NOT Closes — joint-close on agreement). #134 also has:

  • ephapax#88 OPEN — 14 idris2/src/*.idr SPDX headers
  • ephapax#92 OPEN — Qed.Admitted. on preservation (honesty fix; this stance doc cites it)

Both are independent of this seam.

Test plan

  • cd src/abi && idris2 --build ephapax-abi.ipkg → exit 0 locally (3/3 modules)
  • abi-verify.yml green on this PR's CI run
  • Existing Rust CI unaffected (src/abi/ is independent of src/ephapax-*/ crates)

🤖 Generated with Claude Code

…ds#134)
Estate language policy
(standards/rhodium-standard-repositories/spec/LANGUAGE-POLICY.adoc
§Terminology) requires Rust projects to be "designed to admit SPARK/Ada
modules across a stable Idris2-typed boundary, with Zig as the FFI
layer." Ephapax has a Coq `formal/` metatheory and an Idris2
`src/formal/` region/linearity metatheory but no named SPARK admission
seam — standards#134 flags this as residual proof debt.
This PR is the scaffolding pass: name the obligations, give them a
machine-checked file, gate them in CI. No new discharges; the existing
ones (`splitLinearCoverage` / `noEscapeTheorem`) are CITED from the
seam, and the vacuous-wrapper issues in `regionSafetyExtract` /
`noGCExtract` are FLAGGED honestly.
Added:
- `src/abi/Ephapax/ABI/Types.idr` — boundary types: `Qual`, `Ty`,
`Term`, `CtxEntry`/`TypeCtx`, `SExpr`, `WasmExpr`, `RegionId`.
Constructor order is ABI-significant and matches the Rust enums in
`src/ephapax-{syntax,typing,ir,wasm}/`.
- `src/abi/Ephapax/ABI/Invariants.idr` — E1–E6 invariant register:
* E1 type preservation (OWED — Coq `preservation` Admitted, see
ephapax#92).
* E2 linear consumption (head-form DISCHARGED via
`splitLinearCoverage`, control-flow form OWED).
* E3 region no-escape (narrow form DISCHARGED via
`noEscapeTheorem`, operational form OWED).
* E4 no-runtime-GC (OWED — `noGCExtract` is vacuous, flagged).
* E5 WASM compilation correctness (OWED — no formalisation today).
* E6 IR lowering correctness (OWED — no formalisation today).
- `src/abi/Ephapax/ABI/Foreign.idr` — Zig/WASM-FFI boundary:
`InU32`/`InI32Magnitude` range obligations (Integer-bounded, not
Nat — carrying the proof-of-work#63 unhang lesson), `CompileResult`
C-ABI codes with round-trip discharge, and
`compileOkImpliesWasmTyped` tying CompileOk to an E5 certificate.
- `src/abi/ephapax-abi.ipkg` — Idris2 package for the
`Ephapax.ABI.*` namespace.
- `.github/workflows/abi-verify.yml` — HARD GATE: rebuilds the seam
on every PR/push touching `src/abi/**`, snazzybucket/idris2
container (estate-standard image). Mirrors the proof-of-work
`abi-verify.yml` exactly.
- `RUST-SPARK-STANCE.adoc` — top-level stance doc mirroring
proof-of-work's structure: correctness-critical surface map, seam
file table, SPARK admission path, honest-gaps section (preservation
Admitted, vacuous wrappers, no WASM formalisation, parse-tests
baseline-rot).
Verified locally (Idris2 0.8.0):
cd src/abi && idris2 --build ephapax-abi.ipkg # → EXIT 0, 3/3 modules
Refs standards#134 (NOT Closes — joint-close on agreement; #134 also
has ephapax#88 open for SPDX headers and ephapax#92 open for the
`preservation` Qed→Admitted honesty fix, both independent of this).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
@hyperpolymath
hyperpolymath merged commit 9bcde6c into mainMay 20, 2026
@hyperpolymath
hyperpolymath deleted the proof-debt/standards-134-spark-seam branch May 20, 2026 17:46
hyperpolymath added a commit that referenced this pull request May 20, 2026
…andards#134) (#103)
## Summary
`.machine_readable/6a2/STATE.a2ml` claimed:
```
# No active blockers. Formal proofs FULLY CLOSED (67 Qed, 0 Admitted).
```
This was wrong on both axes:
- `formal/Semantics.v::preservation` carries `Qed.` but `coqc` 8.18.0
rejects it with "Attempt to save an incomplete proof (there are
remaining open goals)" — the proof never actually closed. PR#92 (MERGED)
marked it `Admitted.` to restore CI green; PR#102 (OPEN) reduces the
open-goal count from 910 to ~29 via the standard remember-cfg
preservation pattern. So there's at least 1 `Admitted`, not 0.
- `src/formal/Ephapax/Formal/RegionLinear.idr::regionSafetyExtract` /
`noGCExtract` are **vacuous tautological wrappers** (body is the input
unchanged: `= ne` / `= (ne, lc)`). ROADMAP citing them as
"regionSafetyTheorem"/"noGCTheorem" complete is overstated. The honest
E3 (region no-escape) and E4 (no-runtime-GC) obligations are stated in
`src/abi/Ephapax/ABI/Invariants.idr` (the Rust/SPARK seam landed via
PR#95-MERGED).
## What changed
- `phase`, `next_action`, `last_action`, `updated` brought to
2026-05-20.
- `@blockers` block now lists the residual proof debt accurately:
- Semantics.v `preservation` Admitted (with handoff doc pointer)
- vacuous RegionLinear wrappers
- E1–E6 invariant register from the new ABI seam
## What's not in this PR
No source/proof changes. This is purely the machine-readable artefact
catching up to the actual code state. The human-readable docs
(`ROADMAP.adoc`, `PROOF-NEEDS.md`, `RUST-SPARK-STANCE.adoc`) already
reflect this after the 2026-05-20 batch of PR#92 + #95 + #102.
## Refs
Refs standards#134 (**NOT Closes** — joint-close on agreement).
## Test plan
- [x] No `.v` / `.idr` / Rust files touched — build state unaffected
- [x] STATE.a2ml syntax preserved (comment lines + `@state` block +
`@blockers` block + matching `@end`s)
- [ ] CI green (no jobs apply to machine-readable artefacts)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@hyperpolymath