Commit c861efb
## Summary
Closes `subst_typing_gen_l1` (the substitution lemma) by m-polymorphic
generalisation, mirroring the `shift_typing_gen_l1_m` pattern landed in
#187.
Net debt in `formal/Semantics_L1.v`: **19 Qed + 4 Admitted → 25 Qed + 3
Admitted**.
## What changed
- New `subst_typing_gen_l1_m` (m-polymorphic, 29 explicit bullets
covering all L1 constructors).
- `subst_typing_gen_l1` becomes a Linear wrapper around `_m`.
- `typing_preserves_bindings_l1` and `output_shape_at_l1` generalised to
modality-polymorphic (mechanical signature change; body unchanged — only
used by `subst_typing_gen_l1` internally, no other estate callers).
- New `loc_retype_at_R_l1_m` (m-polymorphic sibling of the existing
Linear wrapper) so the substituted-value retyping at compound-rule split
points works at the active modality `m`.
- Internal calls switched to `region_liveness_at_split_l1_gen`
(m-polymorphic) instead of the Linear wrapper.
## Why this shape
The substituted-value premise `Hv_type` stays at Linear — callers
(`subst_preserves_typing_l1`, `preservation_l1`) always have a Linear
v-typing. Inside the m-polymorphic body it is unpacked via
`linear_value_is_loc_l1` and reconstructed at the active `m` via
`loc_retype_at_R_l1_m`.
Mode-split rules — T_Lam_L1_{Linear,Affine}, T_Case_L1_{Linear,Affine},
T_If_L1_{Linear,Affine} — each get their own bullet. Affine cases mirror
Linear because substitution threading is modality-independent (the
Affine rules differ only in permitted output flags, which are quantified
inside each rule and transparent to the IH).
## Residual admits in `Semantics_L1.v` (3, down from 4)
1. `region_shrink_preserves_typing_l1_gen` — list-vs-multiset structural
mismatch in T_Region_Active_L1 shadowed case.
2. `region_liveness_at_split_l1_gen` — 1 narrow admit in
T_Region_Active_L1 `[r = rv]` sub-case (genuinely false per documented
counterexample `ERegion rv (EI32 5)`).
3. `preservation_l1` — capstone; depends on closing (1)+(2) under L2
dispatch + lambda-rigidity gap resolution.
## Doctrine compliance (CLAUDE.md 2026-05-27)
- ✅ No new \`Axiom\` declarations.
- ✅ No ad-hoc side conditions on compound rules.
- ✅ No strengthened lemma signatures dodging the L2 dispatch — the
generalisation moves \`m\` *into* the signature, exposing the modality
dispatch, not hiding it.
- ✅ Legacy \`formal/Semantics.v\` and \`formal/Typing.v\` untouched.
## Test plan
- [x] \`coqc\` clean build via \`cd formal && just clean && just all\`
(Coq 8.18.0).
- [x] \`grep -c "Admitted\.$" Semantics_L1.v\` → 3 (was 4).
- [x] \`grep -c "Qed\.$" Semantics_L1.v\` → 25 (was 19).
- [x] No new \`Axiom\` introduced (\`grep -c "^Axiom " formal/*.v\`
unchanged).
- [ ] CI passes.
## Stacking
This PR is stacked on #187 (the 3 affine-only bullet-structure
regressions). GitHub will auto-retarget to \`main\` when #187
squash-merges.
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 58fcf68 commit c861efb
2 files changed
Lines changed: 322 additions & 41 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
56 | 56 | | |
57 | 57 | | |
58 | 58 | | |
59 | | - | |
| 59 | + | |
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| |||
68 | 68 | | |
69 | 69 | | |
70 | 70 | | |
71 | | - | |
| 71 | + | |
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
92 | | - | |
| 92 | + | |
93 | 93 | | |
94 | | - | |
| 94 | + | |
95 | 95 | | |
96 | 96 | | |
97 | 97 | | |
| |||
222 | 222 | | |
223 | 223 | | |
224 | 224 | | |
225 | | - | |
| 225 | + | |
226 | 226 | | |
227 | 227 | | |
228 | 228 | | |
| |||
0 commit comments