Skip to content

Commit ac6e574

Browse files
hyperpolymathhyperpolymathclaude
authored
feat(formal): stand up Coq formal/ track + mechanize the K-1 Wave-0 seed (#620)
## What Wave 0 of the `docs/PROOF-NEEDS.adoc` programme, on the keystone obligation **K-1** (codegen → typed-WASM semantic-preservation). Stands up the `formal/` directory (the dir #513 names) and lands a **fully mechanized, axiom-free** Coq proof for a minimal fragment. Prover: **Coq/Rocq 8.18** — chosen for K-1 because the typed-WASM target semantics interoperate with `typed-wasm` and ephapax, both of which use Coq `Semantics.v`. ## The proof — `formal/K1_CodegenPreservation.v` A complete compiler-correctness theorem with **no `Admitted`, no axioms** (`Print Assumptions` → *"Closed under the global context"*): ```coq Definition K1_preservation : Prop := forall e v, seval e = Some v -> wexec (compile e) [] = Some [obs v]. Theorem k1_preservation_holds : K1_preservation. (* proven *) ``` i.e. whenever the source big-step evaluates to `v`, the compiled stack-machine code run on the empty operand stack yields exactly the corresponding wasm value `[obs v]`. The fragment (nat/bool · `add`/`and` → a little stack machine standing in for typed-WASM) is deliberately tiny; the **real AST + real typed-WASM operational semantics remain the open obligation**, expanded later the way solo-core's Duet/Ensemble tracks expand Solo. This mirrors how `invariant-path/proofs/SameCube.agda` grounds F-2 with a real proof rather than a hole. ## Coq `.v` policy carve-out (the point you raised) `.v` is shared by **Coq, Verilog, and the estate-banned V-lang** (→ Zig). Coq is neither — so this PR makes the distinction explicit so nothing can sweep it up: - **`.hypatia-ignore`** — explicit `formal/*.v` exemption from `cicd_rules/vlang_detected` (+ `banned_language_file`). Coq ships no `v.mod`, so `vmod_detected` never fires. - **`.claude/CLAUDE.md`** — new *"Formal-methods Coq `.v` (NOT V-lang)"* note: documents the estate `path_allow_prefixes` carve-out for Coq proof scripts, the no-`Admitted`/no-axiom rule, the Coq-vs-Idris2 prover split (Coq here for typed-wasm interop; solo-core stays Idris2), and "do not migrate/delete these as V-lang." ## Track scaffolding `README.adoc`, `_CoqProject`, `justfile` (`check` recipe type-checks **and** asserts the proof is axiom-free), `.gitignore` for Coq artifacts. ## Docs synced - `PROOF-NEEDS.adoc`: K-1 `prose` → **`partial`**; `formal/` now **exists**; Wave-0 row marked in progress. - `FRG-PROFILE.adoc`: the *"no formalisation directory"* honest-gap is **met** (grade stays **E** — D needs *type*-preservation/progress for the affine calculus, a theorem distinct from this codegen-preservation seed). ## How to check ```sh just -f formal/justfile check # or: cd formal && coqc K1_CodegenPreservation.v ``` Requires Coq 8.18+. Verified locally: compiles clean, `Print Assumptions` closed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01KPG9mEQXFyA3k7NWAzMNMr --- _Generated by [Claude Code](https://claude.ai/code/session_01KPG9mEQXFyA3k7NWAzMNMr)_ Co-authored-by: hyperpolymath <paraordinate@yahoo.co.uk> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 85e3f0d commit ac6e574

9 files changed

Lines changed: 324 additions & 10 deletions

File tree

.claude/CLAUDE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,27 @@ The "no Node.js / no Bun" rules in the language policy table have two approved e
139139

140140
Browsers and Cloudflare Workers are NOT supported and never will be (the shim's purpose — fetch, save to disk, exec a native binary — cannot be done in a sandboxed JS runtime). The JSR runtime-compatibility checkboxes for this package should be: Deno ✅, Bun ✅, Node ✅, Workers ❌, Browsers ❌.
141141

142+
### Formal-methods Coq `.v` (NOT V-lang)
143+
144+
The `formal/` directory holds **Coq/Rocq 8.18** proof scripts — mechanized
145+
metatheory for the obligations in `docs/PROOF-NEEDS.adoc` (Wave-0 seed: K-1
146+
codegen→typed-WASM preservation, `formal/K1_CodegenPreservation.v`). Coq uses
147+
the `.v` extension, **shared with Verilog and the estate-banned V-lang** (→
148+
Zig). Coq `.v` is **not** V-lang and is **not** a policy violation:
149+
150+
- The estate vlang ban (`cicd_rules/vlang_detected`, matches `*.v`) carries an
151+
estate-wide `path_allow_prefixes` carve-out for "Coq proof scripts"; V-lang's
152+
`v.mod` manifest (`cicd_rules/vmod_detected`) does not exist for Coq.
153+
- `formal/*.v` is exempted explicitly in `.hypatia-ignore` so a future sweep
154+
cannot conflate the two `.v`. Prover choice is Coq (typed-wasm / ephapax
155+
interop, both Coq); solo-core's separate skeleton stays Idris2.
156+
- Load-bearing proofs here must be **complete**: no `Admitted`, no axioms
157+
(`Print Assumptions` must report "Closed under the global context"),
158+
paralleling the Agda "no postulates in load-bearing tracks" rule;
159+
`formal/justfile`'s `check` recipe enforces it.
160+
161+
Do not "migrate", rewrite, or delete `formal/*.v` as if it were V-lang.
162+
142163
### Package Management
143164

144165
- **Primary**: Guix (guix.scm)

.hypatia-ignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,16 @@ cicd_rules/banned_language_file:tools/res-to-affine/test/fixtures/partial1.res
3232
cicd_rules/banned_language_file:tools/res-to-affine/test/fixtures/phase3.res
3333
cicd_rules/banned_language_file:tools/res-to-affine/test/fixtures/phase3b.res
3434
cicd_rules/banned_language_file:tools/res-to-affine/test/fixtures/phase3c.res
35+
#
36+
# ─── Coq/Rocq proof scripts (.v is NOT V-lang) ──────────────────────
37+
#
38+
# `.v` is shared by Coq, Verilog and the estate-banned V-lang (→ Zig).
39+
# The vlang ban is detected on `*.v` via cicd_rules/vlang_detected, with an
40+
# estate-wide path_allow_prefixes carve-out for "Coq proof scripts". The
41+
# AffineScript `formal/` track (obligation K-1, see docs/PROOF-NEEDS.adoc)
42+
# is Coq 8.18 — not V-lang, not Verilog. Exempt it explicitly so a future
43+
# sweep cannot mis-flag it. (Coq ships no `v.mod`, so vmod_detected never
44+
# fires.) Both rule names are listed for robustness; the non-matching one is
45+
# an inert no-op under the scanner's `grep -qxF` whole-line match.
46+
cicd_rules/vlang_detected:formal/K1_CodegenPreservation.v
47+
cicd_rules/banned_language_file:formal/K1_CodegenPreservation.v

docs/PROOF-NEEDS.adoc

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ than the prose corpus suggests:
6767
*templates* ("Replace with your project's domain-specific proofs"); the Coq
6868
`TypeSafety.v` is example lemmas about list length, not AffineScript. Not
6969
core-metatheory.
70-
* **`formal/`** — the directory #513 names as the mechanized-proof target
71-
**does not exist**.
70+
* **`formal/`** — the directory #513 names as the mechanized-proof target now
71+
**exists** (Coq/Rocq 8.18). It holds the Wave-0 **K-1 seed**
72+
(`formal/K1_CodegenPreservation.v`) — a complete, axiom-free
73+
codegen-preservation proof for a minimal nat/bool fragment (see <<outstanding>>).
7274
* **Research tracks** (not core soundness): `docs/academic/tropical-session-types/`
7375
(Lean), `proposals/echo-types/EchoEncodingFaithfulness.agda`,
7476
`proposals/idaptik/migrated/**/*Boundary.agda` (echo-types loss-with-residue,
@@ -178,8 +180,11 @@ The work in flight changes which obligations are *load-bearing* and which are
178180
`⟦compile(p)⟧_wasm = ⟦p⟧_source` for the operational semantics. This is the
179181
single obligation every *face* and every *aLib conformer* ultimately rests on:
180182
prove the backend preserves meaning once, and front-end face theorems
181-
(<<faces>>) compose into end-to-end correctness. Rigour `XL`. Status `prose`
182-
(`operational-semantics.md` / `denotational-semantics.md` are the inputs).
183+
(<<faces>>) compose into end-to-end correctness. Rigour `XL`. Status `partial`
184+
(was `prose`): a Wave-0 mechanized seed — `formal/K1_CodegenPreservation.v`
185+
(Coq, no axioms) — proves preservation for a minimal nat/bool · add/and
186+
fragment compiled to a stack machine; the real AffineScript AST + real
187+
typed-WASM operational semantics remain the open obligation.
183188
* **K-2 — Effect-soundness is *blocked*, not merely unproven.** P-6 cannot be
184189
honestly *stated against the current backend* because #555 drops handler arms
185190
on three of the codegen targets. The obligation must be split: (a) prove
@@ -311,10 +316,11 @@ F-1 (full transformer preservation) is non-trivial rather than a formality.
311316
|===
312317
| Wave | Items | Gates
313318

314-
| 0 (now)
315-
| Stand up `formal/` (the #513 target dir). *State* — without proving — P-2,
316-
P-3 (rejecting #554), F-1, F-3, F-4 as signatures/holes, mirroring the
317-
solo-core skeleton style. Cross-link `CAPABILITY-MATRIX.adoc` rows (K-4).
319+
| 0
320+
| *In progress.* DONE: `formal/` stood up (Coq/Rocq); **K-1 seed mechanized**
321+
(`K1_CodegenPreservation.v`, axiom-free). NEXT: *state* P-2, P-3 (rejecting
322+
#554), F-1, F-3, F-4 as signatures, mirroring solo-core; cross-link
323+
`CAPABILITY-MATRIX.adoc` rows (K-4).
318324
| —
319325

320326
| 1

formal/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Coq/Rocq build artifacts
2+
*.vo
3+
*.vok
4+
*.vos
5+
*.glob
6+
.*.aux
7+
.lia.cache
8+
.nia.cache
9+
.coqdeps.d

formal/K1_CodegenPreservation.v

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
(* SPDX-License-Identifier: MPL-2.0 *)
2+
(* SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) *)
3+
4+
(*
5+
K1_CodegenPreservation.v
6+
════════════════════════
7+
Wave-0 seed of obligation **K-1** from docs/PROOF-NEEDS.adoc:
8+
"codegen → typed-WASM semantic-preservation" — the keystone every face
9+
(via F-1) and every aLib conformer ultimately composes through.
10+
11+
This file is a Coq/Rocq PROOF SCRIPT. It is NOT V-lang and NOT Verilog —
12+
the `.v` extension is shared between Coq, Verilog and V-lang. The estate
13+
language policy bans *V-lang* (→ Zig) and carves Coq proof scripts out of
14+
the `cicd_rules/vlang_detected` rule via `path_allow_prefixes`; this repo
15+
makes that explicit for `formal/` in `.hypatia-ignore`.
16+
17+
SCOPE (honest). This discharges K-1 for a deliberately minimal fragment:
18+
a two-type (nat, bool) expression language with `add` and `and`, compiled
19+
to a little stack machine that stands in for typed-WASM. The full
20+
obligation — the real AffineScript AST and the real typed-WASM operational
21+
semantics — is future work that *expands* this core, exactly the way
22+
solo-core's Duet/Ensemble tracks expand the Solo fragment. What is proven
23+
here is the genuine article for the fragment: a complete, machine-checked
24+
compiler-correctness theorem with NO `Admitted`, NO `Axiom`, NO `postulate`
25+
(estate rule: load-bearing proofs must be constructive and complete).
26+
27+
Check it: coqc formal/K1_CodegenPreservation.v (or: just -f formal/justfile check)
28+
*)
29+
30+
Require Import List.
31+
Import ListNotations.
32+
33+
(* ══════════════════ Source: a minimal AffineScript fragment ══════════════ *)
34+
35+
Inductive sval : Type :=
36+
| VNat (n : nat)
37+
| VBool (b : bool).
38+
39+
Inductive sexp : Type :=
40+
| SNat (n : nat)
41+
| SBool (b : bool)
42+
| SAdd (e1 e2 : sexp)
43+
| SAnd (e1 e2 : sexp).
44+
45+
(* Big-step source evaluator. Partial: `add` on bools (or `and` on nats) is
46+
stuck (None), so `seval e = Some v` is a real, non-trivial hypothesis. *)
47+
Fixpoint seval (e : sexp) : option sval :=
48+
match e with
49+
| SNat n => Some (VNat n)
50+
| SBool b => Some (VBool b)
51+
| SAdd e1 e2 =>
52+
match seval e1, seval e2 with
53+
| Some (VNat a), Some (VNat b) => Some (VNat (a + b))
54+
| _, _ => None
55+
end
56+
| SAnd e1 e2 =>
57+
match seval e1, seval e2 with
58+
| Some (VBool a), Some (VBool b) => Some (VBool (andb a b))
59+
| _, _ => None
60+
end
61+
end.
62+
63+
(* ══════════════ Target: a minimal typed-WASM-style stack machine ═════════ *)
64+
65+
Inductive wval : Type :=
66+
| WNat (n : nat)
67+
| WBool (b : bool).
68+
69+
Inductive instr : Type :=
70+
| IPushN (n : nat)
71+
| IPushB (b : bool)
72+
| IAdd
73+
| IAnd.
74+
75+
Definition code := list instr.
76+
Definition stack := list wval.
77+
78+
(* One instruction over the stack. None = trap (ill-typed operand stack),
79+
the analogue of a typed-WASM validation failure. *)
80+
Definition wstep (i : instr) (s : stack) : option stack :=
81+
match i, s with
82+
| IPushN n, s => Some (WNat n :: s)
83+
| IPushB b, s => Some (WBool b :: s)
84+
| IAdd, WNat b :: WNat a :: s' => Some (WNat (a + b) :: s')
85+
| IAnd, WBool b :: WBool a :: s' => Some (WBool (andb a b) :: s')
86+
| _, _ => None
87+
end.
88+
89+
Fixpoint wexec (c : code) (s : stack) : option stack :=
90+
match c with
91+
| [] => Some s
92+
| i :: rest =>
93+
match wstep i s with
94+
| Some s' => wexec rest s'
95+
| None => None
96+
end
97+
end.
98+
99+
(* ══════════════════════ Compiler: source → stack code ════════════════════ *)
100+
101+
Fixpoint compile (e : sexp) : code :=
102+
match e with
103+
| SNat n => [IPushN n]
104+
| SBool b => [IPushB b]
105+
| SAdd e1 e2 => compile e1 ++ compile e2 ++ [IAdd]
106+
| SAnd e1 e2 => compile e1 ++ compile e2 ++ [IAnd]
107+
end.
108+
109+
(* Value correspondence: a source value and the wasm value it denotes. *)
110+
Definition obs (v : sval) : wval :=
111+
match v with
112+
| VNat n => WNat n
113+
| VBool b => WBool b
114+
end.
115+
116+
(* ════════════════ The K-1 obligation, for this fragment ══════════════════ *)
117+
118+
(* Codegen preserves meaning: if the source evaluates to v, then running the
119+
compiled code on the empty operand stack yields exactly [obs v]. *)
120+
Definition K1_preservation : Prop :=
121+
forall (e : sexp) (v : sval),
122+
seval e = Some v ->
123+
wexec (compile e) [] = Some [obs v].
124+
125+
(* ───────────────────────── discharge (no Admitted) ──────────────────────── *)
126+
127+
(* Correctness in continuation-passing form: running `compile e` followed by
128+
any continuation `k`, from any stack `s`, is the same as running `k` with
129+
the source value `v` pushed. Threading `k` is exactly the induction
130+
strength needed (and avoids reasoning about a residual `match`). *)
131+
Lemma compile_correct : forall e v s k,
132+
seval e = Some v ->
133+
wexec (compile e ++ k) s = wexec k (obs v :: s).
134+
Proof.
135+
induction e as [n | b | e1 IH1 e2 IH2 | e1 IH1 e2 IH2];
136+
intros v s k Hev; simpl in Hev.
137+
- (* SNat *) inversion Hev; subst; reflexivity.
138+
- (* SBool *) inversion Hev; subst; reflexivity.
139+
- (* SAdd *)
140+
destruct (seval e1) as [[a | ab] |]; try discriminate;
141+
destruct (seval e2) as [[b | bb] |]; try discriminate;
142+
inversion Hev; subst; clear Hev; simpl; rewrite <- !app_assoc;
143+
rewrite (IH1 _ s _ eq_refl), (IH2 _ _ _ eq_refl); reflexivity.
144+
- (* SAnd *)
145+
destruct (seval e1) as [[na | a] |]; try discriminate;
146+
destruct (seval e2) as [[nb | b] |]; try discriminate;
147+
inversion Hev; subst; clear Hev; simpl; rewrite <- !app_assoc;
148+
rewrite (IH1 _ s _ eq_refl), (IH2 _ _ _ eq_refl); reflexivity.
149+
Qed.
150+
151+
Theorem k1_preservation_holds : K1_preservation.
152+
Proof.
153+
unfold K1_preservation; intros e v Hev.
154+
pose proof (compile_correct e v [] [] Hev) as H.
155+
rewrite app_nil_r in H; simpl in H; exact H.
156+
Qed.
157+
158+
(* `Print Assumptions` must report "Closed under the global context" — i.e.
159+
the theorem rests on no axioms. CI greps for exactly that string. *)
160+
Print Assumptions k1_preservation_holds.

formal/README.adoc

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
3+
= AffineScript `formal/` — Mechanized Metatheory (Coq/Rocq)
4+
Jonathan D.A. Jewell
5+
:toc: left
6+
:toclevels: 2
7+
8+
This directory is the machine-checked home for the proof obligations
9+
catalogued in `docs/PROOF-NEEDS.adoc`, and is the `formal/` target directory
10+
issue #513 names for mechanized proofs. Prover: **Coq/Rocq 8.18** — chosen for
11+
K-1 because the typed-WASM target semantics interoperate with `typed-wasm` and
12+
ephapax, both of which use Coq (`Semantics.v`).
13+
14+
[IMPORTANT]
15+
.`.v` here is Coq, not V-lang
16+
====
17+
Coq proof scripts use the `.v` extension — shared with Verilog and the
18+
estate-banned **V-lang**. Everything in `formal/` is Coq/Rocq, *not* V-lang and
19+
*not* Verilog. The estate language policy carves Coq proof scripts out of the
20+
`cicd_rules/vlang_detected` rule (`path_allow_prefixes` for "Coq proof
21+
scripts"); `.hypatia-ignore` makes that explicit for this directory so a sweep
22+
cannot mistake it. Coq has no `v.mod` manifest, so `vmod_detected` never fires.
23+
====
24+
25+
== Contents
26+
27+
[cols="2,2,3"]
28+
|===
29+
| File | Obligation | Status
30+
31+
| `K1_CodegenPreservation.v`
32+
| **K-1** — codegen → typed-WASM semantic-preservation
33+
| **mechanized** for a minimal fragment (no `Admitted`, no axioms). The full
34+
obligation remains open — see <<scope>>.
35+
|===
36+
37+
== What `K1_CodegenPreservation.v` proves
38+
39+
A complete, axiom-free compiler-correctness theorem for a minimal two-type
40+
AffineScript fragment (nat + bool, with `add` and `and`) compiled to a small
41+
stack machine that stands in for typed-WASM:
42+
43+
[source,coq]
44+
----
45+
Definition K1_preservation : Prop :=
46+
forall e v, seval e = Some v -> wexec (compile e) [] = Some [obs v].
47+
48+
Theorem k1_preservation_holds : K1_preservation. (* proven *)
49+
----
50+
51+
i.e. whenever the source big-step evaluates to a value `v`, the compiled code
52+
run on the empty operand stack yields exactly the corresponding wasm value
53+
`[obs v]`. `Print Assumptions k1_preservation_holds` reports *Closed under the
54+
global context* — the proof rests on no axioms, honouring the estate rule that
55+
load-bearing proofs be constructive and complete (no `Admitted`, no
56+
`postulate`). This mirrors how `invariant-path/proofs/SameCube.agda` grounds
57+
F-2 with a real `--safe` proof rather than a stated hole.
58+
59+
[#scope]
60+
== Scope (honest)
61+
62+
This is the **Wave-0 seed** of K-1, not the discharged obligation. The fragment
63+
is deliberately tiny: no functions, binders, effects, ownership, traits, or
64+
the real instruction set. The full theorem needs the real AffineScript AST and
65+
the real typed-WASM operational semantics; expanding this core is the analogue
66+
of solo-core's Duet/Ensemble tracks expanding the Solo fragment. Tracked in
67+
`docs/PROOF-NEEDS.adoc` (K-1) and #513 (must-have 7).
68+
69+
The faces twin **F-1** (transformer semantics-preservation) composes *on top
70+
of* K-1: prove the backend preserves meaning once here, and each
71+
`lib/<face>_face.ml` front-end transform need only preserve the canonical AST
72+
denotation for the same-cube result to follow end-to-end.
73+
74+
== Checking
75+
76+
[source,sh]
77+
----
78+
just -f formal/justfile check # or: cd formal && coqc K1_CodegenPreservation.v
79+
----
80+
81+
Requires Coq 8.18+ (`apt install coq`, or opam `coq`). The `check` recipe fails
82+
if the proof ever starts depending on an axiom or `Admitted`.

formal/_CoqProject

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-Q . ASFormal
2+
K1_CodegenPreservation.v

formal/justfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
# Coq/Rocq proof checks for the AffineScript `formal/` track.
3+
# (Mustfile/justfile per estate policy — no Makefiles.)
4+
5+
# Type-check every proof and assert it closes under no axioms.
6+
check:
7+
#!/usr/bin/env bash
8+
set -euo pipefail
9+
out="$(coqc K1_CodegenPreservation.v)"
10+
printf '%s\n' "$out"
11+
grep -q "Closed under the global context" <<<"$out" \
12+
|| { echo "::error:: K-1 proof depends on an axiom / Admitted"; exit 1; }
13+
echo "OK: K-1 fragment mechanized, no axioms."
14+
15+
# Remove Coq build artifacts.
16+
clean:
17+
rm -f *.vo *.vok *.vos *.glob .*.aux .coqdeps.d

spec/FRG-PROFILE.adoc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ For AffineScript, the following FRG tightening applies:
167167

168168
== What is NOT yet met (honest gaps)
169169

170-
* No formalisation directory.
170+
* `formal/` now exists *(met 2026-06-21)* — Coq/Rocq 8.18, holding the
171+
mechanized K-1 codegen-preservation seed. (The *typing-judgment* encoding and
172+
*type*-preservation/progress below remain open.)
171173
* No qualifying-prover encoding of the AST or typing judgment.
172174
* No preservation or progress statement.
173175
* (PROOF-NEEDS: met 2026-06-20.) `docs/PROOF-NEEDS.adoc` now enumerates the
@@ -178,7 +180,8 @@ For AffineScript, the following FRG tightening applies:
178180

179181
== Path to next grade (D — preservation stated)
180182

181-
* Create `formal/` directory.
183+
* [DONE 2026-06-21] Create `formal/` directory (Coq/Rocq; holds the K-1
184+
codegen-preservation seed).
182185
* Encode AST in a qualifying prover (Rocq is the natural choice
183186
for compatibility with ephapax / typed-wasm).
184187
* Encode typing judgment.
@@ -219,6 +222,7 @@ dependent/refinement aspirations).
219222

220223
| 2026-05-28 | E (pragmatic) | Initial FRG assessment. Strict reading = X (no formal/). Pragmatic E based on conformance corpus + operational typechecker + honest README status block. Recommend adopting strict X until qualifying-prover mechanisation lands.
221224
| 2026-06-20 | E (pragmatic) | `docs/PROOF-NEEDS.adoc` authored — open obligations enumerated (P-/F-/K- series), closing the "no PROOF-NEEDS" honest gap and completing path-to-D step 6. Grade unchanged (still no `formal/` prover encoding). Faces obligations F-1…F-7 newly catalogued.
225+
| 2026-06-21 | E (pragmatic) | `formal/` stood up (Coq/Rocq 8.18) with the mechanized **K-1 codegen-preservation seed** (`K1_CodegenPreservation.v`, axiom-free; `Print Assumptions` closed) — closes the "no formalisation directory" gap. Grade still E: D needs *type*-preservation/progress stated for the affine calculus itself (K-1 is codegen-preservation for a minimal fragment, a distinct theorem).
222226
|===
223227

224228
== Review cycle

0 commit comments

Comments
 (0)