You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## Summary
Owner picked **option 5a** (level-split: intro stays at L1 via PR #204,
elim adds `T_App_L2_Eff` to `has_type_l2`) on 2026-05-28 after PR #207
escalated the slice 3 redesign decision.
## Why 5a
`PRESERVATION-DESIGN.md` §5.1 lines 468-474 already endorse this split:
> Effect-typed function types are a typing-layer property, not a
region-layer property. Adding them to L1's unparameterised judgment
would conflate the two. **L2 is the natural home**: the modality
parameter is already a typing-layer decoration; the effect annotation
rides alongside it. **After L2's effect-typed TFun lands, L1's gap
closes by importation, not by re-deriving L1.**
Option 5a returns the slice plan to the design-doc-prescribed line.
## Three subagents converged on viability
- **TypingL2.v audit** (`formal/TypingL2.v:85-91`): single `L2_lift_l1`
constructor; adding `T_App_L2_Eff` as a sibling is additive; zero
downstream consumers in `formal/*.v`.
- **Slice 4 verification** (`formal/Semantics_L1.v:1696-1731`):
`T_App_L1` at `TypingL1.v:231-234` requires `TFun`, NOT `TFunEff`; no
coercion bridge exists; TFunEff lambdas have no L1 application
derivation path → inert-at-L1 closure works by inversion vacuity for the
effect-typed sub-case.
- **Design-doc cross-check**: §5.1 lines 468-474 endorse L1-intro /
L2-elim split; §10 imposes no sequencing constraint blocking 5a.
## Slice 4 split — honest carry-forward
Option 5a closes the effect-typed path (4a) by inversion vacuity but
does **not** close the legacy `TFun` body-R-rigidity path (4b). The
legacy gap is carried forward into `preservation_l2` via L1 importation,
not concealed.
## What's in this PR
- `formal/PHASE-D-REDESIGN.md` — new "Slice 3 sub-sub-addendum — option
5a picked, slice plan revised (2026-05-28, session 5)" section (~110
lines).
- `.machine_readable/6a2/STATE.a2ml` — phase `owner-escalation` →
`implementation`; next_action targets T_App_L2_Eff in TypingL2.v.
## What this PR is NOT
- No code changes to any `.v` file.
- No new `Admitted.` or `Axiom.` declarations.
- No patching of legacy `Semantics.v` or `Typing.v`.
- `Counterexample.v` untouched.
## Test plan
- [x] coqc not invoked — docs-only PR
- [x] Commit is GPG-signed (38ffac4)
- [x] Slice plan reflects option 5a sequencing
- [ ] Auto-merge SQUASH armed post-creation
## Cross-references
- PR #207 — slice 3 sub-addendum + option 4 non-viability
- PR #204 — T_Lam_L1_*_Eff rules (now reframed as inert introduction at
L1)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
next_action: "OWNER DECISION NEEDED — Phase D slice 3 redesign. Option 4 (meta-lemma) provably non-viable per formal/PHASE-D-REDESIGN.md slice 3 sub-addendum (2026-05-28 session 4): strengthened expr_strictly_free_of_region covers ELam's T1 annotation but cannot constrain R_in/R_out in TFunEff (free parameters of T_Lam_L1_*_Eff, syntax-invisible). Remaining options refined: (1) split lemma (high cost; doesn't fully eliminate the blocker), (2) env-frame Δ (medium-high; remove_first still cuts into R_in), (3) defer T_App_L1_Eff (partially viable — closes slice 4 for inert TFunEff lambdas, blocks slice 5), (5) NEW level-split (move T_App_L1_Eff to TypingL2.v as T_App_L2_Eff; L1 lambda-rigidity closes trivially for inert TFunEff at L1; L2 handles effect-typed application from the start). Per CLAUDE.md owner directive 'DO escalate before patching': owner picks the option. No code lands until then."
10
-
last_action: "Phase D slice 3 session 4 (2026-05-28): analysed option 4 (meta-lemma) in detail; proved non-viable due to R_in/R_out being free parameters of T_Lam_L1_*_Eff that strict-free predicate cannot constrain. Documented analysis as slice 3 sub-addendum in formal/PHASE-D-REDESIGN.md. Added option 5 (level-split: T_App in L2, not L1) to the candidate list. Updated owner-decision matrix with cost profiles for options 1/2/3/5. PR landing the analysis as docs-only (no code change, no admits introduced). Slice 4 and slice 5 sit downstream of owner decision."
11
-
updated: 2026-05-28T18:00:00Z
8
+
phase: "implementation"
9
+
next_action: "Phase D slice 3 implementation under option 5a (level-split, intro at L1, elim at L2). Owner picked option 5a 2026-05-28 session 5 after design-doc §5.1 cross-check confirmed alignment with the canonical 'L2 is the natural home for effect-typed TFun' line (PRESERVATION-DESIGN.md lines 468-474). Next concrete code work: add `T_App_L2_Eff` constructor to `has_type_l2` in formal/TypingL2.v as a sibling of `L2_lift_l1` (insertion point after line 91), with premise structure threading R_in/R_out per PHASE-D-REDESIGN.md slice 3 sub-sub-addendum (session 5). Slice 4 split into 4a (TFunEff path closes by inversion vacuity — T_App_L1 requires TFun not TFunEff, no L1 derivation reaches the case) and 4b (legacy TFun body-R-rigidity stays gated; honest admit carried into preservation_l2 via L1 importation). Slice 5 lands new theorem `preservation_l2` over `has_type_l2`."
10
+
last_action: "Phase D slice 3 session 5 (2026-05-28): owner picked option 5a after three subagents converged on viability — TypingL2.v audit confirms thin lift-only inductive ready for thickening with T_App_L2_Eff (sibling to L2_lift_l1, zero downstream breakage in formal/*.v); slice 4 verification confirms TFunEff lambdas have no L1 application derivation path (T_App_L1 at TypingL1.v:231-234 requires TFun not TFunEff, no coercion bridge via linear_to_affine/T_Var/T_Loc, so inert-at-L1 closure works by inversion vacuity for effect-typed path); design-doc §5.1 cross-check confirms option 5a aligns with the canonical L1-intro/L2-elim split documented at PRESERVATION-DESIGN.md lines 468-474. PHASE-D-REDESIGN.md updated with slice 3 sub-sub-addendum documenting option 5a decision, slice 4 split into 4a/4b, T_App_L2_Eff rule sketch with side-condition flow analysis, and slice plan revision. Slice 4b admit honestly recorded as inherited debt to be carried forward into preservation_l2 — option 5a is NOT a closure of preservation_l1, it is a redirection of effect-typed paths to preservation_l2."
The owner picked **option 5a** (level-split, intro stays at L1, elim moves to L2) on 2026-05-28 after the session 4 analysis (slice 3 sub-addendum above) and a session 5 design-doc cross-check.
378
+
379
+
### Why 5a is the right call — design-doc alignment
> **Why this isn't L1's job.** Effect-typed function types are a typing-layer property, not a region-layer property. Adding them to L1's unparameterised judgment would conflate the two. **L2 is the natural home**: the modality parameter is *already* a typing-layer decoration; the effect annotation rides alongside it. **After L2's effect-typed TFun lands, L1's gap closes by importation, not by re-deriving L1.**
384
+
385
+
The doc consistently names the introduction rule `T_Lam_L1_Linear` / `T_Lam_L1_Affine` with the `_L1_` infix, confirming that intro lives in L1. Option 5a is therefore not an architectural departure — it returns the slice plan to the design-doc-prescribed line, which session 3's first slice-3 attempt (T_App_L1_Eff in `has_type_l1`) had deviated from.
386
+
387
+
§10's implementation order ("each step's correctness is independent of the next") imposes no sequencing constraint that blocks 5a.
388
+
389
+
### 5a vs 5b
390
+
391
+
Two sub-variants of option 5 exist:
392
+
393
+
| Sub-option | What | Disposition |
394
+
|---|---|---|
395
+
|**5a (picked)**| Intro stays at L1 via PR #204; elim adds `T_App_L2_Eff` to `has_type_l2`. |**Picked.** Smallest delta from current main. Design-doc-aligned. |
396
+
| 5b | Retract PR #204's L1 intro landing; move both intro and elim into L2. | Discarded — retracts an already-merged PR for marginal architectural neatness; trades real churn for theoretical symmetry. |
397
+
398
+
### What changes vs the original slice plan
399
+
400
+
| Slice | Original plan | Option 5a revised plan |
| 2 |`T_Lam_L1_*_Eff` with R ⊆ R_in side condition | Unchanged — *but reframed as "inert introduction at L1"*. ✅ MERGED PR #204|
404
+
| 3 |`T_App_L1_Eff` in `has_type_l1`|**MOVED**: `T_App_L2_Eff` lands in `has_type_l2` (TypingL2.v) as a sibling of `L2_lift_l1`. |
405
+
| 4 |`preservation_l1` lambda-rigidity closure |**SPLIT** into 4a (effect-typed path) + 4b (legacy path) — see below. |
406
+
| 5 | Broader effect-typing + Phase B/C unblocks | Naturally hosted in L2 with effect-aware lemmas; `preservation_l2` is the new theorem target. |
407
+
408
+
### Slice 4 split — what option 5a does and does not close at L1
409
+
410
+
The session 4 addendum noted that under option 5a, "TFunEff lambdas are inert at L1, and inert values preserve trivially." A session 5 subagent verification confirmed this holds for *one of two* sub-cases inside `preservation_l1`'s `S_App_Step2`:
411
+
412
+
-**Slice 4a — TFunEff lambdas (effect-typed path).** Under option 5a there is no `T_App_L1_Eff` rule, and the legacy `T_App_L1` at `TypingL1.v:231-234` requires `e1 : TFun T1 T2`, NOT `TFunEff`. No coercion bridge exists (`linear_to_affine` is structural; T_Var/T_Loc cannot hide TFunEff). Therefore any `EApp v1 e2` derivation at L1 with `v1` typed via `T_Lam_L1_*_Eff` is vacuous: no L1 derivation reaches this case. The corresponding sub-case in `preservation_l1` closes by inversion vacuity. **No new proof work needed.**
413
+
414
+
-**Slice 4b — legacy `TFun` lambdas (body-R-rigidity path).** The legacy `T_Lam_L1_Linear` / `T_Lam_L1_Affine` rules at `TypingL1.v:177-184` still produce `TFun T1 T2`, and `T_App_L1` at `TypingL1.v:231-234` still accepts them. The body-R-rigidity gap documented in `Semantics_L1.v:1708-1713`*remains* for these lambdas under option 5a — option 5a's level-split does **not** add structural information that closes legacy `TFun` lambda-body preservation across an R-shift. **This sub-case stays gated.**
415
+
416
+
Implication: `preservation_l1` as currently stated (over the whole `has_type_l1` judgment) cannot Qed under option 5a alone. The natural closure venue is `preservation_l2` — a new theorem stated over `has_type_l2`, where effect-typed paths are fully covered and legacy `TFun` paths are honestly carried forward via L1 importation (with the legacy body-R-rigidity admit recorded as inherited debt rather than concealed).
417
+
418
+
### The T_App_L2_Eff rule design
419
+
420
+
The L2 elimination rule mirrors `T_App_L1` but with effect threading through R_in/R_out:
421
+
422
+
```coq
423
+
| T_App_L2_Eff : forall m R R1 G G' G'' e1 e2 T1 T2 R_in R_out,
424
+
has_type_l2 m R G e1 (TFunEff T1 T2 R_in R_out) R1 G' ->
425
+
has_type_l2 m R1 G' e2 T1 R_in G'' ->
426
+
has_type_l2 m R G (EApp e1 e2) T2 R_out G''
427
+
```
428
+
429
+
Reading: e1 produces an effect-typed lambda (consuming R → R1, where R1 is the intermediate env after e1's evaluation). e2 evaluates the argument, threading R1 → R_in (the lambda's input expectation). The lambda body then runs, consuming R_in and producing R_out. The whole `EApp` expression's output env is R_out.
430
+
431
+
The e1 sub-derivation at type `TFunEff T1 T2 R_in R_out` lifts from an L1 derivation via `L2_lift_l1` (since `T_Lam_L1_*_Eff` rules are still the source of TFunEff typings — option 5a keeps intro at L1).
432
+
433
+
**Side condition discharge**: PR #204's `(forall r, In r R -> In r R_in)` constraint (R ⊆ R_in on the lambda's input env) was the load-bearing invariant for slice 2's substitution closure. At elimination time (T_App_L2_Eff), this constraint flows naturally — the lambda was formed at R ⊆ R_in, and the call site supplies R_in directly via e2's output env. No new side condition is needed at elimination.
434
+
435
+
### Implementation surface (verified by session 5 subagent audit)
436
+
437
+
`formal/TypingL2.v` currently has a single constructor `L2_lift_l1` at lines 85-91 — a modality-indexed lift-only inductive ready for thickening. Adding `T_App_L2_Eff` as a sibling constructor (insertion point: after line 91) is additive and has zero downstream consumers in `formal/*.v` (only the file itself references `has_type_l2`). Existing utilities (`weaken_modality`, `weaken_modality_le`, `lift_l1_to_*`, `project_l2_to_l1`) continue to work — they bridge via `L2_lift_l1` for L1-derived facts and the new constructor adds an independent path for T_App_L2_Eff derivations.
438
+
439
+
### Slice plan (post-option-5a)
440
+
441
+
| Slice | Scope | Status |
442
+
|---|---|---|
443
+
| 1 | TFunEff syntax | ✅ MERGED PR #200|
444
+
| 2 |`T_Lam_L1_*_Eff` rules with R ⊆ R_in side condition | ✅ MERGED PR #204|
445
+
| 3 (option 5a) |`T_App_L2_Eff` in TypingL2.v as a sibling constructor to `L2_lift_l1`|**Next**|
446
+
| 4a | TFunEff path inert-at-L1 (closes by inversion vacuity) | Bundled with slice 5 (`preservation_l2`) |
447
+
| 4b | Legacy `TFun` body-R-rigidity at preservation_l1 |**Stays gated**; honest admit carried forward into `preservation_l2` via L1 importation |
448
+
| 5 |`preservation_l2` (new theorem); broader effect-typing; Phase B/C unblocks | After slice 3 |
0 commit comments