Commit 6ce16d1
## Summary
Ships **Stage 1b** of the four-stage Phase 3b resolution plan (parent
#235 / Stage 1 #239 / Stages 2-4 #240-#242), closing the L1 substitution
+ L2 preservation β-case for closed TFunEff substituents in leaf-only
outer bodies.
**Builds on Stage 1a (PR #252, auto-merge armed)** which shipped the
syntactic infrastructure (`tfuneff_lambda_free`) + the soundness-gap
witness (`Counterexample_L2_nested.v`).
Closes ephapax issue #249. With this PR, Stage 1 (#239) is fully
delivered.
## What ships
### Syntax.v (canonical closure machinery)
- `expr_closed_below : nat -> expr -> bool` — Fixpoint, bool per
post-redesign convention. Standard CS "no free de Bruijn variables ≥ k"
predicate.
- `closed_below_shift_id` — closed-below-c terms are shift-invariant at
cutoff c.
- `expr_closed_below_shift_mono` — closure survives shifting.
- `ctx_mark_used_app_lt` — `ctx_mark_used` commutes with context append
when marked position lies within the head.
### Semantics_L1.v (body-transfer + RG-poly retype)
- `closed_below_k_typing_outer_tail_irrelevant_l1_m` — the body-transfer
core. Structural induction across 28+ typing rules; ~200 lines.
Establishes that closed-below-k terms' typing depends only on G's first
k positions; the tail is structurally irrelevant.
- `closed_value_typing_G_poly_l1_m` — closed TFunEff values type at any
G' (any-G' form per elegance-first "state what's actually true", not "G
of matching length").
- `closed_value_typing_RG_poly_l1_m` — combined RG-poly retype chaining
the G-poly helper with `tfuneff_lambda_retype_l1_m` (PR #224) for the
R-component under `R' ⊆ R_in` side condition.
- `closed_value_shift_id_l1_m` — cutoff-0 wrapper of
`closed_below_shift_id`.
- `value_TFunEff_R_subset_R_in_l1_m` — extracts `R ⊆ R_in` from a
TFunEff value's typing.
- `sub_R_in_R_in_via_value_l1_m` — chain helper packaging
`count_occ_le_l1_m` + R-subset for compound-rule call sites.
- `subst_typing_gen_l1_m_tfuneff` Qed (~300 lines) — mirrors Phase 2's
`subst_typing_gen_l1_m_ground_nonlinear`. Inner `T_Lam_L1_*_Eff` cases
discharge via P1 `discriminate`; compound rules use the RG-poly retype +
R-subset chain to handle the G-mismatch.
### TypingL2.v (β-case closure)
- `preservation_l2_app_eff_beta_tfuneff_l1` — L1-level kernel. Inverts
the lambda derivation through `T_Lam_L1_Linear_Eff` /
`T_Lam_L1_Affine_Eff`; collapses R/G via `value_R_G_preserving_l1`;
defers to the substitution kernel above at k=0.
- `preservation_l2_app_eff_beta_tfuneff` — L2 wrapper. Inverts both
`has_type_l2` hypotheses through `L2_lift_l1` (the `T_App_L2_Eff` cases
discriminate via expression-shape mismatch).
### `.machine_readable/6a2/STATE.a2ml`
- `last_action` records the full Stage 1b deliverable surface.
- `next_action` advances to Stages 2-4 (#240/#241/#242).
## Two-condition statement (per Stage 1 framing)
```coq
Lemma preservation_l2_app_eff_beta_tfuneff :
forall m R R1 G G' G'' v2 Ta Tb R_in_v R_out_v T2 R_in R_out ebody,
is_value v2 ->
tfuneff_lambda_free ebody = true -> (* P1 *)
(forall r, In r (regions_introduced_by ebody) -> In r R_in_v) -> (* P2 *)
expr_closed_below 0 v2 = true -> (* P3 *)
has_type_l2 m R G (ELam (TFunEff Ta Tb R_in_v R_out_v) ebody)
(TFunEff (TFunEff Ta Tb R_in_v R_out_v) T2 R_in R_out) R1 G' ->
has_type_l2 m R1 G' v2 (TFunEff Ta Tb R_in_v R_out_v) R_in G'' ->
has_type_l2 m R G (subst 0 v2 ebody) T2 R_out G''.
```
The mechanised soundness-gap witnesses for the conditional form:
- `Counterexample_L2.v` (PR #234, Phase 4c) — fresh-region gap
(counterexample to dropping P2).
- `Counterexample_L2_nested.v` (Stage 1a, PR #252) — nested-lambda gap
(counterexample to dropping P1).
Stage 4 (#242) achieves the unconditional form once the L4 annotation
extension (#240) and CPS argument (#241) land — the proof content of
this PR's `closed_value_typing_*` family is reused unchanged in Stage 4
as the closure-discharge kernel.
## Path-(i) elegance-first design choices
Per the priority order (elegance + correctness > everything; workload
least), this PR bakes in two explicit refinements over the issue body's
draft:
1. **`bool` predicate target** for `expr_closed_below` — matches
post-redesign convention (`is_linear_ty`, `is_ground_nonlinear_ty`,
`tfuneff_lambda_free` are all bool). The legacy Prop predicates
(`expr_free_of_region`) are pre-redesign artefacts.
2. **Any-G' statement form** for the closed-value helper — states what's
actually true ("for closed values, G is genuinely irrelevant"), not what
fell out of the proof induction.
Two refinements that touch approved scope were deliberately NOT made:
- P1 (`tfuneff_lambda_free`) precondition retained, not dropped —
re-staging is owner territory.
- 4-stage plan accepted as is — no re-staging proposal folded into Stage
1b.
## Print Assumptions verdict
All new Qed lemmas: **Closed under the global context**.
- `subst_typing_gen_l1_m_tfuneff`: Closed under the global context
- `closed_value_typing_G_poly_l1_m`: Closed under the global context
- `closed_value_typing_RG_poly_l1_m`: Closed under the global context
- `closed_below_k_typing_outer_tail_irrelevant_l1_m`: Closed under the
global context
- `preservation_l2_app_eff_beta_tfuneff_l1`: Closed under the global
context
- `preservation_l2_app_eff_beta_tfuneff`: Closed under the global
context
Zero new axioms. Zero new admits.
## 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 (canonical CS infrastructure; no
sibling-region-disjointness, no region-weakening predicates on syntactic
shape, no admit-shuffling, no legacy-preservation closure attempt).
- ✅ Strictly NEW infrastructure orthogonal to legacy.
## Test plan
- [x] `just -f formal/Justfile all` clean across all 12 .v files
- [x] Print Assumptions on every new Qed lemma reports "Closed under the
global context"
- [x] No `Axiom` / `Admitted` introduced
- [x] No legacy file touched per owner directive
- [x] Stage 1a's contributions (`tfuneff_lambda_free`,
`Counterexample_L2_nested.v`) still build clean
- [x] Phase 2's contributions (`ground_nonlinear_retype_l1_m`,
`subst_typing_gen_l1_m_ground_nonlinear`) still build clean
- [x] Phase 4a + 4b L2 β-wrappers still build clean
- [ ] `coq-build.yml` CI workflow runs against this PR (gated on PR #231
/ #236 fixes)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7f27aa8 commit 6ce16d1
4 files changed
Lines changed: 1304 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
10 | | - | |
11 | | - | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| |||
0 commit comments