proof(coq): add step_R_eq_or_touches_region region-invariance lemma#114
Merged
Merged
Conversation
Lands a fresh Coq lemma (Qed, ~80 LOC) capturing the structural fact
that the step relation only changes the region environment [R] when
the expression contains a region operation at a step-reducible
position. This is the missing piece for closing the 10 congruence
goals out of preservation's remaining 22 — the sibling-typing
premise in each can be transferred from the pre-step R to the
post-step R' precisely when R = R' (which the lemma's left
disjunct guarantees for non-region step paths).
## What's landed
- `Inductive touches_region : expr -> Prop` — 19 constructors,
one per step-reducible compound form (TR_StringConcat{1,2},
TR_Let, TR_LetLin, TR_App{1,2}, TR_If, TR_Pair{1,2}, TR_Fst,
TR_Snd, TR_Inl, TR_Inr, TR_Case, TR_StringLen, TR_Borrow,
TR_Drop, TR_Copy, plus the base case TR_here for ERegion).
- `Lemma step_R_eq_or_touches_region` (Qed) — for any step
(mu, R, e) -->> (mu', R', e'), either R = R' or e satisfies
touches_region. Proved by induction on step with the same
remember + revert structure used in `preservation` itself
(so the IHs are clean over the inner step's config).
## What's NOT in this PR
- Actually applying the lemma inside `preservation` to close
goals. The intended tactic uses `pose proof + destruct +
subst + IH match`, but in `match goal` form on the specific
22-goal shapes the application hits ltac edge cases I haven't
pinned. The lemma is a usable building block for future
per-case manual proofs; the wholesale `all: try solve` tactic
application is left as an inline comment-sketch for the next
pass.
## Verification
$ coqc -Q . Ephapax Semantics.v
(builds clean; Admitted preservation unchanged at 22 goals)
Refs standards#124, ephapax#102, ephapax#104, ephapax#106.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
added a commit
that referenced
this pull request
May 21, 2026
…ofs (#116) ## Summary **Preservation existential count: 22 → 12** (10 goals closed). Builds on the region-invariance lemma `step_R_eq_or_touches_region` (PR #114) by adding per-step-constructor manual proof scripts inside `Theorem preservation`. ## Closed (10 step constructors) | Constructor | Closure technique | |---|---| | `S_Let_Val`, `S_LetLin_Val` | β-reduction via `subst_preserves_typing` + `value_context_unchanged` | | `S_App_Fun` | Inversion of `ELam` typing + value-context invariance on arg | | `S_If_True`, `S_If_False` | Branch typing under `VBool`'s unchanged-ctx via `value_context_unchanged` | | `S_Fst`, `S_Snd` | `EPair` inversion → child typing match | | `S_Case_Inl`, `S_Case_Inr` | `EInl` / `EInr` typing inversion + body substitution | | `S_Copy` | `T_Pair` on non-linear value with equal pre/post context | ## Open (12 remaining) **11 congruence cases** (`S_StringConcat_Step1/2`, `S_StringLen_Step`, `S_Let_Step`, `S_LetLin_Step`, `S_App_Step1/2`, `S_If_Step`, `S_Pair_Step1/2`, `S_Case_Step`). Root cause: the **linearity-context drift** I diagnosed earlier — even after `step_R_eq_or_touches_region` puts us in the `R = R'` branch, the IH's output context (a Skolem variable from `edestruct`) doesn't unify with the sibling premise's pre-context. So `eapply T_Foo; [exact Hout | exact Hsibling]` fails on the middle-context unification. The tactic-block scaffolding for these 11 cases is in place (poses `step_R_eq_or_touches_region`, dispatches the LEFT branch, specialises `IHHstep`), with the final reconstruction silently failing — they fall through to `Admitted`. The right next step is **lemma B**: a "step preserves output linearity context" or context-transfer re-typing via the existing `typing_ctx_transfer`/`type_determinacy` machinery. **1 region case** (`S_Region_Step` + `T_Region_Active`): the documented language-design blocker — region-env weakening for non-values. Tracked in `formal/PRESERVATION-HANDOFF.md`. ## Verification ``` $ coqc -Q . Ephapax Semantics.v (builds clean; Admitted preservation now at 12 existentials) ``` ## Refs - `standards#124` (proof-debt audit epic) - `ephapax#102` (910 → 29 via remember-cfg) - `ephapax#106` (29 → 22 via universal-IH revert) - `ephapax#114` (region-invariance lemma — used here) ## Cumulative | State | Open goals | |---|---:| | Pre-#102 | 910 | | Post-#102 | 29 | | Post-#106 | 22 | | **Post this PR** | **12** | 98.7% reduction across the day from start of campaign. 🤖 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 21, 2026
…122) Closure sweep after PR #116 took preservation from 22 → 12 open goals and PR #121 landed Phase 1 scaffold. Updates the preservation-count claims across docs to reflect 12, and adds a CHANGELOG entry summarising the full 2026-05-20 → 2026-05-21 reduction campaign. ## Files updated | File | What changed | |---|---| | `README.adoc` | Coq formal-foundations paragraph; reduction chain now lists all 8 PRs through #121; clear pointer to ROADMAP closure plan | | `ROADMAP.adoc` | Formal-proof status table row (`12 open goals`); v0.1 blocker entry; v1.0 status; 97.6% → 98.7% reduction figure | | `EXPLAINME.adoc` | Coq theorem table; reduction-story bullets extended through #114, #116, #121 | | `CHANGELOG.md` | New "Proof state" + "Documentation" sections under `[Unreleased]` tracking the full PR chain (#92, #102, #104, #106, #114, #115, #116, #117, #121) + the Idris2 totality campaign (#89–#100) + doc/wiki refresh (#113 + wiki) | ## Companion wiki update `Home.md`, `Proof-status.md`, `What-can-go-wrong.md` updated in the wiki repo with the same 22 → 12 figures + extended reduction story. Pushed separately to wiki master. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the region-invariance lemma for the step relation — the missing piece of metatheoretic infrastructure that should eventually close ~10 of preservation's remaining 22 goals (the congruence cases where sibling-typing transfer is the only blocker).
What's in
Inductive touches_region : expr -> Prop19 constructors, one per step-reducible compound form:
TR_here— base case (ERegion r e)TR_StringConcat1,TR_StringConcat2— congruence into the two armsTR_Let,TR_LetLin,TR_App1,TR_App2,TR_If,TR_Pair1,TR_Pair2,TR_Fst,TR_Snd,TR_Inl,TR_Inr,TR_Case,TR_StringLen,TR_Borrow,TR_Drop,TR_Copy— congruence into each Step1/Step variantLemma step_R_eq_or_touches_region(Qed)For any step from
(mu, R, e)to(mu', R', e'), either the region environment is preserved (the left disjunct), or the expression contains a region operation at a step-reducible position (the right disjunct).Proof by induction on the step, with the same
remember + revertstructure used insidepreservationitself. Three case classes:Atom steps (R kept literally in the constructor's conclusion — S_StringNew, S_StringConcat, S_StringLen, S_Let_Val, S_LetLin_Val, S_App_Fun, S_If_True, S_If_False, S_Fst, S_Snd, S_Case_Inl, S_Case_Inr, S_Drop, S_Copy): close by
left; reflexivity.Region steps (S_Region_Enter, S_Region_Exit, S_Region_Step): close by
right; apply TR_here.Congruence steps (S_X_StepK): close by IH on the inner step + appropriate
TR_Xconstructor.What's not in
The tactic that would apply this lemma inside
preservationto actually close goals. The intended pattern is documented as a comment-sketch:In isolation the
pose proofstep works (verified by inserting a diagnostic). Inmatch goal with [H : step _ _ |- _] => ...form across all goals viaall: try solve [...], the subsequent destruct/subst/IH chain hits ltac edge cases on these specific goal shapes. The lemma remains usable for future per-case manual proofs — that's the next-session deliverable.Why land this separately
The lemma is reusable infrastructure regardless of whether the wholesale tactic ever lands. Future closures of the 22 remaining goals will reach for
step_R_eq_or_touches_regionper-case anyway. Banking the Qed-closed lemma now means the next session opens with one fewer prerequisite to write.Verification
Refs
standards#124(proof-debt audit epic)ephapax#102(910 → 29 via remember-cfg)ephapax#104(PROOF STATUS docs correction)ephapax#106(29 → 22 via universal-IH revert)Test plan
coqc -Q . Ephapax Semantics.vbuilds cleanstep_R_eq_or_touches_regionat line 3293🤖 Generated with Claude Code