Skip to content

docs+test: Phase D slice 4 Phase 4c — mechanised soundness-gap counterexample for TFunEff β#234

Merged
hyperpolymath merged 1 commit into
mainfrom
proof-debt/phase-4c-soundness-gap-counterexample
May 30, 2026
Merged

docs+test: Phase D slice 4 Phase 4c — mechanised soundness-gap counterexample for TFunEff β#234
hyperpolymath merged 1 commit into
mainfrom
proof-debt/phase-4c-soundness-gap-counterexample

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Ships a mechanised proof that preservation_l2 fails for TFunEff substituends inside fresh-region scopes, plus a design-doc addendum prescribing the conditional Phase 4c closure path.

This is the L1/L2 analogue of `formal/Counterexample.v` (which witnesses the legacy preservation's soundness gap), providing rigorous justification for the conditional preservation_l2 statement that Phase 4c will ship.

What this PR ships

`formal/Counterexample_L2.v` (new)

Three Qed lemmas (zero axioms, zero admits) witnessing the soundness gap:

  • `e_before_typed` — input `EApp outer v2` types via T_App_L2_Eff at `TFunEff TUnit TUnit [] []`.
  • `e_step` — operational step S_App_Fun reduces to `ERegion r2 v2`.
  • `e_after_untypable` — no L1 derivation exists for the β-result at the same outer type.

Configuration:

```coq
T1_inner = TFunEff TUnit TUnit [] [] (* R_in_v = [] )
outer = ELam T1_inner (ERegion r2 (EVar 0)) (
body introduces fresh r2 )
v2 = ELam TUnit EUnit (
a value of type T1_inner )
e_before = EApp outer v2 (
well-typed )
e_after = ERegion r2 v2 (
β-result, NOT well-typed *)
```

Structural mechanism: T_Region_L1's `~ In r (free_regions T)` premise prevents the fresh r from being in `R_in_v ⊆ free_regions(TFunEff)`, so the post-β term's inner TFunEff value cannot re-type at the new threaded R = `r :: R`.

`formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md` addendum

New §"Phase 4c addendum (2026-05-30) — conditional preservation_l2 for TFunEff β" documents the counterexample and prescribes three resolution paths:

  1. Conditional preservation_l2 (recommended) — Phase 3b lemma takes the `regions_introduced_by(e) ⊆ R_in_v` precondition; Phase 4c β-case requires it; programs outside form a documented soundness-gap class. Aligns with the `Counterexample.v` precedent for legacy preservation.
  2. Region-polymorphic TFunEff — type-system change deferred to a future redesign.
  3. L2 region-transfer combinator — adds L2 expressiveness in a future PR.

`formal/_CoqProject`

Adds `Counterexample_L2.v` after `TypingL2.v` in the build order.

`.machine_readable/6a2/STATE.a2ml`

`next_action` shifted to Phase 3b implementation (option-(a) precondition codified by this PR's counterexample); `last_action` records the counterexample landing.

Build + assumption audit

  • `coqc -R . Ephapax` clean rebuild across all 11 .v files.
  • `Print Assumptions e_before_typed` / `e_step` / `e_after_untypable` → "Closed under the global context" for all three. Zero axioms, zero admits.

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

  • ✅ Does not modify `formal/Semantics.v` or `formal/Counterexample.v` (the legacy soundness-gap artifacts).
  • ✅ Does not patch `formal/Typing.v` (legacy judgment).
  • ✅ Does not close any residual `formal/Semantics_L1.v` admit.
  • ✅ Adds NEW infrastructure (a new file) orthogonal to legacy admits, mirroring the precedent of `Counterexample.v` for the legacy preservation.
  • ✅ No new `Axiom` or `Admitted` markers.

Why this matters

Before Phase 3b implementation (~400 lines per PR #230's analysis), this counterexample mechanically witnesses the structural constraint the lemma must satisfy. The conditional preservation_l2 design is now rigorously justified rather than asserted on paper.

Test plan

Refs

🤖 Generated with Claude Code

…rexample for TFunEff β

Ships a mechanised proof that preservation_l2 fails for TFunEff
substituends inside fresh-region scopes, plus a design-doc addendum
prescribing the conditional Phase 4c closure path.

## What this PR ships

### `formal/Counterexample_L2.v` (new)

Three Qed lemmas (zero axioms, zero admits) witnessing the soundness gap:

- `e_before_typed`     — input `EApp outer v2` types via T_App_L2_Eff
  at `TFunEff TUnit TUnit [] []`.
- `e_step`             — operational step S_App_Fun reduces to
  `ERegion r2 v2`.
- `e_after_untypable`  — no L1 derivation exists for the β-result
  at the same outer type.

Configuration:

```
T1_inner = TFunEff TUnit TUnit [] []                       (* R_in_v = [] *)
outer    = ELam T1_inner (ERegion r2 (EVar 0))
v2       = ELam TUnit EUnit
e_before = EApp outer v2          (* well-typed *)
e_after  = ERegion r2 v2          (* β-result, not well-typed *)
```

Structural mechanism: T_Region_L1's `~ In r (free_regions T)`
premise prevents the fresh r from being in `R_in_v ⊆ free_regions(TFunEff)`,
so the post-β term's inner TFunEff value cannot re-type at the new
threaded R = `r :: R`.

### `formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md` addendum

New §"Phase 4c addendum (2026-05-30) — conditional preservation_l2 for
TFunEff β" documents the counterexample and prescribes three
resolution paths:

1. **Conditional preservation_l2 (recommended)** — Phase 3b lemma
   takes the `regions_introduced_by(e) ⊆ R_in_v` precondition; Phase
   4c β-case requires it; programs outside form a documented
   soundness-gap class. Aligns with `Counterexample.v` precedent.
2. **Region-polymorphic TFunEff** — type-system change deferred to a
   future redesign.
3. **L2 region-transfer combinator** — adds L2 expressiveness in a
   future PR.

### `formal/_CoqProject`

Adds `Counterexample_L2.v` after `TypingL2.v` in the build order.

### `.machine_readable/6a2/STATE.a2ml`

`next_action` shifted to Phase 3b implementation (option-(a) precondition
codified by this PR's counterexample); `last_action` records the
counterexample landing.

## Build + assumption audit

- `coqc -R . Ephapax` clean rebuild across all 11 .v files.
- `Print Assumptions e_before_typed` / `e_step` / `e_after_untypable`
  → "Closed under the global context" for all three. **Zero axioms.**

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

- Does not modify `formal/Semantics.v` or `formal/Counterexample.v`
  (the legacy soundness-gap artifacts).
- Does not patch `formal/Typing.v` (legacy judgment).
- Does not close any residual `formal/Semantics_L1.v` admit.
- Adds NEW infrastructure (a new file) orthogonal to legacy admits,
  mirroring the precedent of `Counterexample.v` for the legacy
  preservation.
- No new `Axiom` or `Admitted` markers.

## Why this matters

Before Phase 3b implementation (~400 lines per PR #230's analysis),
this counterexample mechanically witnesses the structural constraint
the lemma must satisfy. The conditional preservation_l2 design is now
rigorously justified rather than asserted on paper.

Refs:
- ephapax#225 — Phase 3b tracking issue (option (a) selected).
- ephapax#225 comment 4583148707 — on-paper prototype that motivated
  this mechanical formalisation.
- PR #230 — `regions_introduced_by` scaffold (option (a)'s syntactic
  helper).
- PR #228 — Phase 4a (linear T1, no soundness gap).
- PR #233 — Phase 4b (ground-non-linear T1, no soundness gap).
- `formal/Counterexample.v` — legacy preservation counterexample
  (precedent for this file's structure).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath hyperpolymath enabled auto-merge (squash) May 30, 2026 15:13
@@ -0,0 +1,202 @@
(* SPDX-License-Identifier: PMPL-1.0-or-later *)
@@ -0,0 +1,202 @@
(* SPDX-License-Identifier: PMPL-1.0-or-later *)
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 78 issues detected

Severity Count
🔴 Critical 15
🟠 High 13
🟡 Medium 50

⚠️ 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 coq-build.yml",
    "type": "unknown",
    "file": "coq-build.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"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath merged commit 372b352 into main May 30, 2026
15 of 18 checks passed
@hyperpolymath hyperpolymath deleted the proof-debt/phase-4c-soundness-gap-counterexample branch May 30, 2026 15:22
hyperpolymath added a commit that referenced this pull request May 30, 2026
…ut EACCES

coqorg/coq:8.18 defaults to the non-root `coq` user (UID 1000). actions/checkout's
post-step writes save_state files to /__w/_temp/_runner_file_commands which is
mounted from the runner host; the coq user lacks write permission there and
the job dies with EACCES before `coq_makefile` runs (see #234 PR run).
`--user root` makes the shared workspace paths writable while leaving the
in-container build environment effectively unchanged (root inside the
container maps to the runner host's runner user via the Actions sandbox).

Without this fix the merge-oracle workflow itself can't run, defeating the
hard-gate guarantee in [[feedback_proof_pr_build_oracle_is_only_truth]].

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…DE.md DO #4 (closes nothing, files #235)

Pre-implementation review of Phase 3b's option (a) precondition

  (forall r, In r (regions_introduced_by e) -> In r R_in_v)

found it INSUFFICIENT to discharge T_Lam_L1_*_Eff body cases of the
planned subst_typing_gen_l1_m_tfuneff lemma.

Why: the substitution lemma recurses into inner lambda bodies (Phase
2 does so via the IH at formal/Semantics_L1.v:1929-1942). Inner
T_Lam_L1_*_Eff bodies type at the lambda's declared R_in_inner. R_in
is type-level — it lives in the TFunEff slot of the function's TYPE,
not in syntax. `regions_introduced_by(e)` only collects ERegion
subterms' first arguments; R_in_inner is invisible to it.

`tfuneff_lambda_retype_l1_m` (PR #224) requires R' ⊆ R_in_v to
discharge T_Lam_L1_*_Eff's side condition. We have no way to bound
inner R_in by R_in_v.

Phase 2's `subst_typing_gen_l1_m_ground_nonlinear` dodges this via
`ground_nonlinear_retype_l1_m`, which is fully (m, R, G)-polymorphic.
Phase 3b's TFunEff retype has no analogous escape.

Three resolution options documented:
  1. Syntactic helper `declared_lambda_r_ins` — requires ELam
     annotation extension (parameter type only in current syntax).
  2. Semantic precondition over the derivation — clean meaning,
     awkward in Coq.
  3. Leaf-only Phase 3b via `tfuneff_lambda_free e` predicate —
     tactical landing; Phase 5 compound-value redesign subsumes
     (1)/(2) at leisure.

Recommended: option (3). Owner decision required before Phase 3b
implementation can start.

This PR contains documentation only:
  - formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md gains a Phase 3b
    addendum documenting the gap and three resolution options.
  - .machine_readable/6a2/STATE.a2ml flips phase to
    `blocked-on-owner-decision` with next_action pointing at #235.

No formal/*.v changes.

Predecessor PRs unaffected:
  - Phase 4a (#228) MERGED.
  - Phase 4b (parallel session, #233) MERGED.
  - Phase 4c counterexample (#234) auto-merge pending.

Phase 4c's `Counterexample_L2.v` independently justifies the
conditional preservation_l2 statement regardless of which Phase 3b
resolution lands.

Per CLAUDE.md owner directive §DO #4 (escalate before patching):
this PR IS the escalation.

Owner-directive compliance:
  - No Semantics.v / Typing.v / Counterexample.v touch
  - No new Axiom / Admitted markers
  - No closure of residual Semantics_L1.v admits
  - No sibling-region-disjointness side conditions
  - No proposal to close `Theorem preservation` to Qed.

Refs: #225 (Phase 3b parking lot), #230 (regions_introduced_by
helper), #233 (Phase 4b), #234 (Phase 4c counterexample),

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…DE.md DO #4 (closes nothing, files #235)

Pre-implementation review of Phase 3b's option (a) precondition

  (forall r, In r (regions_introduced_by e) -> In r R_in_v)

found it INSUFFICIENT to discharge T_Lam_L1_*_Eff body cases of the
planned subst_typing_gen_l1_m_tfuneff lemma.

Why: the substitution lemma recurses into inner lambda bodies (Phase
2 does so via the IH at formal/Semantics_L1.v:1929-1942). Inner
T_Lam_L1_*_Eff bodies type at the lambda's declared R_in_inner. R_in
is type-level — it lives in the TFunEff slot of the function's TYPE,
not in syntax. `regions_introduced_by(e)` only collects ERegion
subterms' first arguments; R_in_inner is invisible to it.

`tfuneff_lambda_retype_l1_m` (PR #224) requires R' ⊆ R_in_v to
discharge T_Lam_L1_*_Eff's side condition. We have no way to bound
inner R_in by R_in_v.

Phase 2's `subst_typing_gen_l1_m_ground_nonlinear` dodges this via
`ground_nonlinear_retype_l1_m`, which is fully (m, R, G)-polymorphic.
Phase 3b's TFunEff retype has no analogous escape.

Three resolution options documented:
  1. Syntactic helper `declared_lambda_r_ins` — requires ELam
     annotation extension (parameter type only in current syntax).
  2. Semantic precondition over the derivation — clean meaning,
     awkward in Coq.
  3. Leaf-only Phase 3b via `tfuneff_lambda_free e` predicate —
     tactical landing; Phase 5 compound-value redesign subsumes
     (1)/(2) at leisure.

Recommended: option (3). Owner decision required before Phase 3b
implementation can start.

This PR contains documentation only:
  - formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md gains a Phase 3b
    addendum documenting the gap and three resolution options.
  - .machine_readable/6a2/STATE.a2ml flips phase to
    `blocked-on-owner-decision` with next_action pointing at #235.

No formal/*.v changes.

Predecessor PRs unaffected:
  - Phase 4a (#228) MERGED.
  - Phase 4b (parallel session, #233) MERGED.
  - Phase 4c counterexample (#234) auto-merge pending.

Phase 4c's `Counterexample_L2.v` independently justifies the
conditional preservation_l2 statement regardless of which Phase 3b
resolution lands.

Per CLAUDE.md owner directive §DO #4 (escalate before patching):
this PR IS the escalation.

Owner-directive compliance:
  - No Semantics.v / Typing.v / Counterexample.v touch
  - No new Axiom / Admitted markers
  - No closure of residual Semantics_L1.v admits
  - No sibling-region-disjointness side conditions
  - No proposal to close `Theorem preservation` to Qed.

Refs: #225 (Phase 3b parking lot), #230 (regions_introduced_by
helper), #233 (Phase 4b), #234 (Phase 4c counterexample),

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…ut EACCES (#236)

## Summary

The Coq merge-oracle workflow (`coq-build.yml`) was failing across every
`formal/` PR (including #234 which had to bypass) with:

```
Error: EACCES: permission denied, open '/__w/_temp/_runner_file_commands/save_state_…'
```

## Root cause

`coqorg/coq:8.18` defaults to the non-root `coq` user (UID 1000).
`actions/checkout` writes save_state files to
`/__w/_temp/_runner_file_commands` which is mounted from the runner host
— the `coq` user lacks write permission there. The job dies in
checkout's post-step before `coq_makefile` runs.

## Fix

`container.options: --user root` runs the container as root. The shared
workspace paths become writable; the in-container build environment is
otherwise unchanged (root inside the container maps to the runner host's
runner user via the Actions sandbox, not host-root).

## Why this matters

Per `[[feedback_proof_pr_build_oracle_is_only_truth]]` the Coq workflow
is the *only* merge oracle for `formal/` PRs. If the workflow itself
can't run, the hard gate is effectively bypassed.

## Test plan

- [ ] `Coq build — formal/_CoqProject` goes green on this PR
- [ ] `Print Assumptions of load-bearing theorem` step actually executes
(visible in run log)

🤖 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
 / #242) (#237)

## Summary

Phase D slice 4 Phase 3b — design-gap finding (#235) **+ 4-stage staged
resolution plan** owner-approved 2026-05-30 PM. Stages tracked at #239 /
#240 / #241 / #242.

No `formal/*.v` changes. No CI changes (the parallel-session PR #236
owns the Coq EACCES fix).

## 4-stage staged resolution plan

The original three-option framing in #235 is **superseded** by a staged
plan that captures all three "Interesting" values without committing to
any single option's downsides.

| Stage | Issue | Scope | Captures value of |
|---|---|---|---|
| **Stage 1 — IMMEDIATE** | #239 | Leaf-only Phase 3b via
`tfuneff_lambda_free` + `Counterexample_L2_nested.v` + 2-condition
`preservation_l2`. | Option (3) — principled deferral, honest
2-condition statement. |
| **Stage 2 — parallel L4 track** | #240 | `ELam T_param R_in R_out
body` annotation extension. AST + typing rule + cascading. | Option (1)
— L4 "type-level → program-level commitments". |
| **Stage 3 — post-Stage-2** | #241 | Relaxed Phase 3b via
`declared_lambda_r_ins ⊆ R_in_v` + CPS v-typing argument.
Nested-condition collapses. | Option (2) — higher-order proof style
enters codebase. |
| **Stage 4 — Phase 5** | #242 | Compound non-linear +
region-substitution machinery + **unconditional** `preservation_l2`. |
The final destination. |

### Why staging beats single-option commitments

- **(1) alone**: forces AST migration before unblocking preservation_l2.
- **(2) alone**: introduces inductive-over-derivations predicate with no
other use in the codebase.
- **(3) alone**: ends with conditional preservation_l2 forever (no path
to unconditional).

The staged plan: (3) ships today's value at Stage 1, (1) lands L4's
value at L4's timeline (Stage 2), (2)'s value is harvested at exactly
the point CPS is necessary not over-engineered (Stage 3), (4) reaches
unconditional preservation_l2 as the natural sum.

### Stage 1's correctness is delivered, not provisional

Each of the 2 conditions on Stage 1's `preservation_l2` has a
**mechanised counterexample**:

- `Counterexample_L2.v` (already on main, PR #234) — fresh-region gap.
- `Counterexample_L2_nested.v` (new in Stage 1) — nested-lambda gap.

Programs outside the conditional form a precisely-documented soundness
class.

### Sequencing

- Stage 1 green-lit (#239). Implementation ships next session.
- Stages 2-4 tracked but NOT actioned this session.
- Stage 3 blocked on Stage 2; Stage 4 blocked on Stage 3; Stage 2
independent of Stage 1.

## Changes

- `formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md` — Phase 3b addendum (gap
finding + 3-options framing) **+ Phase 3b resolution addendum (4-stage
staged plan)**.
- `.machine_readable/6a2/STATE.a2ml` — phase = `implementation`;
next_action = Stage 1 (#239) implementation.

No `formal/*.v` changes; Coqc 8.18.0 unaffected.

## Predecessor PRs

- Phase 4a (#228) MERGED — `preservation_l2_app_eff_beta_linear`.
- Phase 4b (#233) MERGED —
`preservation_l2_app_eff_beta_ground_nonlinear_l1`.
- Phase 4c (#234) MERGED — `Counterexample_L2.v` 3-Qed soundness-gap
witness.

## Owner-directive compliance (across all 4 stages)

- ✅ No `Semantics.v` / `Typing.v` / `Counterexample.v` (legacy) touch.
- ✅ No new `Axiom` / `Admitted` markers.
- ✅ No closure of residual `Semantics_L1.v` admits — strictly NEW
infrastructure under the four-layer redesign.
- ✅ Per-layer derivation: preservation_l2 closes via L2 infra; legacy
preservation remains Admitted (PROVABLY FALSE) per 2026-05-27 directive.

## Test plan

- [ ] CI green (no code changes; Coq oracle should pass unchanged —
pending PR #236's EACCES fix landing).
- [ ] Issues #235 / #239 / #240 / #241 / #242 cross-referenced.

Refs: #225 (Phase 3b parking lot), #230 (`regions_introduced_by`), #233
(Phase 4b), #234 (Phase 4c), #235 (parent finding), #236 (parallel Coq
EACCES fix), #239 (Stage 1), #240 (Stage 2), #241 (Stage 3), #242 (Stage
4).

🤖 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
## Summary

- Rewords two docstring lines in `formal/Counterexample_L2.v` to clear
`code_safety/admitted` + `code_safety/coq_admit_tactic` Hypatia
false-positives now red on main since #234 merged
- No code change; pure documentation rewording

## Background

`Counterexample_L2.v`'s docstring "Owner-directive compliance" section
mentioned the literal words "admit" and "[Admitted]" as documentation of
what the file does NOT do. Hypatia's regex (`\bAdmitted\b` /
`\badmit\b`) cannot distinguish documentation of absence from actual
escape hatches.

Two lines reworded:
- Line 50: `Does not close any residual [Semantics_L1.v] admit.` → `Does
not close any residual proof-debt in [Semantics_L1.v].`
- Line 54: `No new [Axiom] or [Admitted] markers.` → `Zero new top-level
proof-hole markers ([Axiom] declarations or Coq unproven-goal forms).`

Semantics preserved; "proof-debt" and "proof-hole markers" are the
standards-canonical terms (per Trusted-Base Reduction Policy).

## Verification

`grep -nE "\b(admit|Admitted)\b" formal/Counterexample_L2.v` returns no
matches.

## Test plan

- [x] No remaining word-boundary matches for the two flagged regexes
- [ ] `hypatia / Hypatia Neurosymbolic Analysis` green on this PR
- [ ] Auto-merge SQUASH armed

🤖 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
…ounterexample_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>
hyperpolymath added a commit that referenced this pull request May 30, 2026
…ff substituents

Ships the L2-judgment half of Stage 1b. Closes the [T_App_L2_Eff]
β-case for T1 = TFunEff Ta Tb R_in_v R_out_v under the three-condition
statement (P1 leaf-only body + P2 regions ⊆ R_in_v + P3 closure of v2).

Mirrors PR #228's [preservation_l2_app_eff_beta_linear] (Phase 4a,
linear T1) and Phase 4b's [preservation_l2_app_eff_beta_ground_nonlinear]
(ground-non-linear T1) structurally with the same
`value_R_G_preserving_l1`-collapse pattern.

Two Qed lemmas:

- `preservation_l2_app_eff_beta_tfuneff_l1` — the L1-level kernel.
  Inverts the lambda derivation through `T_Lam_L1_Linear_Eff` /
  `T_Lam_L1_Affine_Eff`; collapses R_in = R1 = R and G'' = G' = G
  via `value_R_G_preserving_l1`; then defers to the substitution
  kernel `subst_typing_gen_l1_m_tfuneff` (Phase 3b Stage 1b, this
  branch's prior commit) at k = 0.

- `preservation_l2_app_eff_beta_tfuneff` — the L2 wrapper. Inverts
  both `has_type_l2` hypotheses through `L2_lift_l1` (the
  `T_App_L2_Eff` cases discriminate via expression-shape mismatch),
  then defers to the L1 kernel and re-lifts via `L2_lift_l1`.

Combined with PRs #228 (Phase 4a, linear T1) and #233 (Phase 4b,
ground-non-linear T1), this closes the `T_App_L2_Eff` β-case for
T1 ∈ {linear, ground-non-linear, TFunEff}. Phase 4d (compound non-
linear EPair / EInl / EInr / EEcho) remains open at Phase 5.

Print Assumptions verdict:
- 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.

The mechanised soundness-gap witnesses for the conditional form are
preserved in:
- Counterexample_L2.v (PR #234, Phase 4c) — fresh-region gap (the
  counterexample to dropping P2).
- Counterexample_L2_nested.v (Stage 1a, this PR's predecessor #252)
  — nested-lambda gap (the counterexample to dropping P1).

The two files together justify why Stage 1 ships the two-condition
(plus P3 closure) statement rather than an unconditional version.
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.

Also: STATE.a2ml refreshed — last_action now records the full
Stage 1b deliverable surface; next_action advances to Stages 2-4.

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.

Refs:
- ephapax issue #249 (Stage 1b tracking — closes via this PR).
- ephapax PR #252 (Stage 1a prerequisite).
- ephapax issue #239 (parent Stage 1; closes via #252 + this PR).
- formal/SUBST-LEMMA-GENERALIZATION-DESIGN.md Phase 3b Stage 1b.

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.

2 participants