Skip to content

Commit 7c4c3f5

Browse files
feat(L1): Phase D slice 4 Phase 3b Stage 1a — tfuneff_lambda_free + Counterexample_L2_nested (#252)
## Summary Ships the **Stage 1a** slice of the four-stage Phase 3b resolution plan (parent #235 / Stage 1 #239 / Stages 2-4 #240-#242). Stage 1 splits into 1a (this PR — syntactic infrastructure + mechanised nested-lambda soundness-gap witness) and 1b (#249 — substitution lemma + preservation_l2 β wrapper) for shipping cadence. ## What lands - **NEW `Fixpoint tfuneff_lambda_free : expr -> bool`** in `formal/Syntax.v`. Conservative leaf-only predicate: `false` on every `ELam`, compositional `andb` propagation through compound forms. Used by Stage 1b's substitution lemma to exfalso the inner `T_Lam_L1_*_Eff` cases. - **NEW `formal/Counterexample_L2_nested.v`** — three Qed lemmas (`e_before_typed`, `e_step`, `e_after_untypable`) mechanising the nested-TFunEff soundness gap. Sibling artifact to `Counterexample_L2.v` (PR #234): together the two files justify the **two-condition** preservation_l2 statement Stage 1 delivers — P1 (`tfuneff_lambda_free ebody = true`, rules out the nested-lambda gap class witnessed here) and P2 (`regions_introduced_by ebody ⊆ R_in_v`, rules out the fresh-region gap class witnessed in `Counterexample_L2.v`). - Wired into `formal/_CoqProject` after `Counterexample_L2.v`. - `formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md` gains a "Phase 3b Stage 1a (landed) — split from Stage 1" subsection documenting the 1a/1b split and the structural blocker (G-mismatch at compound binder rules). - `.machine_readable/6a2/STATE.a2ml` refreshes next_action to Stage 1b (#249). ## Configuration (nested-lambda counterexample) ``` outer = ELam T_v (ELam (TBase TUnit) (EVar 1)) T_inner = TFunEff (TBase TUnit) T_v [r2] [r2] v = ELam (TBase TUnit) EUnit at T_v = TFunEff TUnit TUnit [] [] e_before = EApp outer v at T_inner, R = [] (well-typed via T_App_L2_Eff) e_after = ELam (TBase TUnit) v at T_inner, R = [] (untypable) ``` The inner lambda's body references the outer-bound variable via `EVar 1`; post-β substitutes `v` for the outer variable. The resulting `ELam (TBase TUnit) v` cannot retype the inner `v` at `[r2] ⊄ [] = R_in_v`. ## Owner-directive compliance (CLAUDE.md 2026-05-27) - No touch to `formal/Semantics.v` / `Typing.v` / `Counterexample.v`. - No closure of residual `Semantics_L1.v` admits attempted. - Anti-pattern detector clean. - Strictly NEW infrastructure orthogonal to legacy. ## Test plan - [x] `just -f formal/Justfile all` clean across all 12 .v files with coqc 8.18.0. - [x] Print Assumptions on all three new Qed lemmas → Closed under the global context. - [ ] CI coq-build workflow passes (will check post-push). ## Refs - Parent finding: #235 - Stage 1 tracking: #239 (partially closes — Stage 1a deliverables) - Stage 1b sub-issue: #249 - Stages 2-4: #240 / #241 / #242 - Sibling counterexample: PR #234 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f176f2e commit 7c4c3f5

5 files changed

Lines changed: 299 additions & 2 deletions

File tree

.machine_readable/6a2/STATE.a2ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
@state(version="2.0"):
88
phase: "implementation"
9-
next_action: "Phase D slice 4 Phase 3b Stage 1 (per #239): implement leaf-only Phase 3b. (a) NEW Fixpoint `tfuneff_lambda_free : expr -> bool` in `formal/Syntax.v` (~10 lines). (b) NEW `subst_typing_gen_l1_m_tfuneff` Qed in `formal/Semantics_L1.v` mirroring `subst_typing_gen_l1_m_ground_nonlinear` (~300 lines); inner T_Lam_L1_*_Eff cases exfalso via the `tfuneff_lambda_free` precondition; direct (P1, P2) hypothesis form (no CPS yet — Stage 3 introduces CPS). (c) NEW `preservation_l2_app_eff_beta_tfuneff_l1` + L2 wrapper Qed in `formal/TypingL2.v` under the 2-condition statement: `tfuneff_lambda_free ebody = true ∧ regions_introduced_by ebody ⊆ R_in_v`. (d) NEW `formal/Counterexample_L2_nested.v` (parallel to Counterexample_L2.v) mechanising the nested-TFunEff soundness gap — 3 Qed lemmas, zero axioms. (e) Add to `_CoqProject` after `Counterexample_L2.v`. (f) STATE/design-doc updates. Owner-approved 2026-05-30 PM via the 4-stage staged plan superseding the original three options. Stages 2-4 (#240/#241/#242) tracked but NOT actioned this session. Anti-patterns to refuse (per CLAUDE.md owner directive): no `Admitted` to close cases; no touching `Semantics.v`/`Typing.v`/`Counterexample.v`; no closure of residual `Semantics_L1.v` admits — strictly NEW infrastructure orthogonal to legacy. Coqc 8.18.0 is the only authority."
10-
last_action: "Phase D slice 4 Phase 3b 4-stage resolution plan LANDED (2026-05-30 PM, this PR + cross-issue filings): SUBST-LEMMA-GENERALIZATION-DESIGN.md Phase 3b addendum (gap finding + 3-options framing) + Phase 3b resolution addendum (4-stage plan superseding 3-options) + STATE.a2ml refresh. Cross-issue filings: #235 (parent finding) + #239 (Stage 1 leaf-only Phase 3b, green-lit) + #240 (Stage 2 ELam annotation, parallel L4 track) + #241 (Stage 3 relaxed Phase 3b + CPS, blocked on #240) + #242 (Stage 4 compound non-linear + unconditional preservation_l2, blocked on #241). The 4-stage plan harvests all three Interesting values: L4-alignment (Stage 2 via ELam annotation), higher-order proof style (Stage 3 via CPS), principled deferral + honest 2-condition statement (Stage 1 immediate). Stage 1 ships unblocked preservation_l2 β-case for leaf-only ebody with two mechanised counterexamples (`Counterexample_L2.v` for fresh-region gap, new `Counterexample_L2_nested.v` for nested-lambda gap). No `formal/*.v` changes in this PR (Stage 1 implementation ships next session). Owner-directive compliance: ✅ no Semantics.v / Typing.v / Counterexample.v touch; ✅ escalation-then-resolution per CLAUDE.md §DO #4; ✅ anti-pattern detector clean across all four stages. Coqc 8.18.0 unaffected (no code changes)."
9+
next_action: "Phase D slice 4 Phase 3b Stage 1b (sibling to #239 — file as follow-up sub-issue): implement the deferred substitution-lemma half. (a) `closed_value_typing_G_poly_l1_m` helper in `formal/Semantics_L1.v` (G-polymorphic retype for closed TFunEff values, addressing the structural blocker discovered in Stage 1a). (b) `subst_typing_gen_l1_m_tfuneff` Qed mirroring `subst_typing_gen_l1_m_ground_nonlinear` (~300 lines); inner T_Lam_L1_*_Eff cases exfalso via the `tfuneff_lambda_free` precondition; direct (P1, P2) hypothesis form (no CPS yet — Stage 3 introduces CPS). May add a third precondition `expr_closed_below 0 v = true` to handle the G-mismatch at compound binder rules; document as Stage 1 restriction lifted in Stage 3/4. (c) `preservation_l2_app_eff_beta_tfuneff_l1` + L2 wrapper Qed in `formal/TypingL2.v` under the 2-condition statement: `tfuneff_lambda_free ebody = true ∧ regions_introduced_by ebody ⊆ R_in_v`. Anti-patterns to refuse (per CLAUDE.md owner directive): no `Admitted` to close cases; no touching `Semantics.v`/`Typing.v`/`Counterexample.v`; no closure of residual `Semantics_L1.v` admits — strictly NEW infrastructure orthogonal to legacy. Coqc 8.18.0 is the only authority."
10+
last_action: "Phase D slice 4 Phase 3b Stage 1a LANDED (2026-05-30 PM, this PR): mechanised soundness-gap witness + Stage 1 syntactic infrastructure. (1) `tfuneff_lambda_free : expr -> bool` Fixpoint added to `formal/Syntax.v` (conservative leaf-only predicate; `false` on every `ELam`, compositional `andb` propagation through compound forms). (2) `formal/Counterexample_L2_nested.v` — three Qed lemmas (`e_before_typed`, `e_step`, `e_after_untypable`) mechanising the nested-TFunEff soundness gap with `outer = ELam T_v (ELam (TBase TUnit) (EVar 1))` configuration where inner R_in_inner = [r2] but substituent R_in_v = []; e_after = ELam TUnit v fails to retype the body at `[r2] ⊄ [] = R_in_v`. (3) Wired into `_CoqProject` after `Counterexample_L2.v`. (4) `SUBST-LEMMA-GENERALIZATION-DESIGN.md` gained a 'Phase 3b Stage 1a (landed) — split from Stage 1' subsection inside the Phase 3b resolution section, documenting the Stage 1a / Stage 1b split and the structural blocker (G-mismatch at compound binder rules — `tfuneff_lambda_retype_l1_m` preserves G but IH expects post-e1 G' with different used-flags) that motivated the split. Stage 1b (substitution lemma + preservation_l2 wrapper) ships next session via a follow-up sub-issue. Build oracle: coqc 8.18.0 clean across all 12 .v files; Print Assumptions on all three new Qed lemmas reports 'Closed under the global context' (zero new admits/axioms). Owner-directive compliance: ✅ no Semantics.v / Typing.v / Counterexample.v touch; ✅ no residual Semantics_L1.v admit closure attempted; ✅ anti-pattern detector clean. Sibling counterexample artifact to `Counterexample_L2.v` (PR #234) for the nested-lambda soundness-gap class; the two together justify the two-condition (P1 = `tfuneff_lambda_free`, P2 = `regions_introduced_by ⊆ R_in_v`) preservation_l2 statement Stage 1b delivers."
1111
updated: 2026-05-30T00:00:00Z
1212

1313
@directive(source="owner", date="2026-05-27", canonical="CLAUDE.md"):

formal/Counterexample_L2_nested.v

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
(* SPDX-License-Identifier: PMPL-1.0-or-later *)
2+
(* SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell *)
3+
4+
(** * Soundness gap (L2): preservation_l2 fails for nested-TFunEff
5+
substituends — the gap Phase 3b Stage 1's [tfuneff_lambda_free]
6+
precondition correctly EXCLUDES.
7+
8+
Sibling artifact to [Counterexample_L2.v]. That earlier file
9+
witnessed the soundness gap for TFunEff substituends crossing
10+
a fresh-region scope ([ERegion]). This file witnesses a
11+
DIFFERENT gap class: TFunEff substituends placed inside an
12+
inner [TFunEff] lambda whose declared [R_in_inner] is too
13+
small to accommodate the substituent's required formation env.
14+
15+
The two together justify the **two**-condition statement of
16+
Phase 3b Stage 1's [preservation_l2_app_eff_beta_tfuneff_l1]:
17+
18+
(P1) [tfuneff_lambda_free ebody = true]
19+
— rules out THIS counterexample's class (inner lambda)
20+
(P2) [regions_introduced_by ebody ⊆ R_in_v]
21+
— rules out [Counterexample_L2.v]'s class (fresh region)
22+
23+
Stage 2 (#240) lifts (P1) by carrying [R_in / R_out] on [ELam].
24+
Stage 3 (#241) replaces (P1) with a CPS-style proof that closes
25+
the inner-lambda case via a relaxed [declared_lambda_r_ins ⊆ R_in_v]
26+
obligation. Stage 4 (#242) reaches an unconditional preservation_l2.
27+
28+
===== Configuration =====
29+
30+
T_v := TFunEff TUnit TUnit [] [] (* substituent type, R_in_v = [] *)
31+
v := ELam TUnit EUnit (* value of type T_v *)
32+
inner_body := ELam TUnit (EVar 1) (* inner lambda; body refs outer var *)
33+
T_inner := TFunEff TUnit T_v [r2] [r2] (* inner lambda's annotated type *)
34+
outer := ELam T_v inner_body (* outer lambda; param of type T_v *)
35+
T_outer := TFunEff T_v T_inner [] [] (* outer type *)
36+
e_before := EApp outer v (* well-typed via T_App_L2_Eff at R = [] *)
37+
e_after := ELam TUnit v (* β-result: subst 0 v inner_body *)
38+
39+
===== Why this configuration witnesses the gap =====
40+
41+
Pre-β [outer] is well-typed because the inner lambda's body
42+
[EVar 1] references the outer variable (de-Bruijn index 1
43+
skipping the inner binder) at type [T_v]. Per [T_Var_Unr_L1]
44+
on a non-linear type ([is_linear_ty T_v = false]), the reference
45+
types at any region env; in particular at [R_in_inner = [r2]].
46+
Side condition [R_in_outer ⊆ R_in_inner] passes vacuously when
47+
[R_in_outer = []].
48+
49+
Post-β substitutes [v] for the outer variable. The inner lambda
50+
body becomes [shift 0 1 v = v] (closed value). So
51+
[e_after = ELam TUnit v]. For [e_after] to type at [T_inner],
52+
[v] would need to retype at [R = [r2]] via [T_Lam_L1_*_Eff],
53+
which requires [[r2] ⊆ R_in_v = []]. This fails on [r2 ∈ [r2]]
54+
vs. [r2 ∉ []].
55+
56+
The structural mechanism: [tfuneff_lambda_retype_l1_m]
57+
(Semantics_L1.v:1257) carries the obligation [R' ⊆ R_in_v];
58+
inside a nested [TFunEff] lambda the [R'] is the INNER
59+
[R_in_inner], not the OUTER formation env — and inner [R_in]
60+
annotations are invisible to Phase 3b Stage 1's syntactic
61+
[regions_introduced_by] over-approximation. Stage 1 therefore
62+
refuses ebody-with-inner-lambdas via [tfuneff_lambda_free].
63+
64+
===== Three theorems =====
65+
66+
- [e_before_typed] — outer at [T_outer] via T_Lam_L1_Affine_Eff
67+
cascaded with inner; full e_before via T_App_L2_Eff.
68+
- [e_step] — operational [S_App_Fun] β-reduction.
69+
- [e_after_untypable] — no L1 derivation exists for e_after at
70+
T_inner. Inversion forces [T_Lam_L1_*_Eff]
71+
(only formation rule producing TFunEff);
72+
both modes' side condition
73+
[forall r, In r [r2] -> In r []] is
74+
contradicted by [In r2 [r2]].
75+
76+
===== Owner-directive compliance =====
77+
78+
- Does not modify [Semantics.v] or [Counterexample.v] (legacy
79+
soundness-gap artifacts).
80+
- Does not patch [Typing.v].
81+
- Does not close any residual [Semantics_L1.v] admit.
82+
- Adds NEW infrastructure (a new file in [formal/]) orthogonal
83+
to legacy admits, mirroring the precedent of [Counterexample.v]
84+
for the legacy preservation and [Counterexample_L2.v] for the
85+
fresh-region soundness-gap class.
86+
- No new [Axiom] or [Admitted] markers. *)
87+
88+
From Ephapax Require Import Syntax Typing TypingL1 Modality Semantics Semantics_L1 TypingL2.
89+
Require Import Coq.Strings.String.
90+
Require Import Coq.Lists.List.
91+
Import ListNotations.
92+
Open Scope string_scope.
93+
94+
Section CounterexampleL2Nested.
95+
96+
Definition r2 : region_name := "r2".
97+
98+
(** Substituent type — a TFunEff lambda with empty input region env. *)
99+
Definition T_v : ty :=
100+
TFunEff (TBase TUnit) (TBase TUnit) [] [].
101+
102+
(** Substituent value — a closed [TUnit -> TUnit] lambda. *)
103+
Definition v : expr :=
104+
ELam (TBase TUnit) EUnit.
105+
106+
(** Inner lambda type — annotated with [R_in = R_out = [r2]]. *)
107+
Definition T_inner : ty :=
108+
TFunEff (TBase TUnit) T_v [r2] [r2].
109+
110+
(** Inner lambda body — references the outer-bound variable via
111+
[EVar 1] (de Bruijn index 1 skips the inner [ELam] binder). *)
112+
Definition inner_body : expr :=
113+
ELam (TBase TUnit) (EVar 1).
114+
115+
(** Outer lambda — parameter of type [T_v], body is [inner_body]. *)
116+
Definition outer : expr :=
117+
ELam T_v inner_body.
118+
119+
(** Outer lambda's type. *)
120+
Definition T_outer : ty :=
121+
TFunEff T_v T_inner [] [].
122+
123+
Definition e_before : expr := EApp outer v.
124+
125+
(** Post-β term: [subst 0 v (ELam TUnit (EVar 1))]
126+
= [ELam TUnit (subst 1 (shift 0 1 v) (EVar 1))]
127+
= [ELam TUnit (shift 0 1 v)] (* EVar 1 substitutes to shift 0 1 v *)
128+
= [ELam TUnit v] (* v is a closed value, shift is identity on its body *) *)
129+
Definition e_after : expr := ELam (TBase TUnit) v.
130+
131+
(** Helper: [v] types at [T_v] at any sufficiently small R. *)
132+
133+
Lemma v_typed_at_empty :
134+
has_type_l1 Affine [] [] v T_v [] [].
135+
Proof.
136+
unfold v, T_v.
137+
eapply T_Lam_L1_Affine_Eff with (u := false).
138+
- intros r Hr; inversion Hr.
139+
- apply T_Unit_L1.
140+
Qed.
141+
142+
(** Outer lambda is well-typed at [T_outer]. *)
143+
144+
Lemma outer_typed :
145+
has_type_l1 Affine [] [] outer T_outer [] [].
146+
Proof.
147+
unfold outer, T_outer, T_inner, inner_body.
148+
eapply T_Lam_L1_Affine_Eff with (u := false).
149+
- intros r Hr; inversion Hr.
150+
- (* Inner lambda formation at outer body context.
151+
Outer body context: [ctx_extend [] T_v = (T_v, false) :: []].
152+
Inner lambda forms at TFunEff (TBase TUnit) T_v [r2] [r2]. *)
153+
eapply T_Lam_L1_Affine_Eff with (u := false).
154+
+ intros r Hr; inversion Hr.
155+
+ (* Body of inner: [EVar 1] at R = [r2], context =
156+
ctx_extend ((T_v, false) :: []) (TBase TUnit)
157+
= ((TBase TUnit, false) :: (T_v, false) :: []).
158+
[EVar 1] looks up [T_v] at index 1; output type [T_v]. *)
159+
eapply T_Var_Unr_L1.
160+
* unfold ctx_lookup. simpl. reflexivity.
161+
* reflexivity.
162+
Qed.
163+
164+
(** ===== (a) e_before is well-typed via T_App_L2_Eff ===== *)
165+
166+
Lemma e_before_typed :
167+
has_type_l2 Affine [] [] e_before T_inner [] [].
168+
Proof.
169+
unfold e_before.
170+
eapply T_App_L2_Eff.
171+
- apply L2_lift_l1. exact outer_typed.
172+
- apply L2_lift_l1. exact v_typed_at_empty.
173+
Qed.
174+
175+
(** ===== (b) The β-step from e_before to e_after =====
176+
177+
[subst 0 v (ELam TUnit (EVar 1))]
178+
= [ELam TUnit (subst 1 (shift 0 1 v) (EVar 1))] (* binder descent *)
179+
= [ELam TUnit (shift 0 1 v)] (* EVar 1 substitutes *)
180+
181+
We need [shift 0 1 v = v]. Since [v = ELam TUnit EUnit] and
182+
[shift c d (ELam T0 e0) = ELam T0 (shift (S c) 1 e0)], we get
183+
[shift 0 1 (ELam TUnit EUnit) = ELam TUnit (shift 1 1 EUnit) =
184+
ELam TUnit EUnit = v]. *)
185+
186+
Lemma e_step :
187+
forall mu, step (mu, [], e_before) (mu, [], e_after).
188+
Proof.
189+
intros mu. unfold e_before, e_after, outer, inner_body.
190+
change (ELam (TBase TUnit) v)
191+
with (subst 0 v (ELam (TBase TUnit) (EVar 1))).
192+
apply S_App_Fun. unfold v. apply VLam.
193+
Qed.
194+
195+
(** ===== (c) e_after does NOT type at T_inner =====
196+
197+
No L1 derivation exists for [[] ; [] |=L1[Affine] e_after :
198+
T_inner -| ?R_out; ?G_out].
199+
200+
Proof by inversion: e_after = ELam (TBase TUnit) v is an [ELam]
201+
whose annotated TFunEff type carries [R_in = [r2]]. Only
202+
[T_Lam_L1_Linear_Eff] and [T_Lam_L1_Affine_Eff] produce
203+
TFunEff types ([T_Lam_L1_Linear] and [T_Lam_L1_Affine] produce
204+
[TFun], discriminated). Both _Eff rules form the body of e_after
205+
([v]) at [R = R_in = [r2]] and require [v] to type at
206+
[TFunEff (TBase TUnit) (TBase TUnit) [] []]; the body
207+
[v = ELam (TBase TUnit) EUnit] re-enters [T_Lam_L1_*_Eff],
208+
whose side condition [forall r, In r [r2] -> In r []] is
209+
contradicted by [In r2 [r2]]. *)
210+
211+
Lemma e_after_untypable :
212+
forall R_out G_out,
213+
~ has_type_l1 Affine [] [] e_after T_inner R_out G_out.
214+
Proof.
215+
intros R_out G_out Ht.
216+
unfold e_after, T_inner, v in Ht.
217+
inversion Ht; subst.
218+
(* Only T_Lam_L1_Affine_Eff survives (mode matches, output type
219+
structure matches). The body [ELam (TBase TUnit) EUnit] at
220+
[R = [r2]] must produce a TFunEff. *)
221+
match goal with
222+
| [ Hbody : has_type_l1 _ (r2 :: nil) _
223+
(ELam (TBase TUnit) EUnit) _ _ _ |- _ ] =>
224+
rename Hbody into Hv_inner
225+
end.
226+
inversion Hv_inner; subst.
227+
(* Only T_Lam_L1_Affine_Eff survives — T_Lam_L1_Affine produces
228+
TFun (discriminated against output type
229+
TFunEff (TBase TUnit) (TBase TUnit) [] []). *)
230+
match goal with
231+
| [ Hside : forall r, In r (r2 :: nil) -> In r nil |- _ ] =>
232+
specialize (Hside r2 (or_introl eq_refl)); inversion Hside
233+
end.
234+
Qed.
235+
236+
(** ===== Soundness-gap witness =====
237+
238+
The three lemmas above ([e_before_typed] + [e_step] +
239+
[e_after_untypable]) jointly witness preservation_l2's failure
240+
for the nested-TFunEff substituent class. No top-level
241+
conjunction theorem is stated for the same Type/Prop-sort reason
242+
documented in [Counterexample_L2.v]. *)
243+
244+
End CounterexampleL2Nested.

formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,21 @@ The staged plan: (3) ships today's value, (1) lands L4's value at L4's timeline,
198198

199199
**Sequencing**: Stage 1 implementation green-lit. Stages 2-4 tracked. Stage 3 blocked on Stage 2; Stage 4 blocked on Stage 3; Stage 2 independent of Stage 1.
200200

201+
#### Phase 3b Stage 1a (2026-05-30 PM, landed) — split from Stage 1
202+
203+
Stage 1's deliverables split into two slices for shipping cadence:
204+
205+
**Stage 1a (this PR, landed)** — Infrastructure + soundness-gap witness:
206+
- `tfuneff_lambda_free : expr -> bool` Fixpoint in `formal/Syntax.v`. Conservative leaf-only predicate: `false` on every `ELam`, `true` elsewhere; propagates compositionally through compound forms via `andb`.
207+
- `formal/Counterexample_L2_nested.v` — three `Qed` lemmas (`e_before_typed`, `e_step`, `e_after_untypable`) mechanising the nested-TFunEff soundness gap. Configuration: `outer = ELam T_v (ELam (TBase TUnit) (EVar 1))` with inner `R_in_inner = [r2]`; `v = ELam TUnit EUnit` at `TFunEff TUnit TUnit [] []`. Post-β `e_after = ELam TUnit v` cannot retype the body at `[r2] ⊄ [] = R_in_v`. Sibling artifact to `Counterexample_L2.v`: together the two files justify the **two-condition** preservation_l2 statement Stage 1 ships (P1 = `tfuneff_lambda_free ebody`, P2 = `regions_introduced_by ebody ⊆ R_in_v`).
208+
- Wired into `_CoqProject` after `Counterexample_L2.v`.
209+
- Zero new admits / axioms (Print Assumptions: all three lemmas Closed under the global context).
210+
211+
**Stage 1b (follow-up issue, deferred)** — Substitution lemma + preservation wrapper:
212+
- `subst_typing_gen_l1_m_tfuneff` Qed in `formal/Semantics_L1.v` mirroring `subst_typing_gen_l1_m_ground_nonlinear` (~300 lines); inner `T_Lam_L1_*_Eff` cases exfalso via `tfuneff_lambda_free`; direct (P1, P2) hypothesis form.
213+
- `preservation_l2_app_eff_beta_tfuneff_l1` + L2 wrapper Qed in `formal/TypingL2.v`.
214+
- The structural blocker requiring deferral: the substitution lemma's compound rule cases (T_Let_L1, T_LetLin_L1, T_Case_L1_*) need to retype the substituent value `v` at a different G (post-e1 used-flag updates). Phase 2's analog uses `ground_nonlinear_retype_l1_m` (R-poly AND G-poly); Phase 3b's `tfuneff_lambda_retype_l1_m` preserves G. The Stage 1b machinery needs EITHER (a) a closed-value G-polymorphism helper (`closed_value_typing_G_poly_l1_m` — provable via inversion on T_Lam_L1_*_Eff formation rules but lengthy), OR (b) a G-flag-polymorphic retype variant. Either path is its own sub-deliverable.
215+
201216
### Phase 4: close `preservation_l2` β-case using Phases 1-3
202217

203218
With the substitution machinery in place, the T_App_L2_Eff β-case in `preservation_l2` closes by:

0 commit comments

Comments
 (0)