Skip to content

Commit e5dff6d

Browse files
committed
docs: mark TG-1 and TG-2 LANDED; add echo-types grade semiring design note
Both were already fully proved in proofs/Tangle.lean but not reflected in the documentation. Retrospective correction only — no Lean changes. TG-1 (weakening + subst_preserves + all four theorems extended to var/let): - PROOF-NEEDS.md: NOT STARTED → LANDED with theorem locations - PROOF-NARRATIVE.md §TG-1: parks-note retired, full statement of what was proven including the combined-context invariant for subst_preserves - "let-free fragment" caveat retired throughout; now "full core fragment" - T-Weakening and T-SubstPreserves added to supporting lemma table TG-2 (infer, infer_sound/complete, infer_iff_hasType, type_unique, decidableHasType): - PROOF-NEEDS.md: NOT STARTED → LANDED with theorem locations - PROOF-NARRATIVE.md §TG-2: updated with full proof inventory New §2.7 summarises TG-1+TG-2 structural highlights. New §2.8 notes the echo-types experimental grade semiring (hyperpolymath/echo-types f7a965f): echoAdd/echoEq use the monadic/combining direction; the comonadic/splitting direction needs a full graded adjunction and is under investigation (firewalled). No Tangle design change required. STATE.a2ml: TG-1 milestone → DONE; critical-next-actions updated.
1 parent 60ac2d4 commit e5dff6d

4 files changed

Lines changed: 143 additions & 60 deletions

File tree

.machine_readable/6a2/STATE.a2ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ project = "tangle"
77
version = "0.2.0-dev"
88
last-updated = "2026-06-14"
99
status = "active"
10-
session = "echo OCaml pipeline complete (PR #45+#46) — 2026-06-14"
10+
session = "TG-1+TG-2 documented as LANDED; echo-types grade semiring design note added — 2026-06-14"
1111

1212
[project-context]
1313
name = "Tangle"
@@ -26,10 +26,10 @@ milestones = [
2626
"DONE: Rust tangle-wasm backend + tangle-lsp",
2727
"DONE (TG-0): proofs/Tangle.lean compiles clean; CI build oracle wired (lean-proofs.yml)",
2828
"DONE: Type safety (Progress/Preservation/Determinism/TypeSafety) for the let-free core",
29+
"DONE (TG-1): let-binding type safety — weakening + subst_preserves + all four theorems extended to var/let",
2930
"DONE (TG-10): echo types integrated into the type system (Ty.echo, echoClose/lower/residue); all four theorems extended; residue-recovery + non-injectivity capstones",
3031
"DONE (TG-2): decidability — infer ≡ HasType, type uniqueness, Decidable instance",
3132
"DONE: reproducible Lean toolchain bootstrap (proofs/bootstrap-lean.sh) + SessionStart hook; CI consolidated onto it",
32-
"NEXT (TG-1): extend type safety to let-binding (full de Bruijn substitution)",
3333
"DONE: generalise echo to add/eq — product type (Ty.prod), echoAdd/echoEq in Lean+OCaml (PR #45)",
3434
"NEXT: thread echo residue into TangleIR (coordinate with quandledb)",
3535
"DONE: full OCaml echo pipeline (ast/typecheck/eval/parser/pretty) — PR #45; build fixed PR #46",
@@ -42,12 +42,12 @@ issues = []
4242

4343
[critical-next-actions]
4444
actions = [
45-
"TG-1: let-binding type safety via de Bruijn substitution (Lean 4; ~150 LoC per PROOF-NARRATIVE §TG-1)",
4645
"TG-3: formal refinement proof — OCaml typecheck.ml vs Lean HasType",
4746
"TangleIR: thread echo residue into TangleIR schema; coordinate with quandledb session",
47+
"echo-types grade semiring: monitor experimental/echo-additive comparative protocol; no Tangle action until protocol terminates",
4848
]
4949

5050
[maintenance-status]
5151
last-run-utc = "2026-06-14T03:00:00Z"
5252
last-result = "pass" # unknown | pass | warn | fail
53-
notes = "dune build + dune test (548/548) GREEN after PR #46; lean-proofs CI GREEN; Tangle.lean 26 HasType rules / 57 Step rules, 0 errors, no sorry/axiom/admit"
53+
notes = "dune build + dune test (548/548) GREEN; lean Tangle.lean 0 errors; TG-1+TG-2 LANDED (documented); echo-types f7a965f grade semiring experimental (firewalled)"

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
1313

1414
## [Unreleased]
1515

16+
### Proof documentation catch-up (TG-1, TG-2, echo-types design note)
17+
18+
Both TG-1 and TG-2 were already fully proved in `proofs/Tangle.lean` but not
19+
reflected in PROOF-NEEDS.md / PROOF-NARRATIVE.md. This entry documents the
20+
retrospective correction.
21+
22+
- **TG-1 LANDED**: `weakening` + `subst_preserves` + all four theorems (Progress,
23+
Preservation, Determinism, TypeSafety) extended to `var`/`let`. The "let-free
24+
fragment" caveat in PROOF-NARRATIVE.md is retired.
25+
- **TG-2 LANDED**: `infer` (structural recursion over all 26 HasType rules),
26+
`infer_sound`, `infer_complete`, `infer_iff_hasType`, `type_unique`,
27+
`decidableHasType` — all in `proofs/Tangle.lean` §TG-2.
28+
- **echo-types grade semiring design note** (§2.8 of PROOF-NARRATIVE.md): the
29+
experimental ℕ∪{∞} min-plus grade semiring in `hyperpolymath/echo-types`
30+
(`f7a965f`) uses the combining/monadic direction — the same direction as
31+
Tangle's `echoAdd`/`echoEq`. The splitting/comonadic direction requires a full
32+
graded adjunction and is under experimental investigation (firewalled). No
33+
Tangle design change required now.
34+
1635
### Echo types OCaml pipeline (PR #45 + #46)
1736

1837
### Added

PROOF-NARRATIVE.md

Lines changed: 102 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -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`;
196199
the 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
225284
that `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

PROOF-NEEDS.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ Owner: Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
1212

1313
**Tier:** T1 — Critical.
1414
Tangle owns the type system. KRL and QuandleDB rest on Tangle's
15-
metatheory. The let-free core has been mechanised; the gap to full
16-
language and to implementation-refinement is the remaining work.
15+
metatheory. The core (including let-binding) has been mechanised; the remaining gap is implementation-refinement and WASM/dialect proofs.
1716

1817
## Current state
1918

2019
- **LOC**: ~18,000 (OCaml + Rust + Tangle DSL + Lean proofs)
2120
- **Languages**: OCaml (compiler), Rust (tangle-wasm), Lean 4 (proofs),
2221
Tangle DSL (lib/stdlib + examples)
23-
- **Existing mechanised proofs**: `proofs/Tangle.lean` (560 LoC, 16
22+
- **Existing mechanised proofs**: `proofs/Tangle.lean` (~1604 LoC, 22+
2423
results, all `Qed`)
2524
- **Dangerous patterns**: None detected
2625

@@ -32,26 +31,30 @@ and `proofs/Tangle.lean`:
3231
| ID | Result | LoC |
3332
|----|--------|-----|
3433
| T-Progress | Every well-typed closed term is a value or steps | ~80 |
35-
| T-Preservation | Stepping preserves types | ~85 |
36-
| T-Determinism | Step relation is deterministic | ~130 |
34+
| T-Preservation | Stepping preserves types | ~180 |
35+
| T-Determinism | Step relation is deterministic | ~250 |
3736
| T-TypeSafety | Corollary: well-typed terms never get stuck | ~3 |
38-
| + 12 lemmas | width-append, width-shift, canonical-num/str/word, value-no-step, … | ~150 |
39-
40-
**Coverage:** the **let-free fragment** of core Tangle, comprising
41-
`Num`, `Str`, `Bool`, `Identity`, `BraidLit`, `Compose`, `Tensor`,
42-
`Pipeline`, `Close`, `Add`, `Eq`, plus the **echo-types fragment**
43-
(`EchoClose`, `Lower`, `Residue`, `EchoAdd`, `EchoEq`) and the **product type**
44-
(`Pair`, `Fst`, `Snd` with type former `ρ × σ`). 26 typing rules, 57 step rules.
45-
All four theorems cover the echo fragment (TG-10).
37+
| T-Weakening | Context insertion preserves typing (TG-1) | ~70 |
38+
| T-SubstPreserves | Substitution preserves typing (TG-1) | ~100 |
39+
| `infer` + `infer_sound`/`infer_complete`/`infer_iff_hasType` | Algorithmic type inference ≡ HasType (TG-2) | ~120 |
40+
| `type_unique` + `decidableHasType` | Type uniqueness + Decidable instance (TG-2) | ~15 |
41+
| + canonical lemmas | canonical-num/str/word/echo/prod, value-no-step, width-append/shift, echo capstones, echoAdd/echoEq capstones | ~250 |
42+
43+
**Coverage:** the **full core fragment** of Tangle — `Num`, `Str`, `Bool`, `Identity`,
44+
`BraidLit`, `Compose`, `Tensor`, `Pipeline`, `Close`, `Add`, `Eq`, `Var`, `Let`,
45+
plus the **echo-types fragment** (`EchoClose`, `Lower`, `Residue`, `EchoAdd`,
46+
`EchoEq`) and the **product type** (`Pair`, `Fst`, `Snd`). 26 typing rules,
47+
57 step rules. All four theorems cover the full fragment including let-binding (TG-1)
48+
and the echo/product fragment (TG-10). Type checking is decidable (TG-2).
4649

4750
## What remains
4851

4952
Cross-referenced to [PROOF-NARRATIVE.md §3](PROOF-NARRATIVE.md#3-remaining-obligations-the-narrative-arc).
5053

5154
| # | Statement | Category | Prover | Priority | Effort | Status |
5255
|---|-----------|----------|--------|----------|--------|--------|
53-
| TG-1 | Extend Progress/Preservation/Determinism/TypeSafety to `let`-binding | TP | Lean 4 | P1 | 3d | NOT STARTED (acknowledged in Tangle.lean header) |
54-
| TG-2 | Type checking is decidable: define `infer : Expr → Option Ty` proven equivalent to `HasType` | ALG | Lean 4 | P1 | 1d | NOT STARTED |
56+
| TG-1 | Extend Progress/Preservation/Determinism/TypeSafety to `let`-binding | TP | Lean 4 | P1 | | **LANDED** (`proofs/Tangle.lean` §METATHEORY — `weakening`, `subst_preserves`; all four theorems cover `var`/`let`) |
57+
| TG-2 | Type checking is decidable: define `infer : Expr → Option Ty` proven equivalent to `HasType` | ALG | Lean 4 | P1 | | **LANDED** (`proofs/Tangle.lean` §TG-2 — `infer`, `infer_sound`, `infer_complete`, `infer_iff_hasType`, `type_unique`, `decidableHasType`) |
5558
| TG-3 | OCaml `typecheck.ml` refines the Lean `HasType` spec | TP | Lean 4 + translation validation | P1 | 5d | NOT STARTED |
5659
| TG-4 | Pretty-print/parse round-trip on closed values | INV | OCaml property test (cheap) | P2 | 4h | **LANDED** (PR #46 — OCaml property test in `compiler/test/test_roundtrip.ml`, 36 entries including 16 echo/product forms) |
5760
| TG-5 | `compositional.ml` (418 LoC) rewriter preserves types | TP | Lean 4 + OCaml test file | P2 | 3d | NOT STARTED (B6: no test file yet) |

0 commit comments

Comments
 (0)