Skip to content

Commit 4ee5893

Browse files
A2ML parser totality + correctness, Merkle combiner generalization, proof ledger (#32)
Parser made total by structural recursion (zero covering), inverted-unless and end-of-input bugs fixed; Merkle construction/verification/soundness generalized over the hash combiner (merkleCorrectWith); repo hygiene (untrack build artifacts); proof-campaign ledger (PROOFS.adoc) and post-migration re-entry runbook (AFTER-MIGRATION.adoc). FFI/e2e reconciled to main's #31 implementations.
1 parent d7d1ace commit 4ee5893

37 files changed

Lines changed: 926 additions & 3186 deletions

File tree

.github/workflows/echidna-validation.yml

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,26 @@ jobs:
3131

3232
- name: Dangerous pattern scan (Idris2)
3333
run: |
34-
echo "=== Idris2 Dangerous Pattern Scan ==="
34+
echo "=== Idris2 Dangerous Pattern Scan (code only; comments excluded) ==="
3535
ISSUES=0
3636
for pattern in "believe_me" "assert_total" "assert_smaller" "unsafePerformIO"; do
37-
FOUND=$(grep -rn "$pattern" ochrance-core/ modules/ src/abi/ --include="*.idr" 2>/dev/null | wc -l || echo 0)
38-
if [ "$FOUND" -gt 0 ]; then
39-
echo "CRITICAL: Found $FOUND instances of '$pattern'"
40-
grep -rn "$pattern" ochrance-core/ modules/ src/abi/ --include="*.idr" 2>/dev/null
41-
ISSUES=$((ISSUES + FOUND))
37+
# Strip doc comments (||| ...) and line comments (-- ...) before
38+
# matching, so documentation that merely names a pattern is not
39+
# flagged: only genuine uses in code count. Without this, a doc
40+
# string like "this proof needs no assert_smaller" would fail the gate.
41+
MATCHES=""
42+
for f in $(find ochrance-core/ src/abi/ -name "*.idr" 2>/dev/null); do
43+
M=$(sed -e 's/|||.*$//' -e 's/--.*$//' "$f" | grep -n "$pattern" | sed "s|^|$f:|" || true)
44+
[ -n "$M" ] && MATCHES="${MATCHES}${M}"$'\n'
45+
done
46+
N=$(printf '%s' "$MATCHES" | grep -c . || true)
47+
if [ "$N" -gt 0 ]; then
48+
echo "CRITICAL: Found $N use(s) of '$pattern' in code:"
49+
printf '%s\n' "$MATCHES"
50+
ISSUES=$((ISSUES + N))
4251
fi
4352
done
44-
echo "Total dangerous patterns: $ISSUES"
53+
echo "Total dangerous patterns (in code): $ISSUES"
4554
echo "dangerous_count=$ISSUES" >> $GITHUB_OUTPUT
4655
4756
if [ "$ISSUES" -gt 0 ]; then
@@ -53,7 +62,7 @@ jobs:
5362
run: |
5463
echo "=== Totality Enforcement ==="
5564
MISSING=0
56-
for f in $(find ochrance-core/ modules/ src/abi/ -name "*.idr" 2>/dev/null); do
65+
for f in $(find ochrance-core/ src/abi/ -name "*.idr" 2>/dev/null); do
5766
if ! grep -q "%default total" "$f"; then
5867
echo "WARNING: $f missing '%default total'"
5968
MISSING=$((MISSING + 1))
@@ -67,11 +76,11 @@ jobs:
6776
- name: Partial function check
6877
run: |
6978
echo "=== Partial Function Check ==="
70-
PARTIAL=$(grep -rn "^partial" ochrance-core/ modules/ src/abi/ --include="*.idr" 2>/dev/null | wc -l || echo 0)
79+
PARTIAL=$(grep -rn "^partial" ochrance-core/ src/abi/ --include="*.idr" 2>/dev/null | wc -l || echo 0)
7180
echo "Explicitly partial functions: $PARTIAL"
7281
if [ "$PARTIAL" -gt 0 ]; then
7382
echo "Review required:"
74-
grep -rn "^partial" ochrance-core/ modules/ src/abi/ --include="*.idr" 2>/dev/null
83+
grep -rn "^partial" ochrance-core/ src/abi/ --include="*.idr" 2>/dev/null
7584
fi
7685
7786
- name: FFI stub status
@@ -100,7 +109,7 @@ jobs:
100109
run: |
101110
echo "## ECHIDNA Validation Results" >> $GITHUB_STEP_SUMMARY
102111
echo "" >> $GITHUB_STEP_SUMMARY
103-
echo "- Scanned: ochrance-core/, modules/, src/abi/, ffi/zig/" >> $GITHUB_STEP_SUMMARY
112+
echo "- Scanned: ochrance-core/, src/abi/, ffi/zig/" >> $GITHUB_STEP_SUMMARY
104113
echo "- Checks: dangerous patterns (believe_me etc), totality enforcement, partial functions, FFI stub status, Zig safety" >> $GITHUB_STEP_SUMMARY
105114
echo "" >> $GITHUB_STEP_SUMMARY
106115
echo "*Powered by ECHIDNA neurosymbolic verification*" >> $GITHUB_STEP_SUMMARY

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ htmlcov/
8080

8181
# Zig
8282
**/zig-out/
83+
**/zig-cache/
8384
**/.zig-cache/
8485
**/zig-cache/
8586

ABI-FFI-README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,8 @@ zig build test # Run Zig unit tests
185185
# Ensure libochrance.so is on LD_LIBRARY_PATH
186186
export LD_LIBRARY_PATH="$PWD/ffi/zig/zig-out/lib:$LD_LIBRARY_PATH"
187187

188-
# Type-check and build
188+
# Type-check and build (the core package includes the filesystem subsystem)
189189
idris2 --build ochrance.ipkg
190-
idris2 --build ochrance-fs.ipkg
191190
```
192191

193192
### Cross-Compile

CLAUDE.md

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,26 @@ ochrance/
2121
│ │ ├── Interface.idr # VerifiedSubsystem interface
2222
│ │ ├── Proof.idr # Proof witnesses
2323
│ │ └── Error.idr # q/p/z error taxonomy
24+
│ ├── Filesystem/ # Reference VerifiedSubsystem
25+
│ │ ├── Types.idr # FSState, Block, FSSnapshot
26+
│ │ ├── Merkle.idr # Verified Merkle tree + merkleCorrect theorem
27+
│ │ ├── Verify.idr # Verification logic
28+
│ │ └── Repair.idr # Linear type repair
2429
│ └── FFI/
30+
│ ├── Crypto.idr # FFI to libochrance.so (BLAKE3/SHA-256/Ed25519)
2531
│ └── Echidna.idr # FFI to libechidna.so
26-
├── modules/
27-
│ └── filesystem/ # Reference VerifiedSubsystem
28-
│ ├── Types.idr # FSState, Block, FSSnapshot
29-
│ ├── Merkle.idr # Verified Merkle tree
30-
│ ├── Verify.idr # Verification logic
31-
│ └── Repair.idr # Linear type repair
3232
├── tests/ # Test suite
33-
├── ochrance.ipkg # Core package
34-
└── ochrance-fs.ipkg # Filesystem module package
33+
└── ochrance.ipkg # Core package (includes the filesystem subsystem)
3534
```
3635

3736
## Build Commands
3837

3938
```bash
40-
# Type-check core
39+
# Type-check core (includes the filesystem subsystem)
4140
idris2 --build ochrance.ipkg
4241

43-
# Type-check filesystem module
44-
idris2 --build ochrance-fs.ipkg
45-
4642
# Check single file
47-
idris2 --check ochrance-core/A2ML/Lexer.idr
43+
idris2 --check ochrance-core/Ochrance/A2ML/Lexer.idr
4844

4945
# REPL
5046
idris2 --repl ochrance.ipkg

EXPLAINME.adoc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@ Also integrates with ECHIDNA for neural proof synthesis — FFI calls to libechi
5050
| `ochrance-core/Framework/Proof.idr` | Proof witness types; generic proof structure for all subsystems
5151
| `ochrance-core/Framework/Error.idr` | Error taxonomy: q/* (query), p/* (proof), z/* (zone/system)
5252
| `ochrance-core/Framework/FFI/Echidna.idr` | FFI to ECHIDNA neural prover (via Zig C ABI)
53-
| `modules/filesystem/Types.idr` | Filesystem types: FSState, Block, FSSnapshot with dependent proofs
54-
| `modules/filesystem/Merkle.idr` | Verified Merkle tree: size-indexed with compile-time structure proofs (placeholder XOR hashes)
55-
| `modules/filesystem/Verify.idr` | Verification logic: block hashes, tree integrity, attestation signatures
56-
| `modules/filesystem/Repair.idr` | Linear type repair: repair operations consume old state (Quantity 1)
57-
| `ochrance.ipkg` | Package definition for core library
58-
| `ochrance-fs.ipkg` | Package definition for filesystem module
53+
| `ochrance-core/Ochrance/Filesystem/Types.idr` | Filesystem types: FSState, Block, FSSnapshot with dependent proofs
54+
| `ochrance-core/Ochrance/Filesystem/Merkle.idr` | Verified Merkle tree: height-indexed with compile-time structure proofs and the `merkleCorrect` inclusion-soundness theorem (placeholder XOR hashes for the pure path)
55+
| `ochrance-core/Ochrance/Filesystem/Verify.idr` | Verification logic: block hashes, tree integrity, attestation signatures
56+
| `ochrance-core/Ochrance/Filesystem/Repair.idr` | Linear type repair: repair operations consume old state (Quantity 1)
57+
| `ochrance.ipkg` | Package definition for the core library (includes the filesystem subsystem)
5958
|===
6059

6160
== Testing Critical Paths

Justfile

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,6 @@ check-versions:
2424
build-core:
2525
idris2 --build ochrance.ipkg
2626

27-
# Build filesystem module
28-
build-fs:
29-
idris2 --build ochrance-fs.ipkg
30-
3127
# Build ABI layer
3228
build-abi:
3329
idris2 --build ochrance-abi.ipkg
@@ -37,12 +33,11 @@ build-ffi:
3733
cd ffi/zig && zig build
3834

3935
# Build all components
40-
build: build-core build-fs build-abi build-ffi
36+
build: build-core build-abi build-ffi
4137

4238
# Run all tests (builds core, installs, then runs test suites)
4339
test: build-core
4440
idris2 --install ochrance.ipkg
45-
idris2 --install ochrance-fs.ipkg
4641
idris2 --build tests/A2ML/tests.ipkg
4742
tests/A2ML/build/exec/a2ml-tests
4843
idris2 --build tests/property/tests.ipkg
@@ -59,7 +54,6 @@ test-a2ml: build-core
5954
# Run integration tests only
6055
test-integration: build-core
6156
idris2 --install ochrance.ipkg
62-
idris2 --install ochrance-fs.ipkg
6357
idris2 --build tests/integration/tests.ipkg
6458
tests/integration/build/exec/integration-tests
6559

@@ -89,18 +83,13 @@ check FILE:
8983
repl:
9084
idris2 --repl ochrance.ipkg
9185

92-
# Open REPL for filesystem module
93-
repl-fs:
94-
idris2 --repl ochrance-fs.ipkg
95-
9686
# Find type at position in file
9787
type-at FILE LINE COL:
9888
idris2 --find-type-at {{FILE}}:{{LINE}}:{{COL}}
9989

10090
# Install packages
10191
install:
10292
idris2 --install ochrance.ipkg
103-
idris2 --install ochrance-fs.ipkg
10493
idris2 --install ochrance-abi.ipkg
10594

10695
# Install OSTree hooks
@@ -126,11 +115,11 @@ format:
126115
stats:
127116
@echo "=== Ochránce Statistics ==="
128117
@echo "Idris2 modules:"
129-
@find ochrance-core modules -name "*.idr" | wc -l
118+
@find ochrance-core -name "*.idr" | wc -l
130119
@echo "Total lines of code:"
131-
@find ochrance-core modules -name "*.idr" -exec cat {} \; | wc -l
120+
@find ochrance-core -name "*.idr" -exec cat {} \; | wc -l
132121
@echo "Functions marked total:"
133-
@grep -r 'total' ochrance-core modules | grep -v '%default' | wc -l
122+
@grep -r 'total' ochrance-core | grep -v '%default' | wc -l
134123

135124
# Run panic-attacker pre-commit scan
136125
assail:

docs/AFTER-MIGRATION.adoc

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
= Ochránce — Re-entry After the svalinn → Ephapax Migration
2+
:toc: macro
3+
:sectnums:
4+
5+
// SPDX-License-Identifier: MPL-2.0
6+
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath)
7+
8+
This is the *round-trip closure* for the svalinn migration that was disposed from
9+
the proof campaign (`docs/PROOFS.adoc`, Decision *D3*; outbound charter at
10+
`svalinn/docs/ephapax-migration/HANDOFF.adoc`). Read it when the migration
11+
excursion *returns*, before resuming the proof program. It exists so the loop
12+
"delegate → migrate → come back" closes cleanly even after this thread is gone.
13+
14+
toc::[]
15+
16+
== The loop
17+
18+
----
19+
proof thread (here)
20+
└─ dispose svalinn migration → HANDOFF.adoc → [svalinn + ephapax session]
21+
runs the spike, then the map, then the port (its own draft PRs)
22+
←─ return here → read THIS doc → reconcile → resume PROOFS.adoc
23+
----
24+
25+
You are at the *return* step.
26+
27+
== Reachability first (so you don't hit a 404)
28+
29+
The migration's outputs live in the *svalinn* repo, not here. To do the
30+
reconciliation below you need *either* `hyperpolymath/svalinn` in this session's
31+
scope, *or* the delegated session to paste you its spike verdict. The proof
32+
campaign itself only needs `ochrance`.
33+
34+
== Step 1 — Read the spike verdict (the gate)
35+
36+
The migration was *gated* on a readiness spike (can Ephapax host an HTTP gateway
37+
today?). Its result is the capability matrix in
38+
`svalinn/docs/ephapax-migration/BLOCKER-LINEAGE.adoc`. Branch on it:
39+
40+
[cols="1,4",options="header"]
41+
|===
42+
| Verdict | What it means / what you do
43+
44+
| *GREEN* — Ephapax viable
45+
| The migration proceeded. Go to Step 2.
46+
47+
| *RED* — a MUST-have absent, *D3 invalidated*
48+
| svalinn's language decision is *reopened*. Do *not* resume svalinn proofs.
49+
Update `PROOFS.adoc` D3 with the new decision (stay ReScript + prove /
50+
AffineScript / wait on Ephapax), then treat svalinn as a fresh disposed track.
51+
|===
52+
53+
== Step 2 — Reconcile (green path)
54+
55+
Fold the migration's results back into the campaign. Checklist:
56+
57+
* [ ] `BLOCKER-LINEAGE.adoc` exists and its ring-0 critical chain was executed.
58+
* [ ] *Zero* `Obj.magic` in svalinn `src/` (the 20+ casts are gone
59+
*structurally*, not patched).
60+
* [ ] JWT/JTI revocation is true-by-construction → svalinn *issue #13* is
61+
dischargeable: verify and close it.
62+
* [ ] The *Ephapax* test suite runs *green* in CI (the pre-existing ReScript red
63+
is gone because the ReScript is gone — not because it was fixed).
64+
* [ ] svalinn *PR #32* (the AffineScript language-policy PR) was reconciled to
65+
Ephapax or closed; the `.claude/CLAUDE.md` language table was updated.
66+
* [ ] `PROOFS.adoc` updated: tick the svalinn disposed track; *promote* its
67+
post-migration specs (Appendix E of the charter) into the proof program — now
68+
the language is final, they are provable.
69+
70+
== Step 3 — Resume the proof campaign
71+
72+
Return to `docs/PROOFS.adoc` and continue at the stage you left (Stage 1 on Opus
73+
if you came straight back). The svalinn specs become a *sibling track* once
74+
Ephapax is the language; prove them via the route the spike established —
75+
Ephapax's own linear types, the Idris ABI layer (`svalinn/src/abi/*.idr`), or
76+
SPARK (`svalinn/docs/cerro-torre-integration.adoc` §6.2).
77+
78+
== Cross-references
79+
80+
* `docs/PROOFS.adoc` — the proof-campaign ledger (Decision D3, disposed tracks).
81+
* `svalinn/docs/ephapax-migration/HANDOFF.adoc` — the outbound charter.
82+
* `svalinn/docs/ephapax-migration/BLOCKER-LINEAGE.adoc` — the migration's own
83+
output (spike verdict + critical chain), produced by the delegated session.

0 commit comments

Comments
 (0)