Skip to content

Commit 87fc39b

Browse files
docs: canonicalise the preservation closure plan in ROADMAP (#117)
After PR #116 brought preservation to 12 open goals (from 910 at session start), this PR sets the 5-phase closure plan as the canonical path in ROADMAP.adoc. Any session picking up the proof work follows this. ## Plan summary Full detail in ROADMAP §"Preservation closure plan". 5 phases: 1. **Lemma B** (linearity-context invariance for siblings) — ~3-4h 2. **Apply Lemma B** → close 11 congruence cases — ~2h, parallelizable 3. **Region-env weakening lemma** for non-values — 1-2 days 4. **Apply Phase 3** → close S_Region_Step — ~1h 5. **`Admitted.` → `Qed.`** + docs sweep — ~1h Total: 3 sessions / ~10 hours wall-clock with fan-out. ## Other docs updated - `PROOF-NEEDS.md` — points at ROADMAP plan + lists 5 phases - `formal/PRESERVATION-HANDOFF.md` — header redirects to ROADMAP; state-at-a-glance extended through 2026-05-21 No proof changes. Phase 1 commences in a follow-up PR on top of this. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b38c24f commit 87fc39b

3 files changed

Lines changed: 241 additions & 12 deletions

File tree

PROOF-NEEDS.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,22 @@
77
- `src/formal/Ephapax/Formal/RegionLinear.idr` — Idris2 region-based linearity proof (explicitly states "REAL proof — not believe_me, not assert_total")
88
- 17 Idris2 files across formal verification layer
99
- No `believe_me`, `sorry`, or `assert_total` in Idris2 source code
10-
- Coq admitted proofs remaining in `formal/Semantics.v`: 1 (`preservation`)
10+
- Coq admitted proofs remaining in `formal/Semantics.v`: 1 (`preservation` — 12 open goals, plan below)
1111

1212
## What needs proving
13-
- **`preservation`**: Close the remaining ~29 open goals in the proof script at `formal/Semantics.v` L3215–L3339 so the `Qed` lands and the file builds without `Admitted.` Down from 910 open goals (full 35×26 cross-case combinatorial) after introducing the standard preservation pattern (`remember (mu, R, e) as cfg eqn:Hcfg` + symmetric for cfg', then `inversion Hcfg; subst; inversion Hcfg'; subst;` inside each case). The remaining 29 are real diagonal cases — see `formal/PRESERVATION-HANDOFF.md` for the per-case checklist. Supporting lemmas already Qed (`subst_preserves_typing`, `region_env_perm_typing`, `region_add_typing`, `region_shrink_preserves_typing`, `values_dont_step`). The S_Region_Step + T_Region_Active case still blocks on a region-env *weakening* lemma for non-values, which does not yet exist. An earlier ~40-goal diagnostic (PR #104) measured the PRE-`remember-cfg`-pattern state and is superseded.
13+
- **`preservation`**: Close the remaining **12 open goals** in `formal/Semantics.v` so the `Qed` lands. Down from 910 at session start (98.7% reduction). Reduction story: 910 → 29 via remember-cfg (PR #102) → 22 via universal-IH revert (PR #106) → 12 via per-case manual closures (PR #116). The remaining 12 are 11 congruence cases (`S_*_Step` variants) + 1 region case (`S_Region_Step + T_Region_Active`).
14+
15+
**Canonical closure path: `ROADMAP.adoc` § Preservation closure plan** — 5 phases:
16+
17+
1. **Lemma B (linearity-context invariance for siblings)** — closes the IH-vs-sibling context mismatch blocking the 11 congruence cases. ~3–4 hours.
18+
2. **Apply Lemma B → close 11 congruence cases** — per-case manual proof scripts (PR #116 pattern). ~2 hours, parallelizable.
19+
3. **Region-env weakening lemma for non-values** — defines `safe_for_region_weakening` predicate + proves the weakening lemma. 1–2 days, genuine metatheoretic work.
20+
4. **Apply Phase 3 lemma → close S_Region_Step**~1 hour.
21+
5. **`Admitted.``Qed.` + docs sweep** — mechanical, ~1 hour.
22+
23+
Total: 3 sessions / ~10 hours wall-clock with fan-out. See ROADMAP for full effort estimates and risk-adjusted forecast.
24+
25+
Supporting lemmas already Qed: `subst_preserves_typing`, `region_env_perm_typing`, `region_add_typing`, `region_shrink_preserves_typing`, `values_dont_step`, and **`step_R_eq_or_touches_region`** (PR #114, the region-invariance lemma used by the per-case closures and required by Phase 2).
1426
- **Linear type consumption**: Prove resources with linear types are consumed exactly once across all execution paths (region boundaries, exception handlers)
1527
- **Effect system soundness**: Prove the effect type system correctly tracks side effects and that effect-free terms are truly pure
1628
- **Region safety**: Prove that region-based memory management prevents use-after-free and dangling references across region boundaries

ROADMAP.adoc

Lines changed: 214 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,220 @@ All four headline theorems complete with **zero `believe_me` /
150150
* [ ] Type checker completion (`ephapax-typing`)
151151
* [ ] WASM code generation: lambda/app compilation (closure conversion)
152152
* [x] Coq: `subst_preserves_typing` (Qed)
153-
* [ ] **Coq: close `preservation` to Qed** — the v0.1 blocker. 22 open
154-
goals remain (down from 910); needs region-invariance + context-
155-
preservation lemmas + the documented region-env weakening lemma
156-
for non-values. Multi-day proof engineering. Tracked in
157-
`formal/PRESERVATION-HANDOFF.md`.
153+
* [ ] **Coq: close `preservation` to Qed** — the v0.1 blocker. **12
154+
open goals remain** as of 2026-05-21 (down from 910 at session
155+
start). Full closure plan in
156+
<<preservation-closure-plan,Preservation closure plan>> below.
157+
158+
[#preservation-closure-plan]
159+
== Preservation closure plan (current canonical path)
160+
161+
The 5-phase plan to close `formal/Semantics.v` `preservation` to
162+
`Qed.` Each phase has a concrete deliverable, time estimate, and
163+
dependency chain. This is the **rightful path** any session picking
164+
up the proof should follow.
165+
166+
=== Reduction story so far
167+
168+
[cols="3,1,2"]
169+
|===
170+
| Stage | Open goals | Mechanism
171+
172+
| Pre-campaign (in-file "Qed 2026-04-27" claim was unsubstantiated)
173+
| 910
174+
| Documented honestly by PR #92.
175+
176+
| After `remember (mu, R, e) as cfg`
177+
| 29
178+
| Standard preservation pattern. PR #102.
179+
180+
| After `revert mu R e mu' R' e' Hcfg Hcfg'` (universal-IH)
181+
| 22
182+
| Clean IH quantification across congruence cases. PR #106.
183+
184+
| After region-invariance lemma `step_R_eq_or_touches_region`
185+
| 22
186+
| Infrastructure landed; no goals closed alone. PR #114.
187+
188+
| After per-case manual closures
189+
| **12**
190+
| 10 β-reduction / value-step cases discharged. PR #116.
191+
|===
192+
193+
98.7% reduction across one day. Remaining 12 = 11 congruence cases
194+
(`S_*_Step` variants) + 1 region case (`S_Region_Step + T_Region_Active`).
195+
196+
=== Phase 1 — Lemma B: linearity-context invariance for siblings
197+
198+
**Goal**: a Coq lemma that lets `T_StringConcat`-style reconstruction
199+
succeed in congruence cases.
200+
201+
**Statement (sketch)**:
202+
203+
[source,coq]
204+
----
205+
Lemma sibling_typing_transfers_across_step :
206+
forall mu R e mu' R' e' G G_end T G_out,
207+
(mu, R, e) -->> (mu', R', e') ->
208+
R; G |- e : T -| G_end -> (* original typing *)
209+
R'; G |- e' : T -| G_out -> (* stepped typing from IH *)
210+
G_end = G_out. (* linearity contexts coincide *)
211+
----
212+
213+
The linearity-context evolution induced by `e` is invariant under
214+
step. With this, sibling typing premises like
215+
`H6 : R; G' |- e2 : ...` become typable at `R; G_out |- e2 : ...`
216+
via `G' = G_out`.
217+
218+
**Approach**: induction on `step` with `type_determinacy` per case.
219+
Same pattern as `step_R_eq_or_touches_region`.
220+
221+
**Effort**: 3–4 hours focused session.
222+
223+
**Risk**: `G_end = G_out` may need weakening to "context-equivalent up
224+
to flag positions" via the existing `types_agree` machinery. If so,
225+
the lemma is slightly harder but still tractable.
226+
227+
=== Phase 2 — Apply Lemma B → close 11 congruence cases
228+
229+
**Goal**: 12 → 1 open goals.
230+
231+
**Approach**: extend the PR #116 per-case manual proof pattern to the
232+
11 `S_X_Step` cases. Each:
233+
234+
. `pose proof (step_R_eq_or_touches_region ... Hstep)` → dispatch
235+
the `R = R'` branch via `subst`.
236+
. `edestruct (IHHstep ...)` → get `Hout : R'; G0 |- e1' : T -| Gout`.
237+
. `pose proof (sibling_typing_transfers_across_step ...)` → get
238+
`Gout = G'` (or the context-equivalence variant).
239+
. `rewrite <- (sibling lemma result) in H6` or equivalent.
240+
. `eexists; eapply T_Foo; [exact Hout | exact H6]`.
241+
242+
**Effort**: ~2 hours (11 near-identical bullets).
243+
244+
**Parallelizable**: yes — one agent per typing-constructor cluster
245+
(string ops, let / app, conditionals, products, sums).
246+
247+
=== Phase 3 — Region-env weakening for non-values
248+
249+
**Goal**: discharge the language-design item documented since the
250+
start of the campaign.
251+
252+
**Statement (sketch)**:
253+
254+
[source,coq]
255+
----
256+
Lemma region_add_typing_for_non_values :
257+
forall R e G G' T r,
258+
R; G |- e : T -| G' ->
259+
~ In r R ->
260+
safe_for_region_weakening e -> (* new predicate *)
261+
(r :: R); G |- e : T -| G'.
262+
----
263+
264+
**The hard part**: defining `safe_for_region_weakening`. Naive
265+
weakening is unsound for `EBorrow` (borrows whose region escape the
266+
weakened scope), `EDrop` of a region-bound resource, `EStringNew r' s`
267+
where `r' = r` (shadowing). The predicate rules these out
268+
syntactically.
269+
270+
**Approach**:
271+
272+
. Define the predicate (~30 LOC).
273+
. Prove the lemma by induction on `has_type` (~80–150 LOC).
274+
. Cross-check that the step rule `S_Region_Step + T_Region_Active`
275+
produces an `e'` satisfying the predicate, given the typing
276+
derivation.
277+
278+
**Effort**: 1–2 days. Genuine metatheoretic work.
279+
280+
**Risk**: may need predicate to depend on typing derivation, not just
281+
expression shape. Mitigation: start with the simplest possible
282+
predicate (no `ERegion r` or `EStringNew r` syntactically anywhere);
283+
check if it passes the S_Region_Step case. Refine only if it fails.
284+
285+
=== Phase 4 — Close S_Region_Step + T_Region_Active
286+
287+
**Goal**: 1 → 0 open goals.
288+
289+
**Approach**: replace `apply region_add_typing` with
290+
`apply region_add_typing_for_non_values` in the existing
291+
`T_Region_Active` `try solve` block at `formal/Semantics.v:3300`-ish.
292+
293+
**Effort**: ~1 hour.
294+
295+
=== Phase 5 — `Admitted.` → `Qed.` + docs sweep
296+
297+
**Goal**: campaign closure. Mechanical (~1 hour).
298+
299+
. **`formal/Semantics.v`** — replace `Admitted.` at the end of
300+
`Theorem preservation` with `Qed.` Remove the PROOF STATUS
301+
comment block.
302+
. **`formal/PRESERVATION-HANDOFF.md`** — collapse to a one-line
303+
"preservation is Qed as of YYYY-MM-DD" tombstone.
304+
. **`PROOF-NEEDS.md`** — flip "Coq admitted proofs remaining: 1" to
305+
"0". Drop the "what needs proving" entry for `preservation`.
306+
. **`ROADMAP.adoc`** — flip the v0.1 checkbox; update the Coq table
307+
row; remove this entire "Preservation closure plan" section
308+
(replace with a 1-line "completed" note).
309+
. **`README.adoc`** — flip the Component status table row; remove
310+
the "22 open / 910 closed" qualifiers in Formal foundations.
311+
. **`EXPLAINME.adoc`** — flip Coq theorem table; remove reduction
312+
story.
313+
. **`CHANGELOG.md`** — entry: "Coq `preservation` closed to `Qed.`
314+
via the 910 → 0 reduction chain (PRs #92, #102, #104, #106,
315+
#114, #116, [Phase 1 PR], [Phase 2 PR], [Phase 3 PR],
316+
[Phase 4 PR])".
317+
. **Wiki `Proof-status.md`** + **`Home.md`** — flip preservation
318+
row to ✅ Qed; replace the reduction story with a one-line
319+
"fully discharged" note.
320+
. **Memory** —
321+
`project_ephapax_preservation_closure_plan.md` → mark CAMPAIGN
322+
COMPLETE.
323+
. **`standards#124`** — post closure comment with full PR chain.
324+
. **GitHub repo description** — drop "preservation 22 open"
325+
qualifier.
326+
327+
=== Effort + parallelization summary
328+
329+
[cols="1,2,2"]
330+
|===
331+
| Phase | Solo effort | Parallelizable?
332+
333+
| 1 (Lemma B)
334+
| 3–4 hours
335+
| Single agent task.
336+
337+
| 2 (Apply Lemma B)
338+
| 2 hours
339+
| 4 agents × ~30 min (one per typing-constructor cluster).
340+
341+
| 3 (Region-env weakening)
342+
| 1–2 days
343+
| Single agent (research-level).
344+
345+
| 4 (Close S_Region_Step)
346+
| 1 hour
347+
| No.
348+
349+
| 5 (Qed flip + docs)
350+
| 1 hour
351+
| 2 agents (repo docs + wiki).
352+
|===
353+
354+
**Sequential ceiling**: ~3 days of focused work.
355+
**With fan-out**: ~5–7 calendar hours over 2–3 sessions.
356+
357+
=== Risk-adjusted forecast
358+
359+
* **80% likely**: Phases 1+2 land in one session. Phase 3 takes ~1
360+
day. Total: 3 sessions, ~10 hours wall-clock.
361+
* **15% likely**: Lemma B needs context-equivalence (not equality);
362+
phase 1 spills into a refinement session.
363+
* **5% likely**: Phase 3 hits a language-design issue (e.g., need to
364+
add a syntactic invariant to the typing rules). If so, the rules
365+
get amended and all earlier `Qed`-proofs need re-checking (~1 day
366+
detour).
158367

159368
== v0.2.0 — Backend maturity
160369

formal/PRESERVATION-HANDOFF.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,26 @@
22

33
# Hand-off: closing `preservation` in `formal/Semantics.v`
44

5-
Diagnostic + remediation log. The proof is still `Admitted.`, but as of
6-
2026-05-20 it's **down from 910 open goals to ~29 real ones** via the
7-
standard preservation pattern. This file tells whoever picks it up
8-
next exactly what's open and why.
5+
Diagnostic + remediation log. The proof is still `Admitted.`, but as
6+
of **2026-05-21** it's **down from 910 open goals to 12** via four
7+
landed PRs. This file tells whoever picks it up next exactly what's
8+
open and what the canonical closure path is.
9+
10+
> **The canonical closure plan is now in `ROADMAP.adoc` §
11+
> "Preservation closure plan".** This file remains as the per-case
12+
> diagnostic record. Read ROADMAP first; come back here for case
13+
> detail.
914
1015
## State at a glance
1116

1217
| Date | Open goals | Notes |
1318
|------|-----------:|-------|
1419
| 2026-04-27 | "fully closed" | In-file comment — but `coqc` rejected the `Qed.`. The claim was unsubstantiated; the proof never closed. |
1520
| 2026-05-20 (am) | 910 | Discovered via `Show. Show Existentials.` before the `Admitted.`. Exactly 35 (step rules) × 26 (typing rules). The existing `try solve [...]` chain closes ZERO. |
16-
| 2026-05-20 (pm) | **29** | After the standard preservation pattern (`remember (mu, R, e) as cfg` + symmetric for cfg', then `inversion Hcfg; subst; inversion Hcfg'; subst;` inside each case). 97% reduction. |
21+
| 2026-05-20 (pm) | 29 | After the standard preservation pattern (`remember (mu, R, e) as cfg` + symmetric for cfg', then `inversion Hcfg; subst; inversion Hcfg'; subst;` inside each case). 97% reduction. PR #102. |
22+
| 2026-05-20 (eve) | 22 | After `revert mu R e mu' R' e' Hcfg Hcfg'` before `induction Hstep` so each case's IH carries universal quantification over the inner step's config. PR #106. |
23+
| 2026-05-20 (eve) | 22 | Region-invariance lemma `step_R_eq_or_touches_region` landed as infrastructure (no goal closures). PR #114. |
24+
| 2026-05-20 (night) | **12** | 10 β-reduction / value-step cases discharged via per-case manual proofs using the lemma. PR #116. **98.7% reduction across one day.** |
1725

1826
## What the 910 → 29 fix did
1927

0 commit comments

Comments
 (0)