@@ -91,22 +91,25 @@ See PROOF-NARRATIVE §2.5.
9191| ** T-Determinism** | The step relation is deterministic: ` e → e₁ ∧ e → e₂ ⟹ e₁ = e₂ ` . | ` Tangle.lean:422-549 ` |
9292| ** T-TypeSafety** | Well-typed closed terms never get stuck (Progress + Preservation corollary). | ` Tangle.lean:556-558 ` |
9393
94- Each is proven for the ** let-free fragment** of the core: numerals,
95- strings, booleans, identity, braid literals, composition, tensor,
96- pipeline, close, addition, and equality.
94+ Each is proven for the ** full core fragment** : numerals, strings, booleans, identity,
95+ braid literals, composition, tensor, pipeline, close, addition, equality, variables,
96+ let-binding, the complete echo/product fragment (see §2.5), and decidable type
97+ inference (see §2.7). The "let-free fragment" caveat is retired — TG-1 and TG-2 are both landed.
9798
9899### Supporting lemmas
99100
100101| ID | Statement | Where |
101102| ----| -----------| -------|
102- | T-ValueNoStep | Values are normal forms: ` IsValue e ⟹ ¬ Step e e' ` . | ` Tangle.lean:189 ` |
103- | T-CanonicalNum | A typed-Num value is ` .num n ` for some ` n ` . | ` Tangle.lean:193-194 ` |
104- | T-CanonicalStr | A typed-Str value is ` .str s ` for some ` s ` . | ` Tangle.lean:197-198 ` |
105- | T-CanonicalWord | A typed-Word[ n] value is ` .identity ` (n=0) or ` .braidLit gs ` (n = width gs). | ` Tangle.lean:201-209 ` |
106- | T-WidthAppend | ` width(gs₁ ++ gs₂) = max(width gs₁, width gs₂) ` . | ` Tangle.lean:219-221 ` |
107- | T-WidthShift | ` width(shift gs n) = if gs=[] then 0 else width gs + n ` . | ` Tangle.lean:235-238 ` |
108- | T-FoldlMaxInit (private) | Algebraic identity for the width fold. | ` Tangle.lean:212-217 ` |
109- | T-FoldlShiftInit (private) | Algebraic identity for the shifted width fold. | ` Tangle.lean:223-233 ` |
103+ | T-ValueNoStep | Values are normal forms: ` IsValue e ⟹ ¬ Step e e' ` . | ` Tangle.lean:394 ` |
104+ | T-CanonicalNum | A typed-Num value is ` .num n ` for some ` n ` . | ` Tangle.lean:405 ` |
105+ | T-CanonicalStr | A typed-Str value is ` .str s ` for some ` s ` . | ` Tangle.lean:409 ` |
106+ | T-CanonicalWord | A typed-Word[ n] value is ` .identity ` (n=0) or ` .braidLit gs ` . | ` Tangle.lean:413 ` |
107+ | T-CanonicalEcho | A typed-Echo value is ` .echoVal r v ` for values r, v. | ` Tangle.lean:428 ` |
108+ | T-CanonicalProd | A typed-Prod value is ` .pair a b ` for values a, b. | ` Tangle.lean:443 ` |
109+ | T-WidthAppend | ` width(gs₁ ++ gs₂) = max(width gs₁, width gs₂) ` . | ` Tangle.lean:466 ` |
110+ | T-WidthShift | ` width(shift gs n) = if gs=[] then 0 else width gs + n ` . | ` Tangle.lean:485 ` |
111+ | ** T-Weakening** | Inserting a fresh hypothesis at de Bruijn position ` Γ₁.length ` preserves typing (TG-1). | ` Tangle.lean:521 ` |
112+ | ** T-SubstPreserves** | Typing is preserved under capture-avoiding substitution of a typed term for a variable (TG-1). | ` Tangle.lean:589 ` |
110113
111114### Type-system and step-relation definitions
112115
@@ -195,48 +198,106 @@ pre-PR #46 `main` did not compile due to two `Warning 8` exhaustiveness gaps
195198** TG-3 gap remains** : the OCaml typechecker is not yet proven to refine ` HasType ` ;
196199the correspondence is validated by the test suite, not by a formal translation.
197200
198- ## 3. Remaining obligations (the narrative arc )
201+ ## 2.7 Let-binding and decidability (TG-1 + TG-2 )
199202
200- What's not yet proven, why it matters, and what assumption each rests on.
203+ Both obligations landed in ` proofs/Tangle.lean ` and are documented in §TG-1 and
204+ §TG-2 of the remaining-obligations section below (those sections now carry LANDED
205+ verdicts). Key structural points:
201206
202- ### TG-1 — Type safety extended to ` let ` -binding
207+ - ** TG-1 (let-binding)** : ` weakening ` + ` subst_preserves ` use the de Bruijn
208+ combined-context invariant — ` subst_preserves ` types the substitutee in
209+ ` Γ₁ ++ Γ₂ ` , not merely ` Γ₂ ` . This is the genuine inductive invariant; the
210+ ` letRed ` consumer uses ` Γ₁ := [] ` where both forms coincide.
203211
204- ** Claim.** Type safety extends to the language fragment with ` let ` .
212+ - ** TG-2 (decidability)** : ` infer ` is a single structural recursion covering all
213+ 26 ` HasType ` rules. Both soundness and completeness are proven; ` type_unique `
214+ follows as a corollary. The ` decidableHasType ` instance makes ` HasType [] e τ `
215+ a decidable proposition directly usable by Lean's typeclass system.
205216
206- ** Why valuable.** The header comment of ` Tangle.lean ` explicitly
207- parks this: "T-Let: ... a future version can add the full substitution
208- machinery from e.g. Autosubst." Until then T-TypeSafety is for the
209- let-free fragment only. ` let ` is in the surface language (`compiler/
210- lib/ast.ml`), so users can write programs the proof doesn't cover.
217+ ## 2.8 Echo-types grade semiring — design note
211218
212- ** Assumptions.**
213- - [[ A-TG-1.1]] Capture-avoiding substitution is well-defined on the
214- de Bruijn representation already used by ` HasType ` .
215- - [[ A-TG-1.2]] The standard "weakening" and "substitution" lemmas hold
216- for the existing ` HasType ` rules.
219+ ` hyperpolymath/echo-types ` (commit ` f7a965f ` , 2026-06-14) added an experimental
220+ ℕ∪{∞} min-plus grade semiring (` experimental/echo-additive/Grade.agda ` ) and a
221+ variance gate (` VarianceGate.agda ` ). Key findings and their implications for Tangle:
222+
223+ - The ** combining direction** (` D_r(D_s A) → D_{r+s} A ` ) has ** monadic** variance.
224+ Tangle's ` echoAdd ` /` echoEq ` use exactly this direction: two residues are merged
225+ into a ` pair ` (the lax monoidal μ map). The current implementation is correct for
226+ this reading.
227+
228+ - The ** splitting direction** (` D_{r+s} A → D_r(D_s A) ` ) has ** comonadic** variance
229+ and requires a full graded adjunction F_r ⊣ U_r. If Tangle ever needs to split an
230+ ` Echo(ρ×σ) ` value back into independent ` Echo(ρ) ` and ` Echo(σ) ` , that is a
231+ non-trivial structural addition — it cannot be derived from the combining map alone.
232+
233+ - The ** grade semiring** (` fin n ` = information count, ` inf ` = total collapse) is a
234+ candidate carrier for a future grade-indexed type former ` Echo[n] ρ τ ` in Tangle.
235+ ` echoAdd ` would then have type ` Num → Num → Echo[2] (Num×Num) Num ` (2 units of
236+ information retained). This is prospective; the experimental subtree is firewalled
237+ until the comparative protocol (monadic vs comonadic) concludes.
238+
239+ - ** No Tangle design change is required now.** The current ` Ty.echo ` /` Ty.prod `
240+ fragment is faithful to the monadic/combining direction and the experimental work
241+ is explicitly gated (` experimental/echo-additive/ ` is not imported by any shipped
242+ module in echo-types or Tangle).
243+
244+ ## 3. Remaining obligations (the narrative arc)
245+
246+ What's not yet proven, why it matters, and what assumption each rests on.
247+
248+ ### TG-1 — Type safety extended to ` let ` -binding
217249
218- ** How to discharge.** Add the substitution lemma, extend ` Step ` with
219- a ` let ` -reduction rule, extend each cases-on-` hs ` block in
220- preservation. Standard POPLmark machinery; ~ 150 LoC.
250+ ** Status: LANDED** (` proofs/Tangle.lean ` §METATHEORY, lines 492–668).
251+
252+ ** Claim.** Type safety (Progress, Preservation, Determinism, TypeSafety) extends
253+ to the full core language including ` var ` and ` let ` .
254+
255+ ** What was proven.**
256+ - ` weakening ` (line 521) — inserting a fresh hypothesis ` σ ` at de Bruijn position
257+ ` Γ₁.length ` preserves typing, with the term shifted by ` shift 1 Γ₁.length ` .
258+ - ` subst_preserves ` (line 589) — typing is closed under replacing the variable at
259+ ` Γ₁.length ` by a well-typed term ` s ` . The substitutee is typed in the combined
260+ context ` Γ₁ ++ Γ₂ ` (the genuine inductive invariant; the ` letRed ` consumer
261+ instantiates ` Γ₁ := [] ` ).
262+ - All four main theorems (Progress, Preservation, Determinism, TypeSafety) were
263+ extended with ` var ` and ` letStep ` /` letRed ` cases. ` Step ` gained ` letStep ` and
264+ ` letRed ` ; ` HasType ` gained ` tVar ` and ` tLet ` .
265+
266+ ** Implementation notes.**
267+ - Variable lookup uses ` List.getElem? ` (not the deprecated ` List.get? ` ); the
268+ append splits go through ` List.getElem?_append_left ` / ` _append_right ` .
269+ - Each derivation is taken apart with ` cases h; rename_i ` rather than
270+ ` cases h with | tCtor ` , because under ` induction e ` the binder arguments
271+ unify with the context and positional arm naming doesn't align.
272+ - The ` subst_preserves ` combined-context invariant closes the ` var = Γ₁.length `
273+ case by ` exact hs ` with no separate shift-composition lemma needed.
274+
275+ ** Assumptions discharged.**
276+ - [[ A-TG-1.1]] ✓ — ` subst ` is defined by structural recursion on ` Expr ` , covering all 22 constructors.
277+ - [[ A-TG-1.2]] ✓ — ` weakening ` and ` subst_preserves ` both proven.
221278
222279### TG-2 — Decidability of type checking
223280
281+ ** Status: LANDED** (` proofs/Tangle.lean ` §TG-2, lines 1399–1604).
282+
224283** Claim.** There is a total function ` infer : Expr → Option Ty ` such
225284that ` infer e = some τ ↔ HasType [] e τ ` .
226285
227- ** Why valuable.** ` Tangle.lean ` establishes the * relation* ` HasType `
228- but not the * algorithm* ` typecheck.ml ` . Without TG-2 we have a proven
229- type system but no proof that the OCaml type checker actually decides
230- it.
231-
232- ** Assumptions.**
233- - [[ A-TG-2.1]] Type-checking proceeds by syntactic recursion on ` Expr `
234- (no impredicative steps).
235- - [[ A-TG-2.2]] Equality on ` Ty ` is decidable (it is — ` deriving DecidableEq ` ).
236-
237- ** How to discharge.** Define ` infer ` in Lean as a structural recursion
238- on ` Expr ` . Prove the ` ↔ ` by case analysis matching the structure of
239- ` HasType ` 's rules.
286+ ** What was proven.**
287+ - ` infer ` (line 1410) — total structural recursion on ` Expr ` ; covers all 26 ` HasType `
288+ rules including the echo/product fragment and let-binding.
289+ - ` infer_complete ` (line 1487) — ` HasType Γ e τ → infer Γ e = some τ ` .
290+ - ` infer_sound ` (line 1493) — ` infer Γ e = some τ → HasType Γ e τ ` .
291+ - ` infer_iff_hasType ` (line 1588) — the biconditional packaging both directions.
292+ - ` type_unique ` (line 1593) — ` HasType Γ e τ₁ → HasType Γ e τ₂ → τ₁ = τ₂ ` (follows
293+ from ` infer_complete ` + ` infer_sound ` ).
294+ - ` decidableHasType ` (line 1601) — ` Decidable (HasType [] e τ) ` instance via ` infer ` .
295+
296+ ** Assumptions discharged.**
297+ - [[ A-TG-2.1]] ✓ — ` infer ` is defined by structural recursion; Lean's termination
298+ checker accepts it without any additional annotation.
299+ - [[ A-TG-2.2]] ✓ — ` Ty ` carries ` deriving DecidableEq ` ; ` Ty ` comparisons in ` infer `
300+ use it directly.
240301
241302### TG-3 — OCaml impl refines the Lean spec
242303
0 commit comments