Skip to content

feat(L1): Phase D slice 4 Phase 2 — subst_typing_gen_l1_m_ground_nonlinear + helpers#220

Merged
hyperpolymath merged 1 commit into
mainfrom
proof-debt/standards-134-phase-d-slice-4-phase-2-subst-gen-ground-nonlinear
May 30, 2026
Merged

feat(L1): Phase D slice 4 Phase 2 — subst_typing_gen_l1_m_ground_nonlinear + helpers#220
hyperpolymath merged 1 commit into
mainfrom
proof-debt/standards-134-phase-d-slice-4-phase-2-subst-gen-ground-nonlinear

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Phase 2 of the non-linear substitution-lemma generalisation per formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md §"Phase 2". Builds on Phase 1's ground_nonlinear_retype_l1_m (#219).

Adds three pieces of NEW infrastructure to formal/Semantics_L1.v, all orthogonal to legacy preservation in Semantics.v:

1. Phase 1 generalisation

ground_nonlinear_retype_l1_m extended from (m monomorphic, G monomorphic) to (m → m', G → G')-polymorphic. The 3 ground typing rules (T_Unit_L1 / T_Bool_L1 / T_I32_L1) are themselves polymorphic in both, so the proof is unchanged. Phase 2 needs the cross-modality bridge to lift the Linear-typed Hv_type into the active modality m inside the substitution lemma's compound cases.

2. ground_nonlinear_value_shift_id_l1 helper

Ground non-linear values (EUnit / EBool b / EI32 n) are closed terms, so de Bruijn shift c d v = v for any c, d. Used to rewrite away the shift 0 1 vv that subst introduces when descending through term binders.

3. subst_typing_gen_l1_m_ground_nonlinear parallel lemma

forall m R Gin e T R' Gout,
  has_type_l1 m R Gin e T R' Gout ->
  forall k T1 v u_in,
    nth_error Gin k = Some (T1, u_in) ->
    is_value v ->
    is_ground_nonlinear_ty T1 = true ->
    R; remove_at k Gin |=L1 v : T1 -| R; remove_at k Gin ->
    forall u_out,
      nth_error Gout k = Some (T1, u_out) ->
      has_type_l1 m R (remove_at k Gin) (subst k v e) T R' (remove_at k Gout).

Mirrors subst_typing_gen_l1_m's 28+ case structure. Three key divergences from the linear lemma:

  • T_Var_Lin_L1 with i = k0: rule's is_linear_ty T = true premise contradicts is_ground_nonlinear_ty Tsub = true (discharged via exfalso).
  • T_Var_Unr_L1 with i = k0: CONSTRUCTIVE here (the symmetric case in the linear lemma is the exfalso branch). The substituted value vv is lifted from Linear into the active modality m via ground_nonlinear_retype_l1_m.
  • Compound rules: ground_nonlinear_retype_l1_m replaces the linear_value_is_loc_l1 + loc_retype_at_R_l1_m + region_liveness_at_split_l1_gen pipeline. The retype takes any R', G', m', so no liveness side-condition is required.

Why this matters

Phase 2 unblocks:

  • Phase 3: tfuneff_lambda_retype_l1_m + extend substitution to TFunEff T1 lambdas.
  • Phase 4: close preservation_l2's T_App_L2_Eff β-case for ground non-linear T1 (in TFunEff T1 T2 R_in R_out lambdas with T1 ∈ {TBase TUnit, TBase TBool, TBase TI32}).

Ships as a sibling lemma rather than folding case-split into the existing subst_typing_gen_l1_m to preserve the ~30 Qed downstreams.

Owner-directive compliance

Per CLAUDE.md 2026-05-27:

  • Does NOT close Theorem preservation in Semantics.v.
  • Does NOT extend Semantics.v / Typing.v / Counterexample.v (all untouched).
  • Does NOT close residual Semantics_L1.v admits via this work — strictly NEW infrastructure.
  • Adds no new Axiom or Admitted declarations.

Test plan

  • just clean && just all in formal/ — clean rebuild of all 10 .v files (coqc 8.18.0).
  • Zero new admits/axioms (all proofs Qed).
  • Semantics.v/Typing.v/Counterexample.v untouched.
  • GPG-signed commit.
  • STATE.a2ml next_action shifted to Phase 3.

Diff

  • formal/Semantics_L1.v +322 (lemma + 2 helpers + doc comments)
  • .machine_readable/6a2/STATE.a2ml +1/-1 (state journal advance)

Refs

Refs hyperpolymath/standards#134 (sub-issue of hyperpolymath/standards#124 estate proof-debt epic). Follows #219 (Phase 1). Phase 3 (TFunEff lambda retype) is the next slice.

🤖 Generated with Claude Code

…linear` + helpers

Phase 2 of the non-linear substitution-lemma generalisation per
`formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md` §"Phase 2". Builds on
Phase 1's `ground_nonlinear_retype_l1_m` (PR #219).

Adds three pieces of NEW infrastructure to `formal/Semantics_L1.v`,
all orthogonal to legacy `preservation` in `Semantics.v` (which
remains correctly `Admitted` — provably false per `Counterexample.v`,
per owner directive 2026-05-27):

1. **Generalisation of Phase 1**: `ground_nonlinear_retype_l1_m`
   extended from (m monomorphic, G monomorphic) to
   (m → m', G → G')-polymorphic. The 3 ground typing rules
   (T_Unit_L1 / T_Bool_L1 / T_I32_L1) are themselves polymorphic in
   both, so the proof is unchanged. Phase 2 needs the cross-modality
   bridge to lift the Linear-typed Hv_type into the active modality m
   inside the substitution lemma's compound cases.

2. **`ground_nonlinear_value_shift_id_l1` helper**: ground non-linear
   values (`EUnit` / `EBool b` / `EI32 n`) are closed terms, so the
   de Bruijn `shift c d v = v` for any c, d. Used to rewrite away the
   `shift 0 1 vv` that `subst` introduces when descending through term
   binders (T_Let_L1, T_LetLin_L1, the four T_Lam_L1 lambda rules,
   the two T_Case_L1 case rules).

3. **`subst_typing_gen_l1_m_ground_nonlinear` parallel lemma**:
   mirrors `subst_typing_gen_l1_m`'s case structure for
   `is_ground_nonlinear_ty T1 = true`. Three key divergences from
   the linear lemma:

   - **T_Var_Lin_L1 with `i = k0`**: rule's
     `is_linear_ty T = true` premise contradicts
     `is_ground_nonlinear_ty Tsub = true`
     (ground non-linear types have `is_linear_ty = false` by
     inspection). Discharged via `exfalso`.

   - **T_Var_Unr_L1 with `i = k0`**: CONSTRUCTIVE here (the symmetric
     case in the linear lemma is the exfalso branch). The substituted
     value `vv` at the Linear judgment is lifted to the active
     modality m via `ground_nonlinear_retype_l1_m`.

   - **Compound rules**: `ground_nonlinear_retype_l1_m` replaces the
     `linear_value_is_loc_l1` + `loc_retype_at_R_l1_m` +
     `region_liveness_at_split_l1_gen` pipeline. The retype takes any
     R', any G', any m', so no liveness side-condition is required;
     compound cases collapse to a single retype invocation.

Ships as a **sibling lemma** rather than folding case-split into
the existing `subst_typing_gen_l1_m` to preserve the ~30 Qed
downstreams of the linear version.

Phase 2 unblocks:
- Phase 3 (TFunEff lambda retype + extend substitution to TFunEff T1)
- Phase 4 (close `preservation_l2`'s T_App_L2_Eff β-case for ground
  non-linear T1)

## Owner-directive compliance

Per `CLAUDE.md` 2026-05-27:

- Does NOT close `Theorem preservation` in `Semantics.v`.
- Does NOT extend `Semantics.v` / `Typing.v` / `Counterexample.v`.
- Does NOT close residual `Semantics_L1.v` admits via this work —
  strictly NEW infrastructure orthogonal to legacy.
- Adds no new `Axiom` or `Admitted` declarations.
- Follows post-2026-05-26 four-layer redesign per
  `PRESERVATION-DESIGN.md`.

Build oracle: coqc 8.18.0 clean rebuild across all 10 .v files.

STATE.a2ml `next_action` shifts to Phase 3.

Refs hyperpolymath/standards#134 (sub-issue of hyperpolymath/standards#124).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath hyperpolymath enabled auto-merge (squash) May 30, 2026 12:51
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 74 issues detected

Severity Count
🔴 Critical 13
🟠 High 13
🟡 Medium 48

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in abi-verify.yml",
    "type": "unknown",
    "file": "abi-verify.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in boj-build.yml",
    "type": "unknown",
    "file": "boj-build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "unknown",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in governance.yml",
    "type": "unknown",
    "file": "governance.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in hypatia-scan.yml",
    "type": "unknown",
    "file": "hypatia-scan.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in instant-sync.yml",
    "type": "unknown",
    "file": "instant-sync.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in mirror.yml",
    "type": "unknown",
    "file": "mirror.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in rust-ci.yml",
    "type": "unknown",
    "file": "rust-ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in rust-ci.yml",
    "type": "unknown",
    "file": "rust-ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit 8200ed7 into main May 30, 2026
17 checks passed
@hyperpolymath hyperpolymath deleted the proof-debt/standards-134-phase-d-slice-4-phase-2-subst-gen-ground-nonlinear branch May 30, 2026 12:52
hyperpolymath added a commit that referenced this pull request May 30, 2026
## Summary

- Adds `tfuneff_lambda_retype_l1_m` to `formal/Semantics_L1.v` —
re-types values at `TFunEff T1 T2 R_in R_out` across `R → R'` under the
side condition `forall r, In r R' -> In r R_in`.
- Phase 3a of the SUBST-LEMMA-GENERALIZATION-DESIGN.md plan; mirrors
Phase 1 / Phase 2 split shipped in #219 / #220.
- Zero new admits, zero new axioms, no patch to legacy `preservation` in
`Semantics.v`.

## Why

For values typed at `TFunEff T1 T2 R_in R_out`, the lambda's body is
typed at `R_in` (carried in the type, independent of the outer `R`). The
outer `R` enters the typing rule only through the side condition `forall
r, In r R -> In r R_in`. Re-typing at any `R'` reduces to discharging
the analogous side condition for `R'`.

Two value-shape × typing-rule cases survive `inversion`:
- `T_Lam_L1_Linear_Eff` — Linear-modality TFunEff lambda
- `T_Lam_L1_Affine_Eff` — Affine-modality TFunEff lambda

Legacy `T_Lam_L1_Linear` and `T_Lam_L1_Affine` produce `TFun …` (not
`TFunEff …`) so `inversion` auto-discharges them via
constructor-conclusion equation discrimination. Non-lambda value shapes
(`EUnit` / `EBool` / `EI32` / `EPair` / `EInl` / `EInr` / `ELoc` /
`EBorrow` / `EEcho`) are typed at base / product / sum / borrow / region
/ echo types — all distinct from `TFunEff` — and discharge identically.

## Why split Phase 3 into 3a + 3b

SUBST-LEMMA-GENERALIZATION-DESIGN.md Phase 3 originally combined (a) the
retype lemma + (b) the substitution-lemma extension. Splitting follows
the Phase 1 / Phase 2 pattern (Phase 1 = retype lemma; Phase 2 = subst
lemma) and keeps the PR minimal-purpose. Phase 3b (extend
`subst_typing_gen_l1_m` to TFunEff lambda substituends) is queued as a
follow-on.

## Constraints preserved (owner directive 2026-05-27)

- ✅ Does not patch legacy `Semantics.v` `preservation` (provably false
via `Counterexample.v`).
- ✅ Does not extend `Semantics.v` with closure-support lemmas.
- ✅ Does not close residual `Semantics_L1.v` axioms via proof tricks —
Phase 3a adds NEW infrastructure orthogonal to legacy admits.
- ✅ Does not follow pre-2026-05-26 closure plans.
- ✅ Works per-layer (L1 infrastructure → L2 preservation closure
downstream).
- ✅ Modality `m` preserved (cannot vary like Phase 1's ground lemma —
body's modality matches conclusion's).
- ✅ Context `G` preserved (body typed in `ctx_extend G T1`).

## Build

`just -f formal/Justfile all` — Rocq 9.1.1 / Coq 8.18.x.

\`\`\`
COQC Syntax.v
COQC Typing.v
COQC Modality.v
COQC TypingL1.v
COQC Semantics.v
COQC Semantics_L1.v   ← contains the new lemma
COQC Counterexample.v
COQC Echo.v
COQC TypingL2.v
COQC L4.v
\`\`\`

Zero errors, zero new admits.

## Diff

- \`formal/Semantics_L1.v\` +60 (lemma + 35-line docstring)

## Refs

Refs hyperpolymath/standards#124 (estate proof-debt epic)
Refs hyperpolymath/standards#134 (ephapax sub-issue)
Refs \`formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md\` Phase 3

## Phase ladder

- ✅ Phase 1 — \`ground_nonlinear_retype_l1_m\` (#219)
- ✅ Phase 2 — \`subst_typing_gen_l1_m_ground_nonlinear\` + helpers
(#220)
- ✅ Phase 3a — \`tfuneff_lambda_retype_l1_m\` ← **this PR**
- ⏳ Phase 3b — \`subst_typing_gen_l1_m_tfuneff\` (extend subst to
TFunEff substituends)
- ⏳ Phase 4 — close \`preservation_l2\` β-case using Phases 1-3
- ⏳ Phase 5 (deferred) — compound non-linear values

## Test plan

- [x] Toolchain build green (\`just -f formal/Justfile all\`)
- [x] No new \`Admitted.\`, no new \`Axiom\`
- [x] GPG-signed commit

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…is_tfuneff_ty` (#224)

## Summary

- Ships the **retype lemma half** of Phase 3 per
`formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md`.
- Adds `is_tfuneff_ty` predicate (Syntax.v) mirroring
`is_ground_nonlinear_ty`.
- Adds `tfuneff_lambda_retype_l1_m` lemma (Semantics_L1.v): retype
TFunEff lambda value across `(m, R, G) → (m, R', G)` under side
condition `forall r, In r R' → In r R_in`.
- **Phase 3b (substitution-lemma extension) DESCOPED** to a follow-up PR
after structural analysis revealed the `T_Region_L1` fresh-region
obstacle. STATE.a2ml documents the three candidate solutions.

## Why split

`SUBST-LEMMA-GENERALIZATION-DESIGN.md` Phase 3 proposed two pieces
(retype + substitution extension). Walking the substitution proof
revealed: every retype across a threaded `R_n` inside the term `e`
demands `forall r, In r R_n → In r R_in_arg`, and `T_Region_L1` firings
inside `e` introduce fresh `r ∉ R_outer` — freshness wrt the threaded R
does **not** imply membership in the value-type's fixed `R_in_arg`.
Three candidate fixes (syntactic side condition on `e`; universal-R
Hv_type with per-case discharge; restrict to region-free terms) need
Phase 4 prototyping of the actual `subst 0 varg ebody` shape before
choosing. Phase 3a's retype lemma stands on its own as clean
infrastructure usable in 3b and Phase 4.

## Proof shape

`tfuneff_lambda_retype_l1_m`:
- `destruct Hval` (10 value-form cases)
- `inversion Ht; subst; try discriminate`
  - Non-ELam forms: types don't match TFunEff → `discriminate`.
- ELam at TFun (legacy rules `T_Lam_L1_Linear` / `T_Lam_L1_Affine`):
type mismatch TFun ≠ TFunEff → `discriminate`.
- ELam at TFunEff (`T_Lam_L1_Linear_Eff` / `T_Lam_L1_Affine_Eff`):
re-apply rule with new `Hsub`, body via `eassumption`.

Zero new admits, zero new axioms. Coqc 8.18.0 clean rebuild across all
10 .v files.

## Owner-directive compliance (per `CLAUDE.md` 2026-05-27)

- ✅ No closure of legacy `preservation` in `Semantics.v` (untouched).
- ✅ No closure-support lemmas in `Semantics.v` (untouched).
- ✅ No closure of residual `Semantics_L1.v` admits — strictly NEW
orthogonal infrastructure.
- ✅ No patching `Typing.v` (untouched).
- ✅ No new `Admitted` / `Axiom`.
- ✅ Anti-pattern detector clean.

## Test plan

- [x] `coqc -Q . Ephapax` clean across all 10 .v files locally.
- [ ] CI green on `formal/` build job.

Refs: standards#134 (proof-debt epic), #220 (Phase 2), #213 (design
doc).
hyperpolymath added a commit that referenced this pull request May 30, 2026
…) (#230)

## Summary

Adds \`regions_introduced_by : expr -> list region_name\`, a
\`Fixpoint\` collecting region names introduced by \`ERegion\` subterms.

This is scaffolding infrastructure for Phase D slice 4 Phase 3b
(\`subst_typing_gen_l1_m_tfuneff\`) per ephapax issue #225's recommended
option (a).

## Why now

Phase 3b's main obstacle (per #225 analysis): retyping a TFunEff value
at \`r :: R\` (post T_Region_L1 inside substituee body) requires \`r ∈
R_in_v\`, but \`r\` is fresh and unconstrained relative to \`R_in_v\`.
Option (a) resolves this by adding a syntactic over-approximation
precondition:

\`\`\`coq
(forall r, In r (regions_introduced_by e) -> In r R_in_v)
\`\`\`

The precondition is decomposable through compound rules (each
sub-expression's \`regions_introduced_by\` is a subset of the parent's)
and discharges directly at the \`T_Region_L1\` case (where \`r\` is the
head of \`regions_introduced_by (ERegion r e')\`).

## Why split this scaffold off

The full Phase 3b lemma is ~400 lines mirroring Phase 2 with
\`shift_typing_gen_l1_m\` threading at every binder-descent case (Phase
2's \`ground_nonlinear_value_shift_id_l1\` shortcut doesn't apply to
non-scalar TFunEff lambdas — \`shift c 1 (ELam T0 e0) = ELam T0 (shift
(S c) 1 e0)\`, which changes the body's de Bruijn indices). That scope
exceeds the single-session budget that Phase 1 / Phase 2 / Phase 3a have
been shipping at.

Landing the helper alone keeps a future Phase 3b implementation PR
focused on the lemma body without re-introducing the predicate.

## Verification

\`\`\`
$ cd /tmp/ephapax-phase-3b/formal && just all
coq_makefile -f _CoqProject -o build.mk
make -f build.mk
COQDEP VFILES
COQC Syntax.v
COQC Typing.v
COQC Modality.v
COQC TypingL1.v
COQC Semantics.v
COQC Semantics_L1.v
COQC Counterexample.v
COQC Echo.v
COQC TypingL2.v
COQC L4.v
(exit 0)
\`\`\`

Rocq 9.1.1 / Coq 8.18. Zero new admits, zero new axioms. Helper is
currently unused by any lemma — landing as preparatory infrastructure.

## Owner-directive compliance

- ✅ Does NOT modify \`Semantics.v\`.
- ✅ Does NOT add new admits or axioms.
- ✅ Pure syntactic Fixpoint; no semantic consequences.
- ✅ Lives in \`Syntax.v\` alongside \`is_ground_nonlinear_ty\` and
\`is_tfuneff_ty\` (matching precedent).

## Refs

- ephapax#225 — Phase 3b tracking issue, option (a)
- formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md Phase 3b
- PR #220 — Phase 2 (\`subst_typing_gen_l1_m_ground_nonlinear\`) for
structural template
- PR #228 — Phase 4a (\`preservation_l2_app_eff_beta_linear\`) for Phase
4 use shape

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…-linear T1 (#233)

## Summary

Phase 4 continuation following PR #228's Phase 4a (linear T1). Closes
the \`T_App_L2_Eff\` β-case (\`S_App_Fun\` step) for ground-non-linear
T1 ∈ { \`TBase TUnit\`, \`TBase TBool\`, \`TBase TI32\` } via Phase 2's
\`subst_typing_gen_l1_m_ground_nonlinear\` (PR #220).

Two lemmas, mirroring #228's Linear pattern:

- **\`preservation_l2_app_eff_beta_ground_nonlinear_l1\`** — L1-level
kernel. Inversion on the lambda forces \`T_Lam_L1_*_Eff\` (TFun cases
discriminate); \`value_R_G_preserving_l1\` on the argument collapses
\`R_in\` / \`G''\` to \`R\` / \`G\`. The Linear case discharges the
\`|=L1\` (Linear) \`Hv_type\` premise directly with \`Harg\`; the Affine
case bridges via \`ground_nonlinear_retype_l1_m\` (cross-modality, same
R) since Phase 2's premise uses the Linear-only \`|=L1\` shorthand.

- **\`preservation_l2_app_eff_beta_ground_nonlinear\`** — L2 wrapper.
Inverts both \`has_type_l2\` hypotheses through \`L2_lift_l1\`
(\`T_App_L2_Eff\` discriminates: lambda's head is \`ELam\` not \`EApp\`;
argument is a value). Defers to the L1 kernel and re-lifts via
\`L2_lift_l1\`.

Combined with PR #228's Phase 4a, this closes \`T_App_L2_Eff\` β for T1
∈ { **linear**, **ground-non-linear** }. Remaining open:
- **Phase 4c** (\`TFunEff T1\`) — blocked on Phase 3b, [issue
#225](#225).
- **Phase 4d** (compound: \`EPair\` / \`EInl\` / \`EInr\` / \`EEcho\`
with non-linear sub-components) — deferred to Phase 5 per
\`SUBST-LEMMA-GENERALIZATION-DESIGN.md\`.

## Build + assumption audit

\`\`\`
$ cd /tmp/ephapax-phase-4b/formal && just all
coq_makefile -f _CoqProject -o build.mk
make -f build.mk
COQDEP VFILES
COQC TypingL2.v
COQC L4.v
(exit 0)
\`\`\`

- Rocq 9.1.1 / Coq 8.18 clean rebuild across all 10 .v files.
- Zero new admits, zero new axioms.
- \`Print Assumptions preservation_l2_app_eff_beta_ground_nonlinear\`
shows only pre-existing axioms inherited transitively via
\`subst_typing_gen_l1_m_ground_nonlinear\` (PR #220's audit closed that
lemma under the global context).

## Net delta

- \`formal/TypingL2.v\`: +83 lines (one L1 kernel lemma + one L2 wrapper
lemma + ~30 line docstring).
- No other files touched.

## Owner-directive compliance (CLAUDE.md 2026-05-27)

- ✅ Does NOT close \`Theorem preservation\` in \`formal/Semantics.v\`.
- ✅ Does NOT extend \`Semantics.v\` / \`Typing.v\` /
\`Counterexample.v\`.
- ✅ Does NOT close any residual \`Semantics_L1.v\` admit (purely new
infrastructure).
- ✅ Works per-layer: L1 kernel + L2 wrapper, both at the post-redesign
m-indexed \`has_type_l1\` judgment.
- ✅ Reads \`PRESERVATION-DESIGN.md\` /
\`SUBST-LEMMA-GENERALIZATION-DESIGN.md\` first.
- ✅ No new \`Axiom\` or \`Admitted\` markers.

## Refs

- PR #220 — Phase 2 (\`subst_typing_gen_l1_m_ground_nonlinear\`)
- PR #228 — Phase 4a (linear T1 sibling)
- ephapax#225 — Phase 4c gating issue (TFunEff)
- formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md Phase 4
- formal/PRESERVATION-DESIGN.md §5.1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant