diff --git a/ABI-FFI-README.md b/ABI-FFI-README.adoc similarity index 75% rename from ABI-FFI-README.md rename to ABI-FFI-README.adoc index f28fda7..78f86b2 100644 --- a/ABI-FFI-README.md +++ b/ABI-FFI-README.adoc @@ -1,21 +1,20 @@ - -# TANGLE ABI/FFI Documentation +== TANGLE ABI/FFI Documentation -## Overview +=== Overview -This library follows the **Hyperpolymath RSR Standard** for ABI and FFI design: +This library follows the *Hyperpolymath RSR Standard* for ABI and FFI +design: -- **ABI (Application Binary Interface)** defined in **Idris2** with formal proofs -- **FFI (Foreign Function Interface)** implemented in **Zig** for C compatibility -- **Generated C headers** bridge Idris2 ABI to Zig FFI -- **Any language** can call through standard C ABI +* *ABI (Application Binary Interface)* defined in *Idris2* with formal +proofs +* *FFI (Foreign Function Interface)* implemented in *Zig* for C +compatibility +* *Generated C headers* bridge Idris2 ABI to Zig FFI +* *Any language* can call through standard C ABI -## Architecture +=== Architecture -``` +.... ┌─────────────────────────────────────────────┐ │ ABI Definitions (Idris2) │ │ src/abi/ │ @@ -47,11 +46,11 @@ This library follows the **Hyperpolymath RSR Standard** for ABI and FFI design: │ Any Language via C ABI │ │ - Rust, ReScript, Julia, Python, etc. │ └─────────────────────────────────────────────┘ -``` +.... -## Directory Structure +=== Directory Structure -``` +.... tangle/ ├── src/ │ ├── abi/ # ABI definitions (Idris2) @@ -79,15 +78,17 @@ tangle/ ├── rust/ ├── rescript/ └── julia/ -``` +.... -## Why Idris2 for ABI? +=== Why Idris2 for ABI? -### 1. **Formal Verification** +==== 1. *Formal Verification* -Idris2's dependent types allow proving properties about the ABI at compile-time: +Idris2’s dependent types allow proving properties about the ABI at +compile-time: -```idris +[source,idris] +---- -- Prove struct size is correct public export exampleStructSize : HasSize ExampleStruct 16 @@ -99,13 +100,14 @@ fieldAligned : Divides 8 (offsetOf ExampleStruct.field) -- Prove ABI is platform-compatible public export abiCompatible : Compatible (ABI 1) (ABI 2) -``` +---- -### 2. **Type Safety** +==== 2. *Type Safety* Encode invariants that C/Zig cannot express: -```idris +[source,idris] +---- -- Non-null pointer guaranteed at type level data Handle : Type where MkHandle : (ptr : Bits64) -> {auto 0 nonNull : So (ptr /= 0)} -> Handle @@ -113,13 +115,14 @@ data Handle : Type where -- Array with length proof data Buffer : (n : Nat) -> Type where MkBuffer : Vect n Byte -> Buffer n -``` +---- -### 3. **Platform Abstraction** +==== 3. *Platform Abstraction* Platform-specific types with compile-time selection: -```idris +[source,idris] +---- CInt : Platform -> Type CInt Linux = Bits32 CInt Windows = Bits32 @@ -127,13 +130,14 @@ CInt Windows = Bits32 CSize : Platform -> Type CSize Linux = Bits64 CSize Windows = Bits64 -``` +---- -### 4. **Safe Evolution** +==== 4. *Safe Evolution* Prove that new ABI versions are backward-compatible: -```idris +[source,idris] +---- -- Compiler enforces compatibility abiUpgrade : ABI 1 -> ABI 2 abiUpgrade old = MkABI2 { @@ -142,71 +146,78 @@ abiUpgrade old = MkABI2 { -- Can add new fields new_features = defaults } -``` +---- -## Why Zig for FFI? +=== Why Zig for FFI? -### 1. **C ABI Compatibility** +==== 1. *C ABI Compatibility* Zig exports C-compatible functions naturally: -```zig +[source,zig] +---- export fn library_function(param: i32) i32 { return param * 2; } -``` +---- -### 2. **Memory Safety** +==== 2. *Memory Safety* Compile-time safety without runtime overhead: -```zig +[source,zig] +---- // Null check enforced at compile time const handle = init() orelse return error.InitFailed; defer free(handle); -``` +---- -### 3. **Cross-Compilation** +==== 3. *Cross-Compilation* Built-in cross-compilation to any platform: -```bash +[source,bash] +---- zig build -Dtarget=x86_64-linux zig build -Dtarget=aarch64-macos zig build -Dtarget=x86_64-windows -``` +---- -### 4. **Zero Dependencies** +==== 4. *Zero Dependencies* No runtime, no libc required (unless explicitly needed): -```zig +[source,zig] +---- // Minimal binary size pub const lib = @import("std"); // Only includes what you use -``` +---- -## Building +=== Building -### Build FFI Library +==== Build FFI Library -```bash +[source,bash] +---- cd ffi/zig zig build # Build debug zig build -Doptimize=ReleaseFast # Build optimized zig build test # Run tests -``` +---- -### Generate C Header from Idris2 ABI +==== Generate C Header from Idris2 ABI -```bash +[source,bash] +---- cd src/abi idris2 --cg c-header Types.idr -o ../../generated/abi/tangle.h -``` +---- -### Cross-Compile +==== Cross-Compile -```bash +[source,bash] +---- cd ffi/zig # Linux x86_64 @@ -217,13 +228,14 @@ zig build -Dtarget=aarch64-macos # Windows x86_64 zig build -Dtarget=x86_64-windows -``` +---- -## Usage +=== Usage -### From C +==== From C -```c +[source,c] +---- #include "tangle.h" int main() { @@ -239,16 +251,19 @@ int main() { tangle_free(handle); return 0; } -``` +---- Compile with: -```bash + +[source,bash] +---- gcc -o example example.c -ltangle -L./zig-out/lib -``` +---- -### From Idris2 +==== From Idris2 -```idris +[source,idris] +---- import TANGLE.ABI.Foreign main : IO () @@ -261,11 +276,12 @@ main = do free handle putStrLn "Success" -``` +---- -### From Rust +==== From Rust -```rust +[source,rust] +---- #[link(name = "tangle")] extern "C" { fn tangle_init() -> *mut std::ffi::c_void; @@ -284,11 +300,12 @@ fn main() { tangle_free(handle); } } -``` +---- -### From Julia +==== From Julia -```julia +[source,julia] +---- const libtangle = "libtangle" function init() @@ -314,27 +331,30 @@ try finally cleanup(handle) end -``` +---- -## Testing +=== Testing -### Unit Tests (Zig) +==== Unit Tests (Zig) -```bash +[source,bash] +---- cd ffi/zig zig build test -``` +---- -### Integration Tests +==== Integration Tests -```bash +[source,bash] +---- cd ffi/zig zig build test-integration -``` +---- -### ABI Verification (Idris2) +==== ABI Verification (Idris2) -```idris +[source,idris] +---- -- Compile-time verification %runElab verifyABI @@ -344,44 +364,44 @@ main = do verifyLayoutsCorrect verifyAlignmentsCorrect putStrLn "ABI verification passed" -``` +---- -## Contributing +=== Contributing When modifying the ABI/FFI: -1. **Update ABI first** (`src/abi/*.idr`) - - Modify type definitions - - Update proofs - - Ensure backward compatibility - -2. **Generate C header** - ```bash - idris2 --cg c-header src/abi/Types.idr -o generated/abi/tangle.h - ``` - -3. **Update FFI implementation** (`ffi/zig/src/main.zig`) - - Implement new functions - - Match ABI types exactly - -4. **Add tests** - - Unit tests in Zig - - Integration tests - - ABI verification tests - -5. **Update documentation** - - Function signatures - - Usage examples - - Migration guide (if breaking changes) - -## License +[arabic] +. *Update ABI first* (`+src/abi/*.idr+`) +* Modify type definitions +* Update proofs +* Ensure backward compatibility +. *Generate C header* ++ +[source,bash] +---- +idris2 --cg c-header src/abi/Types.idr -o generated/abi/tangle.h +---- +. *Update FFI implementation* (`+ffi/zig/src/main.zig+`) +* Implement new functions +* Match ABI types exactly +. *Add tests* +* Unit tests in Zig +* Integration tests +* ABI verification tests +. *Update documentation* +* Function signatures +* Usage examples +* Migration guide (if breaking changes) + +=== License MPL-2.0 -## See Also +=== See Also -- [Idris2 Documentation](https://idris2.readthedocs.io) -- [Zig Documentation](https://ziglang.org/documentation/master/) -- [Rhodium Standard Repositories](https://github.com/hyperpolymath/rhodium-standard-repositories) -- [FFI Migration Guide](../ffi-migration-guide.md) -- [ABI Migration Guide](../abi-migration-guide.md) +* https://idris2.readthedocs.io[Idris2 Documentation] +* https://ziglang.org/documentation/master/[Zig Documentation] +* https://github.com/hyperpolymath/rhodium-standard-repositories[Rhodium +Standard Repositories] +* link:../ffi-migration-guide.md[FFI Migration Guide] +* link:../abi-migration-guide.md[ABI Migration Guide] diff --git a/ASSUMPTIONS.adoc b/ASSUMPTIONS.adoc new file mode 100644 index 0000000..007b239 --- /dev/null +++ b/ASSUMPTIONS.adoc @@ -0,0 +1,173 @@ +== Assumptions Registry — Tangle + +Every load-bearing *unproven* assumption used in this repo, with an ID, +classification, and the obligation it supports. + +Classifications: - *MATH* — true by an external mathematical theorem +(cite it) - *DESIGN* — true by construction in our code (must remain +true; flag if you change the named code) - *EMPIRICAL* — believed from +testing; not formally verified - *CRYPTO* — standard +cryptographic-primitive assumption + +Cross-references use `+[[A-TG-N.M]]+` syntax, resolved here. + +''''' + +[width="100%",cols="11%,14%,22%,20%,33%",options="header",] +|=== +|ID |Class |Statement |Cited by |Where it lives +|A-TG-1.1 |DESIGN |Capture-avoiding substitution is well-defined on the +de Bruijn representation `+HasType+` uses |TG-1 |`+Tangle.lean+` `+Ctx+` +definition + de Bruijn discipline + +|A-TG-1.2 |MATH |Standard weakening + substitution lemmas hold for the +`+HasType+` rules (POPLmark / TAPL §8) |TG-1 |TAPL Ch. 9; Pierce 2002 + +|A-TG-2.1 |DESIGN |Type-checking proceeds by syntactic recursion on +`+Expr+` (no impredicative steps; matches `+typecheck.ml+`’s shape) +|TG-2 |`+compiler/lib/typecheck.ml+` + +|A-TG-2.2 |DESIGN |Equality on `+Ty+` is decidable (Lean: +`+deriving DecidableEq+`; OCaml: structural `+=+`) |TG-2 +|`+Tangle.lean::Ty+`; `+compiler/lib/ast.ml+` + +|A-TG-3.1 |DESIGN |The OCaml AST in `+compiler/lib/ast.ml+` is in +bijection with the Lean AST in `+Tangle.lean::Expr+` |TG-3 |Both files, +by construction + +|A-TG-3.2 |DESIGN |OCaml `+String.equal+`, `+Int.equal+` coincide with +Lean’s `+==+` on the values used at runtime |TG-3 |Standard library +agreement; verify at the FFI boundary + +|A-TG-4.1 |DESIGN |`+pretty.ml+`’s bracketing is unambiguous w.r.t. +`+parser.mly+`’s precedence |TG-4 |`+compiler/lib/pretty.ml+`, +`+compiler/lib/parser.mly+` + +|A-TG-4.2 |DESIGN |Lexer never strips information needed by the parser +(e.g. whitespace within braid literals) |TG-4 +|`+compiler/lib/lexer.mll+` + +|A-TG-5.1 |DESIGN |Every rewrite in `+compositional.ml+` is +`+Expr → Expr+` (no mutation) |TG-5 |`+compiler/lib/compositional.ml+` + +|A-TG-5.2 |DESIGN |No rewrite introduces a new free variable |TG-5 |Each +rewrite, individually + +|A-TG-6.1 |MATH |WASM small-step semantics is well-defined; assume the +official Wasm spec / WasmCert-Isabelle definition |TG-6 |wasm-spec, +WasmCert-Isabelle + +|A-TG-6.2 |DESIGN |Source semantics has no floating-point +non-determinism (Tangle has only `+Int+` currently) |TG-6 +|`+Tangle.lean::Ty+` lacks `+.float+` + +|A-TG-7.1 |MATH |Word problem in the braid group `+B_n+` is solvable in +polynomial time (Birman–Ko–Lee / Garside normal form) |TG-7 +|Birman–Ko–Lee 1998; _A New Approach to the Word and Conjugacy Problems +in the Braid Groups_ + +|A-TG-7.2 |IMPL |`+braidEquiv+` (`+proofs/Tangle.lean+`) and +`+braid_equiv.ml+` implement Dehornoy handle reduction *correctly*, and +agree with each other. Since the 2026-07-29 ruling (#50) routed `+==+` +through them, this is *load-bearing for the semantics of `+==+`*: the +Step relation’s metatheory is proven only _relative to_ `+braidEquiv+`, +never that it decides braid-group equality. Evidenced by testing (2220 + +8 assertions), not proof. Retired by the mechanised Garside/Dehornoy +proof (#51, research-grade). The Lean port is additionally +*fuel-bounded*, so termination is assumed rather than proven. |TG-7 +|`+compiler/lib/braid_equiv.ml+`; `+proofs/Tangle.lean+` §BRAID-GROUP +EQUIVALENCE; `+compiler/test/tg7+` + +|A-TG-92.1 |MATH |Comparing braid words of different widths is decided +in B_max(n,m) via the standard embedding Bn -> Bn+1 (adjoin a strand no +generator touches). Used to justify widening `+T-Eq-Word+` (#92) and the +match-arm width join. The embedding is standard mathematics but is +*asserted in prose, not mechanised* — no Lean lemma states it. What IS +machine-checked is that the metatheory +(Progress/Preservation/Determinism/TypeSafety, infer_sound/complete) +holds under the widened rule, and that OCaml `+infer_expr+` still agrees +with Lean `+infer+` on the corpus (TG-3, 496 obligations). |TG-7 / #92 +|`+proofs/Tangle.lean+` (`+tEqWord+`, `+infer+`); +`+compiler/lib/typecheck.ml+` + +|A-TG-11.1 |DESIGN |The simply-typed shadow is FAITHFUL to +`+epistemic-types+`: `+Epi[k,rho,tau]+` models `+Epi K k A+` +(Warrant.agda) with standpoints as Nat indices rather than an arbitrary +index set K, and it omits the upstream `+LawfulModality+` functor laws, +`+FactiveModality.reflect+` and `+ReturnModality.return+` (all +deliberately opt-in upstream). What IS mechanised here is non-factivity: +no elimination yields the claim. Erasure and quantity are NOT modelled - +the claim is carried in the value rather than erased, because erasing it +would break uniqueness of typing in a system without quantities. A QTT +treatment (quantity 0 for the claim) would be the faithful version. +|TG-11 |`+proofs/Tangle.lean+` section EPISTEMIC; +`+epistemic-types/src/EpistemicTypes/{Base,Warrant,EchoBridge}.agda+` + +|A-TG-8.1 |DESIGN |Each dialect’s grammar is a strict superset of core’s +EBNF (`+tangle.ebnf+`) |TG-8 |`+dialects/*/grammar.ebnf+` + +|A-TG-8.2 |DESIGN |Each dialect’s typing rules are additive (new +constructors + their typing rules only; no modification of existing +rules) |TG-8 |Per-dialect spec + +|A-TG-9.1 |DESIGN |`+tangle-lsp+` emits diagnostics in four documented +categories (`+PARSE_ERROR+`, `+MISSPELLING_HINT+`, `+STRUCTURAL_HINT+`, +`+NAME_HINT+`); only `+PARSE_ERROR+` corresponds to a grammar-level +rejection. The other three are LSP-only by design (Option B from TG-9 +audit; Option A — full refinement via FFI to `+typecheck.ml+` — remains +queued at #28). Each emission site is tagged in the +`+Diagnostic.source+` field as `+tangle-lsp[CATEGORY]+`. |TG-9 +|`+compiler/tangle-lsp/src/backend.rs+`; +`+compiler/tangle-lsp/docs/lsp-diagnostic-categories.md+` +|=== + +''''' + +=== How to use this file + +* *Reading code.* When you see a function whose correctness depends on +something not enforced by the local types — _that’s an assumption_. Find +or add the entry here and reference it by ID. +* *Writing a proof.* Every proof obligation in PROOF-NARRATIVE.md names +its assumptions by ID. Before discharging the proof, audit the +assumptions block. +* *Modifying load-bearing code.* Each DESIGN assumption names a +file/component. If you edit that file, re-validate the assumption (or +update the obligation if the design changed intentionally). + +=== Promoting / demoting assumptions + +[cols=",,",options="header",] +|=== +|From |To |Trigger +|EMPIRICAL → MATH |discharge with a citation | +|EMPIRICAL → DESIGN |refactor to make it a structural invariant | +|MATH → (delete) |obligation has been re-cast not to need it | +|DESIGN → MATH (rare) |the design happens to encode a known theorem | +|=== + +When you change a row, leave a one-line note in the changelog with the +date and reason. + +''''' + +=== Changelog + +[width="100%",cols="32%,42%,26%",options="header",] +|=== +|Date |Change |By +|2026-06-01 |Initial registry, scoped to Tangle metatheory + +implementation refinement obligations |Audit + +|2026-06-01 |A-TG-9.1 reformulated under TG-9 Option B — accept LSP-only +categories instead of pretending refinement (full Option A queued at +#28). See `+compiler/tangle-lsp/docs/lsp-diagnostic-categories.md+`. +|TG-9 Option B PR + +|2026-06-01 |TG-0 closed: `+proofs/Tangle.lean+` previously had 121 +errors on Lean 4.9–4.16 (commit 8ce7be7 was committed without ever +compiling). Repaired: 62/51 diff, 0 errors on Lean 4.10–4.16. CI oracle +at `+.github/workflows/lean-proofs.yml+` pinned to v4.14.0 via +`+proofs/lean-toolchain+`. Sorry/axiom/admit slippage check added. +Closes hyperpolymath/tangle#32. |TG-0 PR +|=== diff --git a/ASSUMPTIONS.md b/ASSUMPTIONS.md deleted file mode 100644 index e9bbb43..0000000 --- a/ASSUMPTIONS.md +++ /dev/null @@ -1,76 +0,0 @@ - -# Assumptions Registry — Tangle - -Every load-bearing **unproven** assumption used in this repo, with an -ID, classification, and the obligation it supports. - -Classifications: -- **MATH** — true by an external mathematical theorem (cite it) -- **DESIGN** — true by construction in our code (must remain true; flag if you change the named code) -- **EMPIRICAL** — believed from testing; not formally verified -- **CRYPTO** — standard cryptographic-primitive assumption - -Cross-references use `[[A-TG-N.M]]` syntax, resolved here. - ---- - -| ID | Class | Statement | Cited by | Where it lives | -|----|-------|-----------|----------|----------------| -| A-TG-1.1 | DESIGN | Capture-avoiding substitution is well-defined on the de Bruijn representation `HasType` uses | TG-1 | `Tangle.lean` `Ctx` definition + de Bruijn discipline | -| A-TG-1.2 | MATH | Standard weakening + substitution lemmas hold for the `HasType` rules (POPLmark / TAPL §8) | TG-1 | TAPL Ch. 9; Pierce 2002 | -| A-TG-2.1 | DESIGN | Type-checking proceeds by syntactic recursion on `Expr` (no impredicative steps; matches `typecheck.ml`'s shape) | TG-2 | `compiler/lib/typecheck.ml` | -| A-TG-2.2 | DESIGN | Equality on `Ty` is decidable (Lean: `deriving DecidableEq`; OCaml: structural `=`) | TG-2 | `Tangle.lean::Ty`; `compiler/lib/ast.ml` | -| A-TG-3.1 | DESIGN | The OCaml AST in `compiler/lib/ast.ml` is in bijection with the Lean AST in `Tangle.lean::Expr` | TG-3 | Both files, by construction | -| A-TG-3.2 | DESIGN | OCaml `String.equal`, `Int.equal` coincide with Lean's `==` on the values used at runtime | TG-3 | Standard library agreement; verify at the FFI boundary | -| A-TG-4.1 | DESIGN | `pretty.ml`'s bracketing is unambiguous w.r.t. `parser.mly`'s precedence | TG-4 | `compiler/lib/pretty.ml`, `compiler/lib/parser.mly` | -| A-TG-4.2 | DESIGN | Lexer never strips information needed by the parser (e.g. whitespace within braid literals) | TG-4 | `compiler/lib/lexer.mll` | -| A-TG-5.1 | DESIGN | Every rewrite in `compositional.ml` is `Expr → Expr` (no mutation) | TG-5 | `compiler/lib/compositional.ml` | -| A-TG-5.2 | DESIGN | No rewrite introduces a new free variable | TG-5 | Each rewrite, individually | -| A-TG-6.1 | MATH | WASM small-step semantics is well-defined; assume the official Wasm spec / WasmCert-Isabelle definition | TG-6 | wasm-spec, WasmCert-Isabelle | -| A-TG-6.2 | DESIGN | Source semantics has no floating-point non-determinism (Tangle has only `Int` currently) | TG-6 | `Tangle.lean::Ty` lacks `.float` | -| A-TG-7.1 | MATH | Word problem in the braid group `B_n` is solvable in polynomial time (Birman–Ko–Lee / Garside normal form) | TG-7 | Birman–Ko–Lee 1998; _A New Approach to the Word and Conjugacy Problems in the Braid Groups_ | -| A-TG-7.2 | IMPL | `braidEquiv` (`proofs/Tangle.lean`) and `braid_equiv.ml` implement Dehornoy handle reduction **correctly**, and agree with each other. Since the 2026-07-29 ruling (#50) routed `==` through them, this is **load-bearing for the semantics of `==`**: the Step relation's metatheory is proven only *relative to* `braidEquiv`, never that it decides braid-group equality. Evidenced by testing (2220 + 8 assertions), not proof. Retired by the mechanised Garside/Dehornoy proof (#51, research-grade). The Lean port is additionally **fuel-bounded**, so termination is assumed rather than proven. | TG-7 | `compiler/lib/braid_equiv.ml`; `proofs/Tangle.lean` §BRAID-GROUP EQUIVALENCE; `compiler/test/tg7` | -| A-TG-92.1 | MATH | Comparing braid words of different widths is decided in B_max(n,m) via the standard embedding Bn -> Bn+1 (adjoin a strand no generator touches). Used to justify widening `T-Eq-Word` (#92) and the match-arm width join. The embedding is standard mathematics but is **asserted in prose, not mechanised** — no Lean lemma states it. What IS machine-checked is that the metatheory (Progress/Preservation/Determinism/TypeSafety, infer_sound/complete) holds under the widened rule, and that OCaml `infer_expr` still agrees with Lean `infer` on the corpus (TG-3, 496 obligations). | TG-7 / #92 | `proofs/Tangle.lean` (`tEqWord`, `infer`); `compiler/lib/typecheck.ml` | -| A-TG-11.1 | DESIGN | The simply-typed shadow is FAITHFUL to `epistemic-types`: `Epi[k,rho,tau]` models `Epi K k A` (Warrant.agda) with standpoints as Nat indices rather than an arbitrary index set K, and it omits the upstream `LawfulModality` functor laws, `FactiveModality.reflect` and `ReturnModality.return` (all deliberately opt-in upstream). What IS mechanised here is non-factivity: no elimination yields the claim. Erasure and quantity are NOT modelled - the claim is carried in the value rather than erased, because erasing it would break uniqueness of typing in a system without quantities. A QTT treatment (quantity 0 for the claim) would be the faithful version. | TG-11 | `proofs/Tangle.lean` section EPISTEMIC; `epistemic-types/src/EpistemicTypes/{Base,Warrant,EchoBridge}.agda` | -| A-TG-8.1 | DESIGN | Each dialect's grammar is a strict superset of core's EBNF (`tangle.ebnf`) | TG-8 | `dialects/*/grammar.ebnf` | -| A-TG-8.2 | DESIGN | Each dialect's typing rules are additive (new constructors + their typing rules only; no modification of existing rules) | TG-8 | Per-dialect spec | -| A-TG-9.1 | DESIGN | `tangle-lsp` emits diagnostics in four documented categories (`PARSE_ERROR`, `MISSPELLING_HINT`, `STRUCTURAL_HINT`, `NAME_HINT`); only `PARSE_ERROR` corresponds to a grammar-level rejection. The other three are LSP-only by design (Option B from TG-9 audit; Option A — full refinement via FFI to `typecheck.ml` — remains queued at #28). Each emission site is tagged in the `Diagnostic.source` field as `tangle-lsp[CATEGORY]`. | TG-9 | `compiler/tangle-lsp/src/backend.rs`; `compiler/tangle-lsp/docs/lsp-diagnostic-categories.md` | - ---- - -## How to use this file - -- **Reading code.** When you see a function whose correctness depends - on something not enforced by the local types — _that's an - assumption_. Find or add the entry here and reference it by ID. -- **Writing a proof.** Every proof obligation in - [PROOF-NARRATIVE.md](PROOF-NARRATIVE.md) names its assumptions by ID. - Before discharging the proof, audit the assumptions block. -- **Modifying load-bearing code.** Each DESIGN assumption names a - file/component. If you edit that file, re-validate the assumption - (or update the obligation if the design changed intentionally). - -## Promoting / demoting assumptions - -| From | To | Trigger | -|------|-----|---------| -| EMPIRICAL → MATH | discharge with a citation | -| EMPIRICAL → DESIGN | refactor to make it a structural invariant | -| MATH → (delete) | obligation has been re-cast not to need it | -| DESIGN → MATH (rare) | the design happens to encode a known theorem | - -When you change a row, leave a one-line note in the changelog with the -date and reason. - ---- - -## Changelog - -| Date | Change | By | -|------|--------|-----| -| 2026-06-01 | Initial registry, scoped to Tangle metatheory + implementation refinement obligations | Audit | -| 2026-06-01 | A-TG-9.1 reformulated under TG-9 Option B — accept LSP-only categories instead of pretending refinement (full Option A queued at #28). See `compiler/tangle-lsp/docs/lsp-diagnostic-categories.md`. | TG-9 Option B PR | -| 2026-06-01 | TG-0 closed: `proofs/Tangle.lean` previously had 121 errors on Lean 4.9–4.16 (commit 8ce7be7 was committed without ever compiling). Repaired: 62/51 diff, 0 errors on Lean 4.10–4.16. CI oracle at `.github/workflows/lean-proofs.yml` pinned to v4.14.0 via `proofs/lean-toolchain`. Sorry/axiom/admit slippage check added. Closes hyperpolymath/tangle#32. | TG-0 PR | diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc new file mode 100644 index 0000000..2f9c3ed --- /dev/null +++ b/CHANGELOG.adoc @@ -0,0 +1,319 @@ +== Changelog — Tangle + +Tangle is a Turing-complete topological programming language. This file +tracks notable changes to the compiler, stdlib, tooling, and WASM +runtime. + +The format is based on https://keepachangelog.com/en/1.1.0/[Keep a +Changelog]. + +=== [Unreleased] + +==== TG-8 (template): virtual-knot dialect as a conservative extension of core + +* *`+compiler/lib/dialect_vk.ml+`* models the virtual-knot dialect (the +virtual braid monoid VBₙ ⊃ Bₙ — braids plus involutive virtual crossings +vᵢ) as a _conservative extension_ of the core braid language: a real +crossing or a virtual crossing, with the core (real) fragment embedding +via `+embed+` and every decision on it DELEGATED to `+Braid_equiv+` +(TG-7). Conservativity therefore holds by construction — the dialect +cannot change core typing/semantics. +* *`+compiler/test/tg8/tg8_conservativity.ml+`* (2311 assertions) +verifies: faithful embedding (`+project ∘ embed = id+`); the dialect +decides core terms exactly as the core procedure; permutation/writhe +invariants agree on the real fragment; proper extension (a virtual +crossing is a genuinely-new non-real element, `+vᵢ vᵢ = ε+`); and an +honest partial-decision frontier (irreducible mixed virtual content → +`+None+`, never guessed). +* Built as a separate module — no core-AST or Lean-oracle edits (avoids +the `+Warning 8+` exhaustiveness cascade). Surface-syntax integration, +the other four dialects, and a Lean conservativity proof are the next +rungs (PROOF-NEEDS TG-8). + +==== TG-6 (differential rung): execute generated wasm and check it preserves semantics + +* *`+compiler/tangle-wasm/tests/differential.rs+`* adds `+wasmi+` (a +pure-Rust wasm interpreter) as a dev-dependency and EXECUTES the +generated wasm modules, supplying reference host primitives +(`+tangle_rt.alloc_strands+` initialises the identity strand array; +`+tangle_rt.swap_strands+` swaps two cells). It then checks the executed +strand permutation equals an independent in-Rust reference model — over +the trefoil, non-commuting pairs (`+s1 s2+` ≠ `+s2 s1+`), braid-relation +pairs (`+s1 s2 s1+` = `+s2 s1 s2+`), and a 5-strand weave. Run via +`+cargo test+` in `+compiler/tangle-wasm+`. +* This validates the wasm *codegen* against the braid permutation +semantics (catches wrong crossing indices, call order, strand counts, or +a non-instantiable module). It is not a cross-binary diff against +`+eval.ml+`, and the Markov-move helpers are not yet exercised; full +source↔wasm bisimulation remains research-grade (PROOF-NEEDS.md TG-6). +The shipped backend keeps no runtime dependency (`+wasmi+` is dev-only). + +==== TG-7 (non-semantic rung): out-of-band braid-group equivalence + +* *`+compiler/lib/braid_equiv.ml+`* decides braid-GROUP equivalence via +Dehornoy handle reduction (`+equiv+`, `+is_trivial+`, plus +`+writhe+`/`+permutation+` invariants). It is *out-of-band*: the +language’s `+==+` on braids (`+eval.ml+` and the Lean `+Step.eqBraids+` +rule) is left as list equality — no semantics change. Routing `+==+` +through it remains an owner decision (PROOF-NEEDS.md TG-7). +* Tested in `+compiler/test/tg7/tg7_braid_equiv.ml+` (2220 assertions): +the defining relations (commutation, braid relation, cancellation), 400 +randomly-constructed equivalent pairs (relation-preserving moves give +ground truth; writhe/permutation invariants guard the generator), and +invariant-distinguished negatives. Correctness is by-testing; a +mechanised Garside/Dehornoy proof is the research-grade rung. + +==== TG-5 LANDED + readiness map for TG-6/7/8 + +* *TG-5 LANDED*: `+compiler/test/tg5/tg5_invariants.ml+` (189 +assertions, in `+dune runtest+`) — a structural-invariant property test +for the compositional PD lowering (`+compiler/lib/compositional.ml+`). +compositional sits below the type layer, so "`the rewriter preserves +types`" is realised as preserving the lowering’s structural invariants + +the echo residue-recovery property: `+OpenWord+` unit-expanded; +`+ClosedDiagram+` closed / `+components=[]+` / source unit-expanded / +`+|crossings| = |source| = unit-count+`; `+EchoClosed+` residue +*verbatim* (`+echoClose(s1^3)+` keeps `+[s1^3]+` while the diagram is +the 3-crossing unit closure), `+expand(residue) = diagram word+`, and +echo-diagram pdv1-identical to plain `+close+`; plus error-path and +crossing-count pins. Asserts only invariants the lowering guarantees (no +arc-balance/planarity). +* *Readiness map (TG-6/7/8)*: a parallel assessment found each remaining +obligation is blocked on a _prerequisite_, not effort — recorded in +PROOF-NEEDS.md. *TG-8* blocked: the five dialects are prose READMEs with +no implementation. *TG-7* needs an owner decision: braid-group +equivalence changes the observable semantics of `+==+` on braids in both +the evaluator and the Lean `+Step+` relation. *TG-6* blocked: no wasm +runtime is wired in, so even differential testing has nothing to +execute. + +==== TG-3 LANDED: OCaml type checker refines the Lean spec (translation validation) + +Proof obligation TG-3 — "``+compiler/lib/typecheck.ml+` refines the +mechanised `+HasType+` spec`" — is discharged at the +translation-validation level. Full write-up, closure argument, type +translation, divergence catalogue and extra-core feature list: +`+proofs/TG3-REFINEMENT.md+`. + +* *Reduction.* TG-2 proves Lean `+infer ≡ HasType+`, so TG-3 reduces to +"`OCaml `+infer_expr+` ≡ Lean `+infer+` on the shared core fragment`". +* *Closure proof.* The core fragment (literals, let/var, compose/tensor/ +pipeline, add, eq, and the echo/product ops — excluding `+close+` and +the whole Tangle layer) is closed under `+infer_expr+`: it never +produces a `+TTangle+`, under a strengthened _entire-type-tree_ +induction hypothesis (a Tangle must not hide inside a +`+TProd+`/`+TEcho+` and leak out via +`+fst+`/`+snd+`/`+lower+`/`+residue+`). +* *Machine-checked half.* `+proofs/TG3Differential.lean+` — 496 +obligations `+infer [] = := by decide+`, +*generated from the OCaml checker* by `+compiler/test/tg3/tg3_emit.ml+` +and kernel-verified by Lean’s _proven_ `+infer+`. New +`+proofs/check-tg3-differential.sh+` (builds the Tangle `+.olean+`, +checks the obligations); wired into `+lean-proofs.yml+`. +* *OCaml half.* `+compiler/test/tg3/+` runs `+tg3_emit --check+` under +`+dune runtest+`: 1008 assertions over a 490-term corpus — closure +invariant, curated type pins, named→de Bruijn translation +(incl. `+let+`-shadowing), and the OCaml side of every divergence. +* *Divergence catalogue (complete).* *D1* `+close+` (OCaml +`+Tangle[I,I]+` vs Lean `+Word[0]+` — the sole core boundary gateway) +and its downstream vectors D1b `+pipeline(close,close)+`, D1c +`+compose(braid,close)+` (OCaml rejects), D1d `+add(close,close)+`; *D2* +`+bool == bool+` (OCaml accepts as extra-core, Lean rejects). Both sides +of each are pinned. +* *Honest boundary.* Translation validation over a broad corpus plus a +structural argument — not a single Lean theorem quantifying over all +OCaml runs (that would require reflecting `+typecheck.ml+`). Refinement +is OCaml→Lean. + +==== Proof documentation catch-up (TG-1, TG-2, echo-types design note) + +Both TG-1 and TG-2 were already fully proved in `+proofs/Tangle.lean+` +but not reflected in PROOF-NEEDS.md / PROOF-NARRATIVE.md. This entry +documents the retrospective correction. + +* *TG-1 LANDED*: `+weakening+` + `+subst_preserves+` + all four theorems +(Progress, Preservation, Determinism, TypeSafety) extended to +`+var+`/`+let+`. The "`let-free fragment`" caveat in PROOF-NARRATIVE.md +is retired. +* *TG-2 LANDED*: `+infer+` (structural recursion over all 26 HasType +rules), `+infer_sound+`, `+infer_complete+`, `+infer_iff_hasType+`, +`+type_unique+`, `+decidableHasType+` — all in `+proofs/Tangle.lean+` +§TG-2. +* *echo-types grade semiring design note* (§2.8 of PROOF-NARRATIVE.md): +the experimental ℕ∪\{∞} min-plus grade semiring in +`+hyperpolymath/echo-types+` (`+f7a965f+`) uses the combining/monadic +direction — the same direction as Tangle’s `+echoAdd+`/`+echoEq+`. The +splitting/comonadic direction requires a full graded adjunction and is +under experimental investigation (firewalled). No Tangle design change +required now. + +==== Echo-threading: EchoClosed compositional IR node + +The compositional PD compiler (`+compositional.ml+`) now threads the +echo residue through the IR. This is the OCaml-side implementation of +the cross-repo contract at `+docs/spec/ECHO-TANGLEIR-THREADING.md+`. + +* *`+EchoClose of expr+`* added to the `+expr+` type; `+echo_close+` +builder. +* *`+EchoClosed { residue; diagram }+`* added to `+compiled+` — carries +the pre-closure braid word alongside the closed planar diagram +(identical to the plain-`+Close+` output so existing consumers are +unaffected). +* *`+compile_echo_and_send_to_skein+`* — residue-carrying Skein hook +that emits `+echo_closed_payload+` with both `+residue_blob+` +(`+"s1,s2^-1,s1"+` format) and the PDv1 blob. +* *`+word_of_compiled (EchoClosed _)+`* returns the residue braid — the +pre-closure word is recoverable at the IR level. +* Parser adapter (`+of_ast_expr+`) maps `+Ast.EchoClose+` to the +compositional `+EchoClose+`, reachable via the new `+--compile-pd+` CLI +flag (see below). +* Validated against `+EchoProvenance.agda+` (echoes distinguish +tag-differing records) and `+EchoResidue.agda+` (`+no-section+` theorem +— the residue must be threaded, not recomputed after lowering). + +Downstream: Julia `+KRLAdapter.jl+` and `+quandledb+` implement the +consumer side per §3–4 of the contract doc. + +==== Audit follow-up (correctness + coverage hardening) + +A multi-agent adversarial audit of the echo/TG work surfaced fixes, +applied here: + +* *Residue is now verbatim.* `+compile (EchoClose b)+` retains the +_unexpanded_ pre-closure braid as the residue (via a new +`+source_word_of_expr+`), so `+echoClose(braid[s1^3])+` keeps residue +`+s1^3+` rather than the unit-expanded `+s1,s1,s1+`. This matches the +Lean `+echo_residue_recovers+` theorem and the eval interpreter (which +were already exponent-faithful); only the planar diagram is +unit-expanded. +* *`+Eq+` typecheck tightened to the spec.* Word equality now requires +equal width (`+Word[n] == Word[m]+` ⇒ `+n = m+`), matching the Lean +`+tEqWord+` rule; unequal-width comparisons are now rejected instead of +silently evaluating to `+false+`. `+Bool == Bool+` is retained as an +explicit extra-core convenience (used by `+examples/braids_as_data+`). +* *`+--compile-pd +` CLI flag* wires the compositional/Skein path +(previously test-only) into the shipped binary: each closed/echo-closed +`+def+` is lowered to its PDv1 blob, with the residue blob for +`+echoClose+`. +* *Test coverage for the surface echo pipeline.* Added direct typecheck +(`+test_typecheck.ml+`) and eval (`+test_eval.ml+`) tests pinning the +residue/result ordering of all 8 echo/product forms against the Lean +`+Step+` rules — previously only parse/pretty round-trip was tested. +* Adds direct typecheck/eval coverage for the 8 echo forms (suite was +557 before this batch; see the running total below). + +==== TG-9 LANDED: LSP diagnostics delegated to the compiler + +`+tangle-lsp+` previously computed diagnostics from a hand-rolled +lexical scan that diverged from the real parser/typechecker, emitting +LSP-only false positives (wrong comment syntax, delimiters counted +inside string literals, "`unclosed block`" on every multi-def file, +params flagged as undefined). None corresponded to a `+HasType+` failure +— violating TG-9. + +* *`+compiler/lib/check.ml+`* (`+check_source+`) is now the single +diagnostic source: parse-with-recovery + `+Typecheck.check_program+`. +* *`+tanglec --check +`* exposes it as +`+SEVERITY⇥LINE⇥COL⇥MESSAGE+`. +* *`+tangle-lsp+`* shells out to `+tanglec --check+` and forwards +exactly those diagnostics; the lexical scan now only extracts +definitions / references for navigation. With the compiler absent it +emits nothing (`+∅ ⊆ HasType failures+`). The subset relation holds *by +construction*. +* Built-in operations now appear in LSP completion (reusing the +previously diagnostic-only `+TANGLE_BUILTINS+` list). +* Tests: `+compiler/test/test_check.ml+` and `+tangle-lsp+` Rust unit +tests (`+parse_check_line+`, navigation authors no diagnostics, gated +end-to-end delegation against a real `+tanglec+`). + +==== Type-error diagnostics carry source lines + +* `+definition+` gains a `+def_line+` field (set from the parser’s +`+$startpos+`); `+Typecheck.diagnostic+` gains `+diag_line+`. +Definition-scoped type errors now point at the `+def+` line instead of +the file top, so the LSP highlights the right line. +* Removed a duplicate diagnostic: `+check_program+` pass 2 no longer +re-checks definitions (pass 1b already does), so one type error yields +one diagnostic. Statement-level errors (assert/compute/weave) remain +unlocated for now. +* Test-suite total: *597/597* pass. + +==== Echo types OCaml pipeline (PR #45 + #46) + +==== Added + +* Echo/product type system fully landed in the OCaml pipeline (PR #45 + +#46): +** `+ast.ml+`: 8 new `+expr+` constructors (`+echoClose+`, `+lower+`, +`+residue+`, `+pair+`, `+fst+`, `+snd+`, `+echoAdd+`, `+echoEq+`); 2 new +`+ty+` constructors (`+TProd+`, `+TEcho+`) +** `+typecheck.ml+`: 8 new `+infer_expr+` rules mirroring Lean +`+HasType+` (`+T-Echo-Close+`, `+T-Lower+`, `+T-Residue+`, `+T-Pair+`, +`+T-Fst+`, `+T-Snd+`, `+T-Echo-Add+`, `+T-Echo-Eq+`); `+pp_ty+` made +`+rec+` +** `+eval.ml+`: `+VEcho+`/`+VPair+` value forms; 8 new `+eval_expr+` +arms; `+pp_value+` made `+rec+` +** `+lexer.mll+` + `+parser.mly+` + `+token.ml+`: keyword tokens and +grammar productions for all 8 surface forms (`+echoClose(e)+`, +`+lower(e)+`, `+residue(e)+`, `+pair(a,b)+`, `+fst(e)+`, `+snd(e)+`, +`+echoAdd(a,b)+`, `+echoEq(a,b)+`) +** `+pretty.ml+`: pretty-printers for all 8 forms; round-trips through +parser +* TG-4 (pretty-print/parse round-trip) discharged: `+test_roundtrip.ml+` +extended with 8 new echo/product corpus entries (16 round-trip runs) +covering every echo/product constructor (PR #46) +* `+docs/spec/ECHO-TANGLEIR-THREADING.md+`: cross-repo contract for how +echo residue threads through TangleIR to QuandleDB (PR #45) +* Compositional PD compiler API (`+compositional.ml+` / `+.mli+`): +`+expr+`, `+planar_diagram+`, `+compiled+`, `+skein_payload+` types +* `+pdv1_blob_of_pd+`: canonical text serialisation format +(`+pdv1|x=a,b,c,d,s;...|c=arc,arc;...+`) +* `+compile_and_send_to_skein+`: direct Tangle → Skein integration entry +point +* Playground scaffold in `+playground/+` (placeholder PWA + 2 example +programs) +* README rewrite introducing KRL architecture + visual map +(docs/krl_map.html) +* CRG v2 READINESS.md (grade C) + +==== Changed + +* Tangle composition typecheck: correct permutation application +* WASM: fixed composed braid locals and helper expectations +* Zig ABI layer modernized + +==== Fixed + +* `+compiler/bin/main.ml+` debug token printer: add 8 missing echo +keyword token arms (Warning 8 exhaustiveness, PR #46) +* `+compiler/lib/typecheck.ml+` `+strand_type_of_ty+`: add +`+TProd+`/`+TEcho+` arms (Warning 8 exhaustiveness, PR #46) +* EXPLAINME.adoc section heading quotes + +=== Earlier commits (no versions tagged) + +==== UX infrastructure + +* Justfile with doctor, tour, help-me, assail recipes +* UX Manifesto deployment +* Agent instructions methodology layer + +==== Formal proofs + +* Lean 4 proofs: progress, preservation, determinism +* TOPOLOGY.md documentation added + +==== RSR compliance + +* A2ML migration of state files +* SPDX headers, license migration to MPL-2.0 +* stapeln.toml container definition +* Standard workflow deployment (codeql, hypatia, scorecard, etc.) + +==== Language development + +* Compiler (OCaml/dune): parser, typechecker, evaluator, pretty-printer, +REPL +* WASM backend (`+tangle-wasm/+`) +* LSP server (`+tangle-lsp/+`) +* Stdlib (`+lib/stdlib.tangle+`) diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index a72d8d0..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,273 +0,0 @@ - - - -# Changelog — Tangle - -Tangle is a Turing-complete topological programming language. This file -tracks notable changes to the compiler, stdlib, tooling, and WASM runtime. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - -## [Unreleased] - -### TG-8 (template): virtual-knot dialect as a conservative extension of core - -- **`compiler/lib/dialect_vk.ml`** models the virtual-knot dialect (the virtual - braid monoid VBₙ ⊃ Bₙ — braids plus involutive virtual crossings vᵢ) as a - *conservative extension* of the core braid language: a real crossing or a - virtual crossing, with the core (real) fragment embedding via `embed` and every - decision on it DELEGATED to `Braid_equiv` (TG-7). Conservativity therefore - holds by construction — the dialect cannot change core typing/semantics. -- **`compiler/test/tg8/tg8_conservativity.ml`** (2311 assertions) verifies: - faithful embedding (`project ∘ embed = id`); the dialect decides core terms - exactly as the core procedure; permutation/writhe invariants agree on the real - fragment; proper extension (a virtual crossing is a genuinely-new non-real - element, `vᵢ vᵢ = ε`); and an honest partial-decision frontier (irreducible - mixed virtual content → `None`, never guessed). -- Built as a separate module — no core-AST or Lean-oracle edits (avoids the - `Warning 8` exhaustiveness cascade). Surface-syntax integration, the other four - dialects, and a Lean conservativity proof are the next rungs (PROOF-NEEDS TG-8). - -### TG-6 (differential rung): execute generated wasm and check it preserves semantics - -- **`compiler/tangle-wasm/tests/differential.rs`** adds `wasmi` (a pure-Rust wasm - interpreter) as a dev-dependency and EXECUTES the generated wasm modules, - supplying reference host primitives (`tangle_rt.alloc_strands` initialises the - identity strand array; `tangle_rt.swap_strands` swaps two cells). It then - checks the executed strand permutation equals an independent in-Rust reference - model — over the trefoil, non-commuting pairs (`s1 s2` ≠ `s2 s1`), - braid-relation pairs (`s1 s2 s1` = `s2 s1 s2`), and a 5-strand weave. Run via - `cargo test` in `compiler/tangle-wasm`. -- This validates the wasm **codegen** against the braid permutation semantics - (catches wrong crossing indices, call order, strand counts, or a - non-instantiable module). It is not a cross-binary diff against `eval.ml`, and - the Markov-move helpers are not yet exercised; full source↔wasm bisimulation - remains research-grade (PROOF-NEEDS.md TG-6). The shipped backend keeps no - runtime dependency (`wasmi` is dev-only). - -### TG-7 (non-semantic rung): out-of-band braid-group equivalence - -- **`compiler/lib/braid_equiv.ml`** decides braid-GROUP equivalence via Dehornoy - handle reduction (`equiv`, `is_trivial`, plus `writhe`/`permutation` - invariants). It is **out-of-band**: the language's `==` on braids (`eval.ml` - and the Lean `Step.eqBraids` rule) is left as list equality — no semantics - change. Routing `==` through it remains an owner decision (PROOF-NEEDS.md TG-7). -- Tested in `compiler/test/tg7/tg7_braid_equiv.ml` (2220 assertions): the - defining relations (commutation, braid relation, cancellation), 400 - randomly-constructed equivalent pairs (relation-preserving moves give ground - truth; writhe/permutation invariants guard the generator), and - invariant-distinguished negatives. Correctness is by-testing; a mechanised - Garside/Dehornoy proof is the research-grade rung. - -### TG-5 LANDED + readiness map for TG-6/7/8 - -- **TG-5 LANDED**: `compiler/test/tg5/tg5_invariants.ml` (189 assertions, in - `dune runtest`) — a structural-invariant property test for the compositional - PD lowering (`compiler/lib/compositional.ml`). compositional sits below the - type layer, so "the rewriter preserves types" is realised as preserving the - lowering's structural invariants + the echo residue-recovery property: - `OpenWord` unit-expanded; `ClosedDiagram` closed / `components=[]` / source - unit-expanded / `|crossings| = |source| = unit-count`; `EchoClosed` residue - **verbatim** (`echoClose(s1^3)` keeps `[s1^3]` while the diagram is the - 3-crossing unit closure), `expand(residue) = diagram word`, and echo-diagram - pdv1-identical to plain `close`; plus error-path and crossing-count pins. - Asserts only invariants the lowering guarantees (no arc-balance/planarity). -- **Readiness map (TG-6/7/8)**: a parallel assessment found each remaining - obligation is blocked on a *prerequisite*, not effort — recorded in - PROOF-NEEDS.md. **TG-8** blocked: the five dialects are prose READMEs with no - implementation. **TG-7** needs an owner decision: braid-group equivalence - changes the observable semantics of `==` on braids in both the evaluator and - the Lean `Step` relation. **TG-6** blocked: no wasm runtime is wired in, so - even differential testing has nothing to execute. - -### TG-3 LANDED: OCaml type checker refines the Lean spec (translation validation) - -Proof obligation TG-3 — "`compiler/lib/typecheck.ml` refines the mechanised -`HasType` spec" — is discharged at the translation-validation level. Full -write-up, closure argument, type translation, divergence catalogue and -extra-core feature list: `proofs/TG3-REFINEMENT.md`. - -- **Reduction.** TG-2 proves Lean `infer ≡ HasType`, so TG-3 reduces to "OCaml - `infer_expr` ≡ Lean `infer` on the shared core fragment". -- **Closure proof.** The core fragment (literals, let/var, compose/tensor/ - pipeline, add, eq, and the echo/product ops — excluding `close` and the whole - Tangle layer) is closed under `infer_expr`: it never produces a `TTangle`, - under a strengthened *entire-type-tree* induction hypothesis (a Tangle must not - hide inside a `TProd`/`TEcho` and leak out via `fst`/`snd`/`lower`/`residue`). -- **Machine-checked half.** `proofs/TG3Differential.lean` — 496 obligations - `infer [] = := by decide`, **generated from the - OCaml checker** by `compiler/test/tg3/tg3_emit.ml` and kernel-verified by - Lean's *proven* `infer`. New `proofs/check-tg3-differential.sh` (builds the - Tangle `.olean`, checks the obligations); wired into `lean-proofs.yml`. -- **OCaml half.** `compiler/test/tg3/` runs `tg3_emit --check` under - `dune runtest`: 1008 assertions over a 490-term corpus — closure invariant, - curated type pins, named→de Bruijn translation (incl. `let`-shadowing), and the - OCaml side of every divergence. -- **Divergence catalogue (complete).** **D1** `close` (OCaml `Tangle[I,I]` vs - Lean `Word[0]` — the sole core boundary gateway) and its downstream vectors - D1b `pipeline(close,close)`, D1c `compose(braid,close)` (OCaml rejects), D1d - `add(close,close)`; **D2** `bool == bool` (OCaml accepts as extra-core, Lean - rejects). Both sides of each are pinned. -- **Honest boundary.** Translation validation over a broad corpus plus a - structural argument — not a single Lean theorem quantifying over all OCaml - runs (that would require reflecting `typecheck.ml`). Refinement is OCaml→Lean. - -### Proof documentation catch-up (TG-1, TG-2, echo-types design note) - -Both TG-1 and TG-2 were already fully proved in `proofs/Tangle.lean` but not -reflected in PROOF-NEEDS.md / PROOF-NARRATIVE.md. This entry documents the -retrospective correction. - -- **TG-1 LANDED**: `weakening` + `subst_preserves` + all four theorems (Progress, - Preservation, Determinism, TypeSafety) extended to `var`/`let`. The "let-free - fragment" caveat in PROOF-NARRATIVE.md is retired. -- **TG-2 LANDED**: `infer` (structural recursion over all 26 HasType rules), - `infer_sound`, `infer_complete`, `infer_iff_hasType`, `type_unique`, - `decidableHasType` — all in `proofs/Tangle.lean` §TG-2. -- **echo-types grade semiring design note** (§2.8 of PROOF-NARRATIVE.md): the - experimental ℕ∪{∞} min-plus grade semiring in `hyperpolymath/echo-types` - (`f7a965f`) uses the combining/monadic direction — the same direction as - Tangle's `echoAdd`/`echoEq`. The splitting/comonadic direction requires a full - graded adjunction and is under experimental investigation (firewalled). No - Tangle design change required now. - -### Echo-threading: EchoClosed compositional IR node - -The compositional PD compiler (`compositional.ml`) now threads the echo -residue through the IR. This is the OCaml-side implementation of the -cross-repo contract at `docs/spec/ECHO-TANGLEIR-THREADING.md`. - -- **`EchoClose of expr`** added to the `expr` type; `echo_close` builder. -- **`EchoClosed { residue; diagram }`** added to `compiled` — carries - the pre-closure braid word alongside the closed planar diagram - (identical to the plain-`Close` output so existing consumers are - unaffected). -- **`compile_echo_and_send_to_skein`** — residue-carrying Skein hook - that emits `echo_closed_payload` with both `residue_blob` - (`"s1,s2^-1,s1"` format) and the PDv1 blob. -- **`word_of_compiled (EchoClosed _)`** returns the residue braid — - the pre-closure word is recoverable at the IR level. -- Parser adapter (`of_ast_expr`) maps `Ast.EchoClose` to the - compositional `EchoClose`, reachable via the new `--compile-pd` CLI - flag (see below). -- Validated against `EchoProvenance.agda` (echoes distinguish - tag-differing records) and `EchoResidue.agda` (`no-section` theorem — - the residue must be threaded, not recomputed after lowering). - -Downstream: Julia `KRLAdapter.jl` and `quandledb` implement the -consumer side per §3–4 of the contract doc. - -### Audit follow-up (correctness + coverage hardening) - -A multi-agent adversarial audit of the echo/TG work surfaced fixes, -applied here: - -- **Residue is now verbatim.** `compile (EchoClose b)` retains the - *unexpanded* pre-closure braid as the residue (via a new - `source_word_of_expr`), so `echoClose(braid[s1^3])` keeps residue - `s1^3` rather than the unit-expanded `s1,s1,s1`. This matches the Lean - `echo_residue_recovers` theorem and the eval interpreter (which were - already exponent-faithful); only the planar diagram is unit-expanded. -- **`Eq` typecheck tightened to the spec.** Word equality now requires - equal width (`Word[n] == Word[m]` ⇒ `n = m`), matching the Lean - `tEqWord` rule; unequal-width comparisons are now rejected instead of - silently evaluating to `false`. `Bool == Bool` is retained as an - explicit extra-core convenience (used by `examples/braids_as_data`). -- **`--compile-pd ` CLI flag** wires the compositional/Skein path - (previously test-only) into the shipped binary: each closed/echo-closed - `def` is lowered to its PDv1 blob, with the residue blob for `echoClose`. -- **Test coverage for the surface echo pipeline.** Added direct - typecheck (`test_typecheck.ml`) and eval (`test_eval.ml`) tests pinning - the residue/result ordering of all 8 echo/product forms against the - Lean `Step` rules — previously only parse/pretty round-trip was tested. -- Adds direct typecheck/eval coverage for the 8 echo forms (suite was 557 - before this batch; see the running total below). - -### TG-9 LANDED: LSP diagnostics delegated to the compiler - -`tangle-lsp` previously computed diagnostics from a hand-rolled lexical -scan that diverged from the real parser/typechecker, emitting LSP-only -false positives (wrong comment syntax, delimiters counted inside string -literals, "unclosed block" on every multi-def file, params flagged as -undefined). None corresponded to a `HasType` failure — violating TG-9. - -- **`compiler/lib/check.ml`** (`check_source`) is now the single - diagnostic source: parse-with-recovery + `Typecheck.check_program`. -- **`tanglec --check `** exposes it as `SEVERITY⇥LINE⇥COL⇥MESSAGE`. -- **`tangle-lsp`** shells out to `tanglec --check` and forwards exactly - those diagnostics; the lexical scan now only extracts definitions / - references for navigation. With the compiler absent it emits nothing - (`∅ ⊆ HasType failures`). The subset relation holds **by construction**. -- Built-in operations now appear in LSP completion (reusing the - previously diagnostic-only `TANGLE_BUILTINS` list). -- Tests: `compiler/test/test_check.ml` and `tangle-lsp` Rust unit tests - (`parse_check_line`, navigation authors no diagnostics, gated - end-to-end delegation against a real `tanglec`). - -### Type-error diagnostics carry source lines - -- `definition` gains a `def_line` field (set from the parser's - `$startpos`); `Typecheck.diagnostic` gains `diag_line`. Definition-scoped - type errors now point at the `def` line instead of the file top, so the - LSP highlights the right line. -- Removed a duplicate diagnostic: `check_program` pass 2 no longer - re-checks definitions (pass 1b already does), so one type error yields - one diagnostic. Statement-level errors (assert/compute/weave) remain - unlocated for now. -- Test-suite total: **597/597** pass. - -### Echo types OCaml pipeline (PR #45 + #46) - -### Added -- Echo/product type system fully landed in the OCaml pipeline (PR #45 + #46): - - `ast.ml`: 8 new `expr` constructors (`echoClose`, `lower`, `residue`, `pair`, `fst`, `snd`, `echoAdd`, `echoEq`); 2 new `ty` constructors (`TProd`, `TEcho`) - - `typecheck.ml`: 8 new `infer_expr` rules mirroring Lean `HasType` (`T-Echo-Close`, `T-Lower`, `T-Residue`, `T-Pair`, `T-Fst`, `T-Snd`, `T-Echo-Add`, `T-Echo-Eq`); `pp_ty` made `rec` - - `eval.ml`: `VEcho`/`VPair` value forms; 8 new `eval_expr` arms; `pp_value` made `rec` - - `lexer.mll` + `parser.mly` + `token.ml`: keyword tokens and grammar productions for all 8 surface forms (`echoClose(e)`, `lower(e)`, `residue(e)`, `pair(a,b)`, `fst(e)`, `snd(e)`, `echoAdd(a,b)`, `echoEq(a,b)`) - - `pretty.ml`: pretty-printers for all 8 forms; round-trips through parser -- TG-4 (pretty-print/parse round-trip) discharged: `test_roundtrip.ml` extended with 8 new echo/product corpus entries (16 round-trip runs) covering every echo/product constructor (PR #46) -- `docs/spec/ECHO-TANGLEIR-THREADING.md`: cross-repo contract for how echo residue threads through TangleIR to QuandleDB (PR #45) -- Compositional PD compiler API (`compositional.ml` / `.mli`): - `expr`, `planar_diagram`, `compiled`, `skein_payload` types -- `pdv1_blob_of_pd`: canonical text serialisation format - (`pdv1|x=a,b,c,d,s;...|c=arc,arc;...`) -- `compile_and_send_to_skein`: direct Tangle → Skein integration entry point -- Playground scaffold in `playground/` (placeholder PWA + 2 example programs) -- README rewrite introducing KRL architecture + visual map (docs/krl_map.html) -- CRG v2 READINESS.md (grade C) - -### Changed -- Tangle composition typecheck: correct permutation application -- WASM: fixed composed braid locals and helper expectations -- Zig ABI layer modernized - -### Fixed -- `compiler/bin/main.ml` debug token printer: add 8 missing echo keyword token arms (Warning 8 exhaustiveness, PR #46) -- `compiler/lib/typecheck.ml` `strand_type_of_ty`: add `TProd`/`TEcho` arms (Warning 8 exhaustiveness, PR #46) -- EXPLAINME.adoc section heading quotes - -## Earlier commits (no versions tagged) - -### UX infrastructure -- Justfile with doctor, tour, help-me, assail recipes -- UX Manifesto deployment -- Agent instructions methodology layer - -### Formal proofs -- Lean 4 proofs: progress, preservation, determinism -- TOPOLOGY.md documentation added - -### RSR compliance -- A2ML migration of state files -- SPDX headers, license migration to MPL-2.0 -- stapeln.toml container definition -- Standard workflow deployment (codeql, hypatia, scorecard, etc.) - -### Language development -- Compiler (OCaml/dune): parser, typechecker, evaluator, pretty-printer, REPL -- WASM backend (`tangle-wasm/`) -- LSP server (`tangle-lsp/`) -- Stdlib (`lib/stdlib.tangle`) diff --git a/CODE_OF_CONDUCT.adoc b/CODE_OF_CONDUCT.adoc new file mode 100644 index 0000000..3ef46d7 --- /dev/null +++ b/CODE_OF_CONDUCT.adoc @@ -0,0 +1,338 @@ +== Code of Conduct + +=== Our Pledge + +We as members, contributors, and leaders pledge to make participation in +tangle a harassment-free experience for everyone, regardless of age, +body size, visible or invisible disability, ethnicity, sex +characteristics, gender identity and expression, level of experience, +education, socio-economic status, nationality, personal appearance, +race, caste, colour, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, +welcoming, diverse, inclusive, and healthy community. + +We recognise that a thriving open source community requires +*psychological safety* — an environment where people can contribute, ask +questions, make mistakes, and learn without fear of ridicule or +retaliation. + +''''' + +=== Our Standards + +==== Expected Behaviour + +The following behaviours contribute to a positive environment: + +*Communication* - Using welcoming and inclusive language - Being +respectful of differing viewpoints and experiences - Giving and +gracefully accepting constructive feedback - Assuming good intent while +addressing impact - Communicating clearly and patiently, especially with +newcomers + +*Collaboration* - Focusing on what is best for the community - Showing +empathy and kindness toward other community members - Being +collaborative rather than competitive - Mentoring and supporting less +experienced contributors - Celebrating others’ contributions and +successes + +*Professionalism* - Accepting responsibility and apologising to those +affected by our mistakes - Learning from the experience and avoiding +repetition - Respecting others’ time and attention - Staying on topic in +project spaces - Following project guidelines and conventions + +*Accessibility* - Using plain language and avoiding unnecessary jargon - +Providing alt text for images and transcripts for audio/video - Being +patient with those using assistive technologies - Accommodating +different communication styles and needs - Recognising that not everyone +communicates the same way + +==== Unacceptable Behaviour + +The following behaviours are considered harassment and are unacceptable: + +*Harassment* - The use of sexualised language or imagery, and sexual +attention or advances of any kind - Trolling, insulting or derogatory +comments, and personal or political attacks - Public or private +harassment - Deliberate intimidation, stalking, or following (online or +in-person) - Unwelcome physical contact or simulated physical contact +(e.g., emoji) - Sustained disruption of talks, events, or online +discussions + +*Discrimination* - Discriminatory jokes and language - Posting or +threatening to post others’ personally identifying information +("`doxing`") - Advocating for, or encouraging, any of the above +behaviour - Microaggressions — subtle, often unintentional, +discriminatory comments or actions + +*Professional Misconduct* - Publishing others’ private information +without explicit permission - Misrepresenting affiliation or +contributions - Plagiarism or claiming credit for others’ work - +Retaliating against anyone who reports a Code of Conduct violation - +Other conduct which could reasonably be considered inappropriate in a +professional setting + +==== Grey Areas + +Some situations require judgement. When uncertain: + +* *Intent vs Impact*: Good intentions do not excuse harmful impact. +Focus on making things right. +* *Power Dynamics*: Those with more power (maintainers, employers, +experienced contributors) must be especially mindful of their impact. +* *Cultural Differences*: What’s acceptable varies by culture. When in +doubt, err on the side of caution and ask. +* *Humour*: Jokes at others’ expense are rarely funny to everyone. Punch +up, not down. + +''''' + +=== Scope + +This Code of Conduct applies within all community spaces, including: + +*Online Spaces* - Repository discussions, issues, and pull/merge +requests - Project chat channels (Matrix, Discord, Slack, IRC) - Mailing +lists and forums - Social media when representing the project - Video +calls and virtual meetings + +*In-Person Spaces* - Conferences, meetups, and events - Workshops and +training sessions - Any gathering where you represent the project + +*Representation* This Code of Conduct also applies when an individual is +officially representing the community in public spaces. Examples +include: + +* Using an official project email address +* Posting via an official social media account +* Acting as an appointed representative at an event +* Speaking on behalf of the project + +''''' + +=== Enforcement + +==== Reporting + +If you experience or witness unacceptable behaviour, or have any other +concerns, please report it as soon as possible. + +*How to Report* + +[width="99%",cols="30%,33%,37%",options="header",] +|=== +|Method |Details |Best For +|*Email* |j.d.a.jewell@open.ac.uk |Detailed reports, sensitive matters + +|*Private Message* |Contact any maintainer directly |Quick questions, +minor issues + +|*Anonymous Form* |[Link to form if available] |When you need anonymity +|=== + +*What to Include* + +* Your contact information (unless anonymous) +* Names/usernames of those involved +* Description of what happened +* When and where it occurred +* Any witnesses +* Any supporting evidence (screenshots, links) +* How you would like us to respond (if you have a preference) + +*What Happens Next* + +[arabic] +. You will receive acknowledgment within *5 working days* +. The conduct team will review the report +. We may ask for additional information +. We will determine appropriate action +. We will inform you of the outcome (respecting others’ privacy) + +==== Confidentiality + +All reports will be handled with discretion: + +* Reporter identity is protected by default +* Details are shared only with those who need to know +* We will ask before naming you in any communication +* Anonymous reports are accepted and investigated + +==== Conflicts of Interest + +If a conduct team member is involved in an incident: + +* They will recuse themselves from the process +* Another maintainer or external party will handle the report +* We will disclose any potential conflicts + +''''' + +=== Enforcement Guidelines + +The conduct team will follow these guidelines in determining +consequences: + +==== 1. Correction + +*Community Impact*: Use of inappropriate language or other behaviour +deemed unprofessional or unwelcome. + +*Consequence*: A private, written warning providing clarity around the +nature of the violation and an explanation of why the behaviour was +inappropriate. A public apology may be requested. + +*Duration*: Immediate + +==== 2. Warning + +*Community Impact*: A violation through a single incident or series of +actions. + +*Consequence*: A warning with consequences for continued behaviour. No +interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, for a specified period. This +includes avoiding interactions in community spaces as well as external +channels like social media. Violating these terms may lead to a +temporary or permanent ban. + +*Duration*: 1-4 weeks + +==== 3. Temporary Ban + +*Community Impact*: A serious violation of community standards, +including sustained inappropriate behaviour. + +*Consequence*: A temporary ban from any sort of interaction or public +communication with the community for a specified period. No public or +private interaction with the people involved, including unsolicited +interaction with those enforcing the Code of Conduct, is allowed during +this period. Violating these terms may lead to a permanent ban. + +*Duration*: 1-6 months + +==== 4. Permanent Ban + +*Community Impact*: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behaviour, harassment of an +individual, or aggression toward or disparagement of classes of +individuals. + +*Consequence*: A permanent ban from any sort of public interaction +within the community. + +*Duration*: Permanent (with appeal rights after 12 months) + +==== Enforcement Across Perimeters + +For contributors with elevated access (Perimeter 2 or 1): + +[cols=",",options="header",] +|=== +|Level |Additional Consequence +|Correction |Noted in contributor record +|Warning |Access privileges may be temporarily reduced +|Temporary Ban |Access reduced to Perimeter 3 for ban duration +|Permanent Ban |All access revoked +|=== + +''''' + +=== Appeals + +If you believe an enforcement decision was made in error: + +[arabic] +. *Wait 7 days* after the decision (cooling-off period) +. *Email* j.d.a.jewell@open.ac.uk with subject line "`Appeal: [Original +Report ID]`" +. *Explain* why you believe the decision should be reconsidered +. *Provide* any new information not previously available + +*Appeals Process* + +* Appeals are reviewed by a different conduct team member than the +original +* You will receive a response within 14 days +* The appeals decision is final +* You may only appeal once per incident + +*Grounds for Appeal* + +* Procedural errors in the original investigation +* New evidence not previously available +* Disproportionate response to the violation +* Misunderstanding of facts + +''''' + +=== Supporting Those Who Report + +We are committed to supporting those who report violations: + +*We Will* - Believe and take all reports seriously - Respect your +privacy and confidentiality preferences - Keep you informed of progress +(if you wish) - Take steps to protect you from retaliation - Provide +resources if you need support + +*We Will Not* - Require you to confront the person directly - Dismiss +reports without investigation - Reveal your identity without consent - +Tolerate retaliation against reporters - Rush you to make decisions + +''''' + +=== Prevention + +Beyond enforcement, we actively work to prevent issues: + +*Onboarding* - All contributors are expected to read this Code of +Conduct - Perimeter 2 applicants must confirm they’ve read and +understood it - Maintainers receive additional training on enforcement + +*Culture* - We model the behaviour we expect - We intervene early when +we see potential issues - We thank people for positive contributions - +We create opportunities for diverse voices + +*Review* - This Code of Conduct is reviewed annually - Community +feedback is welcomed - Changes are communicated clearly + +''''' + +=== Acknowledgments + +This Code of Conduct is adapted from: + +* https://www.contributor-covenant.org/[Contributor Covenant], version +2.1 +* https://www.djangoproject.com/conduct/[Django Code of Conduct] +* https://www.rust-lang.org/policies/code-of-conduct[Rust Code of +Conduct] +* https://www.python.org/psf/conduct/[Python Community Code of Conduct] + +We thank these communities for their leadership in creating welcoming +spaces. + +''''' + +=== Questions? + +If you have questions about this Code of Conduct: + +* Open a https://github.com/hyperpolymath/tangle/discussions[Discussion] +(for general questions) +* Email j.d.a.jewell@open.ac.uk (for private questions) +* Contact any maintainer directly + +''''' + +=== Summary + +*Be kind. Be respectful. Be collaborative.* + +We’re all here because we care about this project. Let’s make it a place +where everyone can do their best work. + +''''' + +Last updated: 2026 · Based on Contributor Covenant 2.1 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 5c83718..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,311 +0,0 @@ - -# Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in tangle a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, colour, religion, or sexual identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. - -We recognise that a thriving open source community requires **psychological safety** — an environment where people can contribute, ask questions, make mistakes, and learn without fear of ridicule or retaliation. - ---- - -## Our Standards - -### Expected Behaviour - -The following behaviours contribute to a positive environment: - -**Communication** -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Giving and gracefully accepting constructive feedback -- Assuming good intent while addressing impact -- Communicating clearly and patiently, especially with newcomers - -**Collaboration** -- Focusing on what is best for the community -- Showing empathy and kindness toward other community members -- Being collaborative rather than competitive -- Mentoring and supporting less experienced contributors -- Celebrating others' contributions and successes - -**Professionalism** -- Accepting responsibility and apologising to those affected by our mistakes -- Learning from the experience and avoiding repetition -- Respecting others' time and attention -- Staying on topic in project spaces -- Following project guidelines and conventions - -**Accessibility** -- Using plain language and avoiding unnecessary jargon -- Providing alt text for images and transcripts for audio/video -- Being patient with those using assistive technologies -- Accommodating different communication styles and needs -- Recognising that not everyone communicates the same way - -### Unacceptable Behaviour - -The following behaviours are considered harassment and are unacceptable: - -**Harassment** -- The use of sexualised language or imagery, and sexual attention or advances of any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Deliberate intimidation, stalking, or following (online or in-person) -- Unwelcome physical contact or simulated physical contact (e.g., emoji) -- Sustained disruption of talks, events, or online discussions - -**Discrimination** -- Discriminatory jokes and language -- Posting or threatening to post others' personally identifying information ("doxing") -- Advocating for, or encouraging, any of the above behaviour -- Microaggressions — subtle, often unintentional, discriminatory comments or actions - -**Professional Misconduct** -- Publishing others' private information without explicit permission -- Misrepresenting affiliation or contributions -- Plagiarism or claiming credit for others' work -- Retaliating against anyone who reports a Code of Conduct violation -- Other conduct which could reasonably be considered inappropriate in a professional setting - -### Grey Areas - -Some situations require judgement. When uncertain: - -- **Intent vs Impact**: Good intentions do not excuse harmful impact. Focus on making things right. -- **Power Dynamics**: Those with more power (maintainers, employers, experienced contributors) must be especially mindful of their impact. -- **Cultural Differences**: What's acceptable varies by culture. When in doubt, err on the side of caution and ask. -- **Humour**: Jokes at others' expense are rarely funny to everyone. Punch up, not down. - ---- - -## Scope - -This Code of Conduct applies within all community spaces, including: - -**Online Spaces** -- Repository discussions, issues, and pull/merge requests -- Project chat channels (Matrix, Discord, Slack, IRC) -- Mailing lists and forums -- Social media when representing the project -- Video calls and virtual meetings - -**In-Person Spaces** -- Conferences, meetups, and events -- Workshops and training sessions -- Any gathering where you represent the project - -**Representation** -This Code of Conduct also applies when an individual is officially representing the community in public spaces. Examples include: - -- Using an official project email address -- Posting via an official social media account -- Acting as an appointed representative at an event -- Speaking on behalf of the project - ---- - -## Enforcement - -### Reporting - -If you experience or witness unacceptable behaviour, or have any other concerns, please report it as soon as possible. - -**How to Report** - -| Method | Details | Best For | -|--------|---------|----------| -| **Email** | j.d.a.jewell@open.ac.uk | Detailed reports, sensitive matters | -| **Private Message** | Contact any maintainer directly | Quick questions, minor issues | -| **Anonymous Form** | [Link to form if available] | When you need anonymity | - -**What to Include** - -- Your contact information (unless anonymous) -- Names/usernames of those involved -- Description of what happened -- When and where it occurred -- Any witnesses -- Any supporting evidence (screenshots, links) -- How you would like us to respond (if you have a preference) - -**What Happens Next** - -1. You will receive acknowledgment within **5 working days** -2. The conduct team will review the report -3. We may ask for additional information -4. We will determine appropriate action -5. We will inform you of the outcome (respecting others' privacy) - -### Confidentiality - -All reports will be handled with discretion: - -- Reporter identity is protected by default -- Details are shared only with those who need to know -- We will ask before naming you in any communication -- Anonymous reports are accepted and investigated - -### Conflicts of Interest - -If a conduct team member is involved in an incident: - -- They will recuse themselves from the process -- Another maintainer or external party will handle the report -- We will disclose any potential conflicts - ---- - -## Enforcement Guidelines - -The conduct team will follow these guidelines in determining consequences: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behaviour deemed unprofessional or unwelcome. - -**Consequence**: A private, written warning providing clarity around the nature of the violation and an explanation of why the behaviour was inappropriate. A public apology may be requested. - -**Duration**: Immediate - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of actions. - -**Consequence**: A warning with consequences for continued behaviour. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. - -**Duration**: 1-4 weeks - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including sustained inappropriate behaviour. - -**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. - -**Duration**: 1-6 months - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behaviour, harassment of an individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the community. - -**Duration**: Permanent (with appeal rights after 12 months) - -### Enforcement Across Perimeters - -For contributors with elevated access (Perimeter 2 or 1): - -| Level | Additional Consequence | -|-------|----------------------| -| Correction | Noted in contributor record | -| Warning | Access privileges may be temporarily reduced | -| Temporary Ban | Access reduced to Perimeter 3 for ban duration | -| Permanent Ban | All access revoked | - ---- - -## Appeals - -If you believe an enforcement decision was made in error: - -1. **Wait 7 days** after the decision (cooling-off period) -2. **Email** j.d.a.jewell@open.ac.uk with subject line "Appeal: [Original Report ID]" -3. **Explain** why you believe the decision should be reconsidered -4. **Provide** any new information not previously available - -**Appeals Process** - -- Appeals are reviewed by a different conduct team member than the original -- You will receive a response within 14 days -- The appeals decision is final -- You may only appeal once per incident - -**Grounds for Appeal** - -- Procedural errors in the original investigation -- New evidence not previously available -- Disproportionate response to the violation -- Misunderstanding of facts - ---- - -## Supporting Those Who Report - -We are committed to supporting those who report violations: - -**We Will** -- Believe and take all reports seriously -- Respect your privacy and confidentiality preferences -- Keep you informed of progress (if you wish) -- Take steps to protect you from retaliation -- Provide resources if you need support - -**We Will Not** -- Require you to confront the person directly -- Dismiss reports without investigation -- Reveal your identity without consent -- Tolerate retaliation against reporters -- Rush you to make decisions - ---- - -## Prevention - -Beyond enforcement, we actively work to prevent issues: - -**Onboarding** -- All contributors are expected to read this Code of Conduct -- Perimeter 2 applicants must confirm they've read and understood it -- Maintainers receive additional training on enforcement - -**Culture** -- We model the behaviour we expect -- We intervene early when we see potential issues -- We thank people for positive contributions -- We create opportunities for diverse voices - -**Review** -- This Code of Conduct is reviewed annually -- Community feedback is welcomed -- Changes are communicated clearly - ---- - -## Acknowledgments - -This Code of Conduct is adapted from: - -- [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1 -- [Django Code of Conduct](https://www.djangoproject.com/conduct/) -- [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct) -- [Python Community Code of Conduct](https://www.python.org/psf/conduct/) - -We thank these communities for their leadership in creating welcoming spaces. - ---- - -## Questions? - -If you have questions about this Code of Conduct: - -- Open a [Discussion](https://github.com/hyperpolymath/tangle/discussions) (for general questions) -- Email j.d.a.jewell@open.ac.uk (for private questions) -- Contact any maintainer directly - ---- - -## Summary - -**Be kind. Be respectful. Be collaborative.** - -We're all here because we care about this project. Let's make it a place where everyone can do their best work. - ---- - -Last updated: 2026 · Based on Contributor Covenant 2.1 diff --git a/CONTRIBUTING.adoc b/CONTRIBUTING.adoc new file mode 100644 index 0000000..9972433 --- /dev/null +++ b/CONTRIBUTING.adoc @@ -0,0 +1,108 @@ +== Clone the repository + +git clone https://github.com/hyperpolymath/tangle.git cd tangle + +== Using Nix (recommended for reproducibility) + +nix develop + +== Or using toolbox/distrobox + +toolbox create tangle-dev toolbox enter tangle-dev # Install +dependencies manually + +== Verify setup + +just check # or: cargo check / mix compile / etc. just test # Run test +suite + +.... + +### Repository Structure +.... + +tangle/ ├── src/ # Source code (Perimeter 1-2) ├── lib/ # Library code +(Perimeter 1-2) ├── extensions/ # Extensions (Perimeter 2) ├── plugins/ +# Plugins (Perimeter 2) ├── tools/ # Tooling (Perimeter 2) ├── docs/ # +Documentation (Perimeter 3) │ ├── architecture/ # ADRs, specs (Perimeter +2) │ └── proposals/ # RFCs (Perimeter 3) ├── examples/ # Examples +(Perimeter 3) ├── spec/ # Spec tests (Perimeter 3) ├── tests/ # Test +suite (Perimeter 2-3) ├── .well-known/ # Protocol files (Perimeter 1-3) +├── .github/ # GitHub config (Perimeter 1) │ ├── ISSUE_TEMPLATE/ │ └── +workflows/ ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md # +This file ├── GOVERNANCE.md ├── LICENSE ├── MAINTAINERS.md ├── +README.adoc ├── SECURITY.md ├── flake.nix # Nix flake (Perimeter 1) └── +Justfile # Task runner (Perimeter 1) + +.... + +--- + +## How to Contribute + +### Reporting Bugs + +**Before reporting**: +1. Search existing issues +2. Check if it's already fixed in `main` +3. Determine which perimeter the bug affects + +**When reporting**: + +Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md) and include: + +- Clear, descriptive title +- Environment details (OS, versions, toolchain) +- Steps to reproduce +- Expected vs actual behaviour +- Logs, screenshots, or minimal reproduction + +### Suggesting Features + +**Before suggesting**: +1. Check the [roadmap](ROADMAP.md) if available +2. Search existing issues and discussions +3. Consider which perimeter the feature belongs to + +**When suggesting**: + +Use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.md) and include: + +- Problem statement (what pain point does this solve?) +- Proposed solution +- Alternatives considered +- Which perimeter this affects + +### Your First Contribution + +Look for issues labelled: + +- [`good first issue`](https://github.com/hyperpolymath/tangle/labels/good%20first%20issue) — Simple Perimeter 3 tasks +- [`help wanted`](https://github.com/hyperpolymath/tangle/labels/help%20wanted) — Community help needed +- [`documentation`](https://github.com/hyperpolymath/tangle/labels/documentation) — Docs improvements +- [`perimeter-3`](https://github.com/hyperpolymath/tangle/labels/perimeter-3) — Community sandbox scope + +--- + +## Development Workflow + +### Branch Naming +.... + +docs/short-description # Documentation (P3) test/what-added # Test +additions (P3) feat/short-description # New features (P2) +fix/issue-number-description # Bug fixes (P2) refactor/what-changed # +Code improvements (P2) security/what-fixed # Security fixes (P1-2) + +.... + +### Commit Messages + +We follow [Conventional Commits](https://www.conventionalcommits.org/): +.... + +(): + +{empty}[optional body] + +{empty}[optional footer] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index ab9eebb..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,120 +0,0 @@ - -# Clone the repository -git clone https://github.com/hyperpolymath/tangle.git -cd tangle - -# Using Nix (recommended for reproducibility) -nix develop - -# Or using toolbox/distrobox -toolbox create tangle-dev -toolbox enter tangle-dev -# Install dependencies manually - -# Verify setup -just check # or: cargo check / mix compile / etc. -just test # Run test suite -``` - -### Repository Structure -``` -tangle/ -├── src/ # Source code (Perimeter 1-2) -├── lib/ # Library code (Perimeter 1-2) -├── extensions/ # Extensions (Perimeter 2) -├── plugins/ # Plugins (Perimeter 2) -├── tools/ # Tooling (Perimeter 2) -├── docs/ # Documentation (Perimeter 3) -│ ├── architecture/ # ADRs, specs (Perimeter 2) -│ └── proposals/ # RFCs (Perimeter 3) -├── examples/ # Examples (Perimeter 3) -├── spec/ # Spec tests (Perimeter 3) -├── tests/ # Test suite (Perimeter 2-3) -├── .well-known/ # Protocol files (Perimeter 1-3) -├── .github/ # GitHub config (Perimeter 1) -│ ├── ISSUE_TEMPLATE/ -│ └── workflows/ -├── CHANGELOG.md -├── CODE_OF_CONDUCT.md -├── CONTRIBUTING.md # This file -├── GOVERNANCE.md -├── LICENSE -├── MAINTAINERS.md -├── README.adoc -├── SECURITY.md -├── flake.nix # Nix flake (Perimeter 1) -└── Justfile # Task runner (Perimeter 1) -``` - ---- - -## How to Contribute - -### Reporting Bugs - -**Before reporting**: -1. Search existing issues -2. Check if it's already fixed in `main` -3. Determine which perimeter the bug affects - -**When reporting**: - -Use the [bug report template](.github/ISSUE_TEMPLATE/bug_report.md) and include: - -- Clear, descriptive title -- Environment details (OS, versions, toolchain) -- Steps to reproduce -- Expected vs actual behaviour -- Logs, screenshots, or minimal reproduction - -### Suggesting Features - -**Before suggesting**: -1. Check the [roadmap](ROADMAP.md) if available -2. Search existing issues and discussions -3. Consider which perimeter the feature belongs to - -**When suggesting**: - -Use the [feature request template](.github/ISSUE_TEMPLATE/feature_request.md) and include: - -- Problem statement (what pain point does this solve?) -- Proposed solution -- Alternatives considered -- Which perimeter this affects - -### Your First Contribution - -Look for issues labelled: - -- [`good first issue`](https://github.com/hyperpolymath/tangle/labels/good%20first%20issue) — Simple Perimeter 3 tasks -- [`help wanted`](https://github.com/hyperpolymath/tangle/labels/help%20wanted) — Community help needed -- [`documentation`](https://github.com/hyperpolymath/tangle/labels/documentation) — Docs improvements -- [`perimeter-3`](https://github.com/hyperpolymath/tangle/labels/perimeter-3) — Community sandbox scope - ---- - -## Development Workflow - -### Branch Naming -``` -docs/short-description # Documentation (P3) -test/what-added # Test additions (P3) -feat/short-description # New features (P2) -fix/issue-number-description # Bug fixes (P2) -refactor/what-changed # Code improvements (P2) -security/what-fixed # Security fixes (P1-2) -``` - -### Commit Messages - -We follow [Conventional Commits](https://www.conventionalcommits.org/): -``` -(): - -[optional body] - -[optional footer] diff --git a/PROOF-NARRATIVE.adoc b/PROOF-NARRATIVE.adoc new file mode 100644 index 0000000..add765e --- /dev/null +++ b/PROOF-NARRATIVE.adoc @@ -0,0 +1,646 @@ +== Proof Narrative — Tangle + +This file is the *single coherent story* of what Tangle proves, what it +assumes, and what it has left to prove. + +For the per-obligation checklist with status/prover/effort, see +PROOF-NEEDS.md. For the registry of every load-bearing unproven +assumption, see ASSUMPTIONS.md. + +''''' + +=== 1. Position in the stack + +Tangle is the *semantic core* of a four-layer federated stack: + +.... +┌─────────────────────────────────────────────────────────┐ +│ KRL surface language (hyperpolymath/krl) │ +└─────────────────┬───────────────────────────────────────┘ + │ lowers via KR-1, KR-2 to + ▼ +┌─────────────────────────────────────────────────────────┐ +│ TangleIR (canonical interchange obj) │ +└─────────────────┬───────────────────────────────────────┘ + │ has semantics via + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Tangle CORE (THIS REPO) │ +│ proofs/Tangle.lean — mechanised results (26 HasType, 55 Step) │ +│ compiler/lib/*.ml — OCaml implementation │ +│ compiler/tangle-wasm — WASM backend │ +│ compiler/tangle-lsp — LSP server │ +│ dialects/ — braid-calculus, quantum-circuit, etc. │ +└─────────────────┬───────────────────────────────────────┘ + │ persisted/queried via + ▼ +┌─────────────────────────────────────────────────────────┐ +│ Skein.jl + QuandleDB │ +└─────────────────────────────────────────────────────────┘ +.... + +Consequence: *Tangle owes a real metatheory.* It owns the type system +that everyone above and below depends on. Tangle.lean already delivers a +substantial slice of this; this document makes the delivered slice and +the remaining gap explicit. + +=== 2. Proven now + +All results live in link:proofs/Tangle.lean[`+proofs/Tangle.lean+`] +(Lean 4, no `+sorry+`, no `+axiom+`). + +*Build oracle.* As of 2026-06-01 (PR closing TG-0, +hyperpolymath/tangle#32), the file is verified at every push/PR by +`+.github/workflows/lean-proofs.yml+`, pinned to +`+proofs/lean-toolchain = leanprover/lean4:v4.14.0+`. Empirical result +on the original 2026-03-30 commit: 121 errors on every Lean 4 version +4.9–4.16 — the file had never compiled. The current commit returns *0 +errors*, verified locally on v4.10/4.11/4.12/4.13/4.14/4.15/4.16, with +CI gating both `+lean Tangle.lean+` and a `+sorry+`/`+axiom+`/`+admit+` +slippage check. Future drift will fail CI rather than land silently. + +*Echo-types — now integrated as a type-system feature (2026-06-03).* The +earlier audit +(`+feedback_echo_types_audit_krl_tangle_quandledb_not_relevant.md+`) +correctly found that the _external_ echo-types Agda library +(hyperpolymath/echo-types) carries no lambda-calculus / progress / +preservation content of its own, so it does not perturb the four base +theorems. That verdict stands for the external library. *Tangle now +ships its own simply-typed shadow of echo-types as a first-class feature +of the type system* (`+Ty.echo ρ τ+`, constructors +`+echoClose+`/`+lower+`/ `+residue+`, rules +`+T-Echo-Close+`/`+T-Lower+`/`+T-Residue+`). The motivation is intrinsic +to Tangle: `+close : Word[n] → Word[0]+` is the canonical lossy map (the +analogue of echo-types’ `+collapse : Bool → ⊤+`), and the echo layer +makes that loss recoverable at the type level — the residue `+Word[n]+` +is retained and projected back out. Progress, Preservation, Determinism, +and Type Safety in `+proofs/Tangle.lean+` now *cover the echo fragment*, +and three capstone theorems (`+echo_lower_collapses+`, +`+echo_residue_recovers+`, `+echo_distinguishes_collapsed+`) reproduce +echo-types’ `+no-section+` / `+sigma-distinguishes+` barrier inside +Tangle. See PROOF-NARRATIVE §2.5. + +==== Theorems (the main results) + +[width="100%",cols="19%,50%,31%",options="header",] +|=== +|ID |Statement |Where +|*T-Progress* |Every well-typed closed term is either a value or can +take a step. |`+Tangle.lean:670+` + +|*T-Preservation* |Stepping preserves types: +`+Γ ⊢ e : τ ∧ e → e' ⟹ Γ ⊢ e' : τ+`. |`+Tangle.lean:870+` + +|*T-Determinism* |The step relation is deterministic: +`+e → e₁ ∧ e → e₂ ⟹ e₁ = e₂+`. |`+Tangle.lean:1053+` + +|*T-TypeSafety* |Well-typed closed terms never get stuck (Progress + +Preservation corollary). |`+Tangle.lean:1303+` +|=== + +Each is proven for the *full core fragment*: numerals, strings, +booleans, identity, braid literals, composition, tensor, pipeline, +close, addition, equality, variables, let-binding, the complete +echo/product fragment (see §2.5), and decidable type inference (see +§2.7). The "`let-free fragment`" caveat is retired — TG-1 and TG-2 are +both landed. + +==== Supporting lemmas + +[width="100%",cols="19%,50%,31%",options="header",] +|=== +|ID |Statement |Where +|T-ValueNoStep |Values are normal forms: `+IsValue e ⟹ ¬ Step e e'+`. +|`+Tangle.lean:394+` + +|T-CanonicalNum |A typed-Num value is `+.num n+` for some `+n+`. +|`+Tangle.lean:405+` + +|T-CanonicalStr |A typed-Str value is `+.str s+` for some `+s+`. +|`+Tangle.lean:409+` + +|T-CanonicalWord |A typed-Word[n] value is `+.identity+` (n=0) or +`+.braidLit gs+`. |`+Tangle.lean:413+` + +|T-CanonicalEcho |A typed-Echo value is `+.echoVal r v+` for values r, +v. |`+Tangle.lean:428+` + +|T-CanonicalProd |A typed-Prod value is `+.pair a b+` for values a, b. +|`+Tangle.lean:443+` + +|T-WidthAppend |`+width(gs₁ ++ gs₂) = max(width gs₁, width gs₂)+`. +|`+Tangle.lean:466+` + +|T-WidthShift +|`+width(shift gs n) = if gs=[] then 0 else width gs + n+`. +|`+Tangle.lean:485+` + +|*T-Weakening* |Inserting a fresh hypothesis at de Bruijn position +`+Γ₁.length+` preserves typing (TG-1). |`+Tangle.lean:521+` + +|*T-SubstPreserves* |Typing is preserved under capture-avoiding +substitution of a typed term for a variable (TG-1). |`+Tangle.lean:589+` +|=== + +==== Type-system and step-relation definitions + +`+Tangle.lean+` also defines, as inductive types (so they are themselves +proofs of the form "`these are the rules`"): + +* *`+Expr+`* — the AST (mirrors `+compiler/lib/ast.ml+`) +* *`+Ty+`* — `+num+`, `+str+`, `+bool+`, `+word n+` +* *`+IsValue+`* — value predicate +* *`+HasType+`* — typing judgment, 26 rules: 13 base (`+tNum+`, +`+tStr+`, `+tBool+`, `+tIdentity+`, `+tBraid+`, `+tComposeWord+`, +`+tTensorWord+`, `+tPipeline+`, `+tCloseWord+`, `+tAddNum+`, +`+tEqWord+`, `+tEqNum+`, `+tEqStr+`); 4 echo-close (`+tEchoClose+`, +`+tLower+`, `+tResidue+`, `+tEchoVal+`); 7 product+echo-binary +(`+tPair+`, `+tFst+`, `+tSnd+`, `+tEchoAdd+`, `+tEchoEqWord+`, +`+tEchoEqNum+`, `+tEchoEqStr+`); 2 let/var (`+tVar+`, `+tLet+`) +* *`+Step+`* — small-step semantics, 55 rules: 27 base, 9 +echo-close/lower/residue, 6 product, 11 echoAdd/echoEq, 2 let (plus a +separate 2-constructor `+StepStar+` reflexive-transitive closure: +`+refl+`, `+head+`) + +These are the formal spec the OCaml implementation is meant to refine +(see TG-3 below). + +=== 2.5 Echo types — structured loss as a type-system feature + +Echo types are integrated into the core type system (not a separate +layer). The design mirrors echo-types’ fibre definition +`+Echo f y := Σ (x : A), f x ≡ y+` (hyperpolymath/echo-types, +`+Echo.agda+`) in Tangle’s simply-typed setting, motivated by Tangle’s +own canonical lossy operation. + +*Why `+close+`.* `+close : Word[n] → Word[0]+` collapses every braid +word to the identity, discarding the word — exactly the kind of +information-destroying map echo-types is about +(cf. `+collapse : Bool → ⊤+` in `+EchoResidue.agda+`). Echo types make +that loss _recoverable in the type system_. + +[width="100%",cols="30%,15%,55%",options="header",] +|=== +|Construct |Form |Echo-types analogue +|Type former |`+Ty.echo ρ τ+` — a `+τ+`-result carrying a `+ρ+`-residue +|`+Echo f y+` (ρ = domain witness, τ = codomain point) + +|`+echoClose e+` |`+Word[n] → Echo (Word[n]) (Word[0])+` +|`+echo-intro close+` + +|`+lower e+` |`+Echo ρ τ → τ+` — project to result (forget residue) |the +collapse / `+proj₂+` + +|`+residue e+` |`+Echo ρ τ → ρ+` — recover the witness braid |`+proj₁+` + +|`+pair(a, b)+` |`+α → β → α × β+` — product introduction |`+Echo.Pair+` +(product as residue carrier) + +|`+fst(e)+` |`+α × β → α+` — first projection |`+proj₁+` + +|`+snd(e)+` |`+α × β → β+` — second projection |`+proj₂+` + +|`+echoAdd(a, b)+` |`+Num → Num → Echo (Num × Num) Num+` — addition with +summand residue |`+echo-intro add+` + +|`+echoEq(a, b)+` |`+ρ → ρ → Echo (ρ × ρ) Bool+` — equality with operand +residue |`+echo-intro eq+` +|=== + +*Metatheory.* Progress, Preservation, Determinism, and Type Safety all +cover `+echoClose+`/`+lower+`/`+residue+` (the inductions are exhaustive +over the extended `+Step+`/`+HasType+`). A new canonical-forms lemma +`+canonical_echo+` characterises echo values; `+value_no_step+` became +structurally recursive because a formed echo `+echoClose v+` is a value +iff its residue `+v+` is. + +*Capstone theorems* (the echo-types _content_, `+Tangle.lean+` +§ECHO-TYPES): - `+echo_lower_collapses+` — every closed braid lowers to +`+identity+` (the lossy step, re-derived through the echo). - +`+echo_residue_recovers+` — +`+residue (echoClose (braidLit gs)) ⟶ braidLit gs+` (the witness is +retained; `+close+` becomes reversible). - +`+echo_distinguishes_collapsed+` — distinct braids collapse to the +_same_ identity under `+lower+`, yet their residues stay distinct. This +is the Tangle instantiation of echo-types’ non-injectivity barrier +(`+collapse-residue-same+` + `+no-section-collapse-to-residue+`). - +`+echo_roundtrip_typed+` — the round-trip is well-typed: `+residue+` +returns a `+Word[n]+`, `+lower+` returns a `+Word[0]+`. + +Tracked as obligation *TG-10* in PROOF-NEEDS.md (landed). + +=== 2.6 OCaml implementation completeness + +As of 2026-06-14 (PRs #45–#46), the OCaml pipeline (`+compiler/lib/+`) +covers the complete echo + product fragment described in §2.5: + +[width="100%",cols="24%,76%",options="header",] +|=== +|Layer |Echo/product coverage +|`+ast.ml+` |`+EchoClose+`, `+Lower+`, `+Residue+`, `+Pair+`, `+Fst+`, +`+Snd+`, `+EchoAdd+`, `+EchoEq+` in `+expr+`; `+TProd+`, `+TEcho+` in +`+ty+` + +|`+typecheck.ml+` |8 `+infer_expr+` rules matching Lean `+HasType+`; +`+pp_ty+` made `+rec+` + +|`+eval.ml+` |`+VEcho+`, `+VPair+` values; 8 `+eval_expr+` arms; +`+pp_value+` made `+rec+` + +|`+lexer.mll+` / `+parser.mly+` / `+token.ml+` |Keyword tokens + grammar +productions for all 8 surface forms + +|`+pretty.ml+` |Pretty-printers for all 8 forms + +|`+test_roundtrip.ml+` |TG-4 round-trip property test: 26-entry corpus +including all 8 echo/product constructors +|=== + +*Build oracle*: `+dune build+` + `+dune test+` green (run +`+dune runtest+` for the live count — ~597 across 8 suites). The pre-PR +#46 `+main+` did not compile due to two `+Warning 8+` exhaustiveness +gaps (both fixed: `+strand_type_of_ty+` in `+typecheck.ml+`; debug token +printer in `+bin/main.ml+`). + +*TG-3 landed* (translation validation): the OCaml typechecker is proven +to refine `+HasType+` on the core fragment — +`+proofs/TG3Differential.lean+` emits 496 obligations generated from +`+infer_expr+` that Lean’s proven `+infer+` kernel-checks, plus a +closure proof and 1008 OCaml `+--check+` assertions. The two documented +divergences are `+close+` (D1) and `+bool == bool+` (D2). See +`+proofs/TG3-REFINEMENT.md+` and §TG-3 below. + +=== 2.7 Let-binding and decidability (TG-1 + TG-2) + +Both obligations landed in `+proofs/Tangle.lean+` and are documented in +§TG-1 and §TG-2 of the remaining-obligations section below (those +sections now carry LANDED verdicts). Key structural points: + +* *TG-1 (let-binding)*: `+weakening+` + `+subst_preserves+` use the de +Bruijn combined-context invariant — `+subst_preserves+` types the +substitutee in `+Γ₁ ++ Γ₂+`, not merely `+Γ₂+`. This is the genuine +inductive invariant; the `+letRed+` consumer uses `+Γ₁ := []+` where +both forms coincide. +* *TG-2 (decidability)*: `+infer+` is a single structural recursion +covering all 26 `+HasType+` rules. Both soundness and completeness are +proven; `+type_unique+` follows as a corollary. The `+decidableHasType+` +instance makes `+HasType [] e τ+` a decidable proposition directly +usable by Lean’s typeclass system. + +=== 2.8 Echo-types grade semiring — design note + +`+hyperpolymath/echo-types+` (commit `+f7a965f+`, 2026-06-14) added an +experimental ℕ∪\{∞} min-plus grade semiring +(`+experimental/echo-additive/Grade.agda+`) and a variance gate +(`+VarianceGate.agda+`). Key findings and their implications for Tangle: + +* The *combining direction* (`+D_r(D_s A) → D_{r+s} A+`) has *monadic* +variance. Tangle’s `+echoAdd+`/`+echoEq+` use exactly this direction: +two residues are merged into a `+pair+` (the lax monoidal μ map). The +current implementation is correct for this reading. +* The *splitting direction* (`+D_{r+s} A → D_r(D_s A)+`) has *comonadic* +variance and requires a full graded adjunction F_r ⊣ U_r. If Tangle ever +needs to split an `+Echo(ρ×σ)+` value back into independent `+Echo(ρ)+` +and `+Echo(σ)+`, that is a non-trivial structural addition — it cannot +be derived from the combining map alone. +* The *grade semiring* (`+fin n+` = information count, `+inf+` = total +collapse) is a candidate carrier for a future grade-indexed type former +`+Echo[n] ρ τ+` in Tangle. `+echoAdd+` would then have type +`+Num → Num → Echo[2] (Num×Num) Num+` (2 units of information retained). +This is prospective; the experimental subtree is firewalled until the +comparative protocol (monadic vs comonadic) concludes. +* *No Tangle design change is required now.* The current +`+Ty.echo+`/`+Ty.prod+` fragment is faithful to the monadic/combining +direction and the experimental work is explicitly gated +(`+experimental/echo-additive/+` is not imported by any shipped module +in echo-types or Tangle). + +=== 3. Remaining obligations (the narrative arc) + +What’s not yet proven, why it matters, and what assumption each rests +on. + +==== TG-1 — Type safety extended to `+let+`-binding + +*Status: LANDED* (`+proofs/Tangle.lean+` §METATHEORY, lines 492–668). + +*Claim.* Type safety (Progress, Preservation, Determinism, TypeSafety) +extends to the full core language including `+var+` and `+let+`. + +*What was proven.* - `+weakening+` (line 521) — inserting a fresh +hypothesis `+σ+` at de Bruijn position `+Γ₁.length+` preserves typing, +with the term shifted by `+shift 1 Γ₁.length+`. - `+subst_preserves+` +(line 589) — typing is closed under replacing the variable at +`+Γ₁.length+` by a well-typed term `+s+`. The substitutee is typed in +the combined context `+Γ₁ ++ Γ₂+` (the genuine inductive invariant; the +`+letRed+` consumer instantiates `+Γ₁ := []+`). - All four main theorems +(Progress, Preservation, Determinism, TypeSafety) were extended with +`+var+` and `+letStep+`/`+letRed+` cases. `+Step+` gained `+letStep+` +and `+letRed+`; `+HasType+` gained `+tVar+` and `+tLet+`. + +*Implementation notes.* - Variable lookup uses `+List.getElem?+` (not +the deprecated `+List.get?+`); the append splits go through +`+List.getElem?_append_left+` / `+_append_right+`. - Each derivation is +taken apart with `+cases h; rename_i+` rather than +`+cases h with | tCtor+`, because under `+induction e+` the binder +arguments unify with the context and positional arm naming doesn’t +align. - The `+subst_preserves+` combined-context invariant closes the +`+var = Γ₁.length+` case by `+exact hs+` with no separate +shift-composition lemma needed. + +*Assumptions discharged.* - [[A-TG-1.1]] ✓ — `+subst+` is defined by +structural recursion on `+Expr+`, covering all 22 constructors. - +[[A-TG-1.2]] ✓ — `+weakening+` and `+subst_preserves+` both proven. + +==== TG-2 — Decidability of type checking + +*Status: LANDED* (`+proofs/Tangle.lean+` §TG-2, lines 1399–1604). + +*Claim.* There is a total function `+infer : Expr → Option Ty+` such +that `+infer e = some τ ↔ HasType [] e τ+`. + +*What was proven.* - `+infer+` (line 1410) — total structural recursion +on `+Expr+`; covers all 26 `+HasType+` rules including the echo/product +fragment and let-binding. - `+infer_complete+` (line 1487) — +`+HasType Γ e τ → infer Γ e = some τ+`. - `+infer_sound+` (line 1493) — +`+infer Γ e = some τ → HasType Γ e τ+`. - `+infer_iff_hasType+` (line +1588) — the biconditional packaging both directions. - `+type_unique+` +(line 1593) — `+HasType Γ e τ₁ → HasType Γ e τ₂ → τ₁ = τ₂+` (follows +from `+infer_complete+` + `+infer_sound+`). - `+decidableHasType+` (line +1601) — `+Decidable (HasType [] e τ)+` instance via `+infer+`. + +*Assumptions discharged.* - [[A-TG-2.1]] ✓ — `+infer+` is defined by +structural recursion; Lean’s termination checker accepts it without any +additional annotation. - [[A-TG-2.2]] ✓ — `+Ty+` carries +`+deriving DecidableEq+`; `+Ty+` comparisons in `+infer+` use it +directly. + +==== TG-3 — OCaml impl refines the Lean spec + +*Status: LANDED* (2026-06-14, translation-validation level). Full +write-up: `+proofs/TG3-REFINEMENT.md+`. + +*Claim.* For every core-fragment `+e+` accepted by +`+compiler/lib/typecheck.ml+` with type `+τ+`, the Lean-level +proposition `+HasType [] e (T τ)+` holds (and conversely on rejection), +where `+T+` is the type translation +`+TNum↦num … TWord n↦word n, TEcho↦echo, TProd↦prod+`. + +*Why valuable.* Bridges the metatheory (Lean) to the implementation +(OCaml) — the two systems are now checked to be the same on the modelled +fragment. + +*How it was discharged.* 1. *Reduction (via TG-2).* +`+infer_iff_hasType+` gives `+infer ≡ HasType+`, so the claim becomes +"`OCaml `+infer_expr+` ≡ Lean `+infer+` on the core fragment`". 2. +*Closure proof.* `+infer_expr+` keeps core terms inside the translatable +types (never `+TTangle+`), under a strengthened _entire-type-tree_ IH. +`+close+` is the sole core gateway out of `+T+`’s domain and is +excluded. 3. *Machine-checked half.* `+proofs/TG3Differential.lean+` — +496 obligations `+infer [] e = T(infer_expr e) := by decide+`, generated +from the OCaml checker by `+compiler/test/tg3/tg3_emit.ml+`, verified by +`+proofs/check-tg3-differential.sh+`. 4. *OCaml half.* +`+compiler/test/tg3+` `+--check+`: 1008 `+dune runtest+` assertions +(closure invariant, curated pins, named→de Bruijn translation, +divergences). + +*Divergences (complete).* D1 `+close+` (`+Tangle[I,I]+` vs `+word 0+`) + +family D1b/c/d through pipeline/compose/add; D2 `+bool == bool+` (OCaml +accepts, Lean rejects). Both sides pinned. + +*Assumptions / boundary.* - [[A-TG-3.1]] The core OCaml AST/`+ty+` is in +bijection with the Lean AST/`+Ty+` under `+T+` (`+TTangle+` has no image +— handled by the closure proof). - Not claimed: a universal Lean theorem +over all OCaml runs (route 2 below); extra-core features are excluded, +not modelled; refinement is OCaml→Lean only. - Future route 2 (_airtight +refinement_): mechanise the OCaml algorithm in Lean and prove +equivalence to `+HasType+` — out of scope here (see §7 of +TG3-REFINEMENT.md). + +==== TG-4 — Pretty-print/parse round-trip + +*Status: LANDED* (PR #46). `+compiler/test/test_roundtrip.ml+` is a +26-entry corpus including all 8 echo/product constructors (52 round-trip +runs); the full suite is green (run `+dune runtest+` for the live +total). + +*Claim.* `+parse(pretty e) = e+` for every closed value `+e+`. + +*Why valuable.* Free fuzz oracle. Also the foundation of any "`IR +viewer`" tooling that re-parses what `+pretty+` emitted. + +*Assumptions.* - [[A-TG-4.1]] `+pretty.ml+`’s bracketing is unambiguous +w.r.t. the grammar. - [[A-TG-4.2]] Lexer never strips information needed +by the parser (e.g. whitespace within braid literals). + +*How to discharge.* Property test in `+compiler/test/+` — discharged. + +==== TG-5 — `+compositional.ml+` rewriter preserves types + +*Claim.* Every rewrite in `+compiler/lib/compositional.ml+` (418 LoC) +preserves typing: `+Γ ⊢ e : τ ∧ e ↝ e' ⟹ Γ ⊢ e' : τ+`. + +*Why valuable.* That file has zero test coverage (see [B6] in the bug +audit) and is a high-blast-radius refactor target. Type preservation is +the cheapest soundness contract. + +*Assumptions.* - [[A-TG-5.1]] Each rewrite is a function from `+Expr+` +to `+Expr+` — no in-place mutation. - [[A-TG-5.2]] No rewrite introduces +a new free variable. + +*How to discharge.* First, add a test file +(`+compiler/test/compositional_test.ml+`) covering each rewrite. Then +add Lean-level rewrite-preservation lemmas, one per rewrite, in a new +file `+proofs/Compositional.lean+` parameterised on `+Tangle.lean+`’s +`+HasType+`. + +==== TG-6 — WASM compilation preserves semantics + +*Claim.* For every closed well-typed `+e+`, the source-level evaluation +of `+e+` and the WASM execution of `+compile_to_wasm(e)+` agree on the +observable result. + +*Why valuable.* The _compiler correctness_ theorem. Warranted because +Tangle claims structural reasoning means _something_ on the runtime. +Without this, Tangle’s wasm backend is "`trust us, the structure +survives.`" + +*Assumptions.* - [[A-TG-6.1]] Standard WASM semantics (assumed; +specified by Wasm Cert / Wasm spec). - [[A-TG-6.2]] No floating-point +non-determinism in the source semantics (Tangle has only Int currently). + +*How to discharge.* Bisimulation between OCaml `+eval+` and the WASM +small-step. Heavy — this is the high-value research-paper-grade slice +(see typed-wasm proof debt in the estate). + +==== TG-7 — Braid-axiom equality in `+eqBraids+` + +*Claim.* `+Step.eqBraids+` should decide _braid-group equivalence_, not +list equivalence. I.e., `+σ_i σ_j σ_i = σ_j σ_i σ_j when |i-j|=1+` and +`+σ_i σ_j = σ_j σ_i when |i-j|≥2+` should be decidable in finite +generators. + +*Why valuable.* The README claims "`program equivalence is defined by +isotopy.`" Currently `+eqBraids+` only checks list equality, so +`+σ_1 σ_2 σ_1+` and `+σ_2 σ_1 σ_2+` are reported unequal. That’s the +trivial reading. + +*Status — LANDED 2026-07-29 (owner ruling #50), with a stated trusted +base.* `+==+` on braids now decides braid-group equivalence in both +engines: + +* *OCaml* — `+eval.ml+` `+Eq+` (and `+Isotopy+`, which for braids +denotes the _same_ relation) route through +`+compiler/lib/braid_equiv.ml+` (Dehornoy handle reduction). +`+Identity+` is `+VBraid []+`, so identity comparisons flow through the +same case. +* *Lean* — `+Step.eqBraids+` / `+eqIdBraid+` / `+eqBraidId+`, and the +three `+echoEq+` counterparts, use `+braidEquiv+` / `+isTrivialBraid+`: +a faithful in-Lean port of the same procedure, in §BRAID-GROUP +EQUIVALENCE of `+Tangle.lean+`. + +`+σ₁σ₂σ₁ == σ₂σ₁σ₂+` is now `+true+`, which is what the README’s +"`equivalence is defined by isotopy`" always claimed. Progress / +Preservation / Determinism were re-verified *unchanged* — all three need +only that the right-hand side is a _total function into `+Bool+`_, which +`+braidEquiv+` is; Determinism in particular is immediate, since a +function applied to fixed arguments yields a fixed result. + +____ +==== ⚠ TRUSTED, NOT PROVEN — the honest boundary + +`+braidEquiv+` is a *definition*, not an axiom: nothing is postulated, +and the sorry/axiom gate passes legitimately. But *the gate passing does +NOT mean this claim is proven.* What is established is that the +metatheory holds _relative to_ `+braidEquiv+`. What is *not* established +is that `+braidEquiv+` correctly *decides* braid-group equality — that +is the mechanised Garside/Dehornoy correctness proof, which remains +research-grade and out of scope (#51). + +Correctness is currently evidenced *by testing only*: +`+compiler/test/tg7+` (2220 assertions — defining relations, 400 +constructed-equivalent pairs, invariant-distinguished negatives) plus 8 +semantics-distinguishing cases in `+test_eval.ml+`. Testing is not +proof. + +Termination in the Lean port is by an explicit *fuel* bound mirroring +the OCaml `+max_steps+`, not by a well-founded measure. Dehornoy +reduction does terminate, but proving that _is_ the research obligation +above; fuel keeps the definitions total without smuggling in an unproven +termination claim. +____ + +*Assumptions.* - [[A-TG-7.1]] Word problem in the braid group is +solvable in polynomial time on finitely many strands (Birman–Ko–Lee / +Garside-normal-form algorithm — known true). - [[A-TG-7.2]] +`+braidEquiv+` (Lean) and `+braid_equiv.ml+` (OCaml) implement Dehornoy +handle reduction _correctly_, and agree with each other. Evidenced by +testing, not proof. *This is the load-bearing unproven assumption of +TG-7.* + +*How to discharge the remainder.* Mechanise the Dehornoy correctness +argument (or a Birman–Ko–Lee normal form) in Lean, prove +`+braidEquiv u v = true ↔ u ≡ v+` in the braid group, and prove +termination to replace the fuel bound. That retires [[A-TG-7.2]]. + +==== TG-8 — Dialect conservativity + +*Claim.* Each dialect under `+dialects/+` (`+braid-calculus+`, +`+quantum-circuit+`, `+skein-algebra+`, `+string-diagram+`, +`+virtual-knot+`) is a *conservative extension* of core Tangle: any core +program embedded into the dialect typechecks iff it typechecked in core. + +*Why valuable.* Lets dialect work proceed without re-proving safety each +time. Also stops dialect-introduced ambiguities from quietly weakening +core soundness. + +*Assumptions.* - [[A-TG-8.1]] Each dialect’s grammar is a strict +superset of core’s EBNF. - [[A-TG-8.2]] Each dialect’s typing rules are +_additive_ — they only add new constructors and their typing rules, +never modify existing ones. + +*How to discharge.* Per dialect: define `+HasType_dialect+` in Lean as +`+HasType+` plus new rules; prove embedding preservation. + +==== TG-9 — LSP diagnostics ⊆ `+HasType+` failures — *LANDED* + +*Claim.* Every diagnostic emitted by `+tangle-lsp+` corresponds to a +failure of the `+HasType+` judgment in `+Tangle.lean+`. (No LSP-only +diagnostics that the spec doesn’t reject.) + +*Why valuable.* Stops IDE drift from the language definition. Without +it, users get red squigglies in the editor for things that compile, or +vice versa. + +*How discharged (by construction, not by proof).* The audit found the +LSP was emitting several *LSP-only false positives* from a hand-rolled +lexical scan: it skipped `+--+` comments (Tangle uses `+#+` / +`+(* *)+`), counted delimiters inside string literals, incremented +block-depth on every `+def+` (firing "`unclosed block`" on every +multi-def file), and flagged function parameters as "`possibly +undefined`". None of these corresponded to a `+HasType+` failure. + +The refactor removes all hand-rolled diagnostics and routes the LSP +through the real compiler: - `+compiler/lib/check.ml+` +(`+check_source+`) is the single diagnostic source — parse-with-recovery ++ `+Typecheck.check_program+`. - `+tanglec --check+` exposes it as +`+SEVERITY⇥LINE⇥COL⇥MESSAGE+`. - `+tangle-lsp+` shells out to +`+tanglec --check+` and forwards exactly those diagnostics +(`+run_compiler_diagnostics+`); the lexical scan now only extracts +definitions/references for navigation. If the binary is absent it emits +nothing — `+∅ ⊆ HasType failures+`, never a false positive. + +So the subset relation holds _by construction_: the LSP cannot author a +diagnostic the compiler would not produce. + +*Evidence.* `+compiler/test/test_check.ml+` (the diagnostic source is +exactly parse + type failures) and `+tangle-lsp+`’s unit tests +(`+parse_check_line+`, `+analyze+` authors no diagnostics, and a gated +end-to-end delegation test against a real `+tanglec+`). + +*Locations.* Type errors scoped to a definition now carry that `+def+`’s +source line (`+def_line+`, threaded from the parser through +`+check_program+`), and the former duplicate diagnostic (pass 1b + pass +2 both reporting a def error) is removed. Statement-level errors +(assertions / computations / weave blocks) are not yet located and still +surface at the file top; column spans for expressions remain future +work. None of this affects the subset property — only where a diagnostic +points. + +=== 4. The "`stupid proof`" exclusions + +For completeness, we explicitly do *not* pursue: + +* _"``+Expr+` has exactly these constructors`"_ — enforced by the +inductive definition. +* _"`Compose is left-associative`"_ — surface syntax decision, not a +semantic claim. +* _"``+compile_to_wasm+` returns a Vec`"_ — Rust type assertion. +* _"``+generatorWidth (g :: gs) ≥ g.idx + 1+``"_ — implied by +T-WidthAppend +** cons semantics, no extra proof gains anything. + +=== 5. How to add a new obligation + +[arabic] +. Add a row to PROOF-NEEDS.md with `+TG-N+` id, category, prover, +priority, effort. +. Add the narrative entry here with statement, _why valuable_, status, +*assumptions*, _how to discharge_. Assumptions block is non-optional. +. Each new assumption gets an entry in ASSUMPTIONS.md with `+A-TG-N.M+` +id and MATH/DESIGN/EMPIRICAL/CRYPTO classification. + +=== 6. References + +* Implementation: link:compiler/lib/[`+compiler/lib/+`] (OCaml, 2649 +LoC). +* Formal core: link:proofs/Tangle.lean[`+proofs/Tangle.lean+`] (Lean 4, +560 LoC, all `+Qed+`). +* Spec: +link:docs/spec/FORMAL-SEMANTICS.md[`+docs/spec/FORMAL-SEMANTICS.md+`]. +* Decisions: +link:docs/spec/DECISIONS-LOCKED.md[`+docs/spec/DECISIONS-LOCKED.md+`]. +* Companion narratives: +** `+hyperpolymath/krl/PROOF-NARRATIVE.md+` — surface-language +obligations +** `+hyperpolymath/quandledb/PROOF-NARRATIVE.md+` — quandle / DB proofs diff --git a/PROOF-NARRATIVE.md b/PROOF-NARRATIVE.md deleted file mode 100644 index 87c5a1a..0000000 --- a/PROOF-NARRATIVE.md +++ /dev/null @@ -1,564 +0,0 @@ - -# Proof Narrative — Tangle - -This file is the **single coherent story** of what Tangle proves, what -it assumes, and what it has left to prove. - -For the per-obligation checklist with status/prover/effort, see -[PROOF-NEEDS.md](PROOF-NEEDS.md). -For the registry of every load-bearing unproven assumption, see -[ASSUMPTIONS.md](ASSUMPTIONS.md). - ---- - -## 1. Position in the stack - -Tangle is the **semantic core** of a four-layer federated stack: - -``` -┌─────────────────────────────────────────────────────────┐ -│ KRL surface language (hyperpolymath/krl) │ -└─────────────────┬───────────────────────────────────────┘ - │ lowers via KR-1, KR-2 to - ▼ -┌─────────────────────────────────────────────────────────┐ -│ TangleIR (canonical interchange obj) │ -└─────────────────┬───────────────────────────────────────┘ - │ has semantics via - ▼ -┌─────────────────────────────────────────────────────────┐ -│ Tangle CORE (THIS REPO) │ -│ proofs/Tangle.lean — mechanised results (26 HasType, 55 Step) │ -│ compiler/lib/*.ml — OCaml implementation │ -│ compiler/tangle-wasm — WASM backend │ -│ compiler/tangle-lsp — LSP server │ -│ dialects/ — braid-calculus, quantum-circuit, etc. │ -└─────────────────┬───────────────────────────────────────┘ - │ persisted/queried via - ▼ -┌─────────────────────────────────────────────────────────┐ -│ Skein.jl + QuandleDB │ -└─────────────────────────────────────────────────────────┘ -``` - -Consequence: **Tangle owes a real metatheory.** It owns the type -system that everyone above and below depends on. Tangle.lean already -delivers a substantial slice of this; this document makes the -delivered slice and the remaining gap explicit. - -## 2. Proven now - -All results live in [`proofs/Tangle.lean`](proofs/Tangle.lean) -(Lean 4, no `sorry`, no `axiom`). - -**Build oracle.** As of 2026-06-01 (PR closing TG-0, hyperpolymath/tangle#32), -the file is verified at every push/PR by `.github/workflows/lean-proofs.yml`, -pinned to `proofs/lean-toolchain = leanprover/lean4:v4.14.0`. Empirical -result on the original 2026-03-30 commit: 121 errors on every Lean 4 -version 4.9–4.16 — the file had never compiled. The current commit -returns **0 errors**, verified locally on v4.10/4.11/4.12/4.13/4.14/4.15/4.16, -with CI gating both `lean Tangle.lean` and a `sorry`/`axiom`/`admit` -slippage check. Future drift will fail CI rather than land silently. - -**Echo-types — now integrated as a type-system feature (2026-06-03).** -The earlier audit (`feedback_echo_types_audit_krl_tangle_quandledb_not_relevant.md`) -correctly found that the *external* echo-types Agda library -(hyperpolymath/echo-types) carries no lambda-calculus / progress / -preservation content of its own, so it does not perturb the four base -theorems. That verdict stands for the external library. **Tangle now -ships its own simply-typed shadow of echo-types as a first-class feature -of the type system** (`Ty.echo ρ τ`, constructors `echoClose`/`lower`/ -`residue`, rules `T-Echo-Close`/`T-Lower`/`T-Residue`). The motivation is -intrinsic to Tangle: `close : Word[n] → Word[0]` is the canonical lossy -map (the analogue of echo-types' `collapse : Bool → ⊤`), and the echo -layer makes that loss recoverable at the type level — the residue -`Word[n]` is retained and projected back out. Progress, Preservation, -Determinism, and Type Safety in `proofs/Tangle.lean` now **cover the echo -fragment**, and three capstone theorems (`echo_lower_collapses`, -`echo_residue_recovers`, `echo_distinguishes_collapsed`) reproduce -echo-types' `no-section` / `sigma-distinguishes` barrier inside Tangle. -See PROOF-NARRATIVE §2.5. - -### Theorems (the main results) - -| ID | Statement | Where | -|----|-----------|-------| -| **T-Progress** | Every well-typed closed term is either a value or can take a step. | `Tangle.lean:670` | -| **T-Preservation** | Stepping preserves types: `Γ ⊢ e : τ ∧ e → e' ⟹ Γ ⊢ e' : τ`. | `Tangle.lean:870` | -| **T-Determinism** | The step relation is deterministic: `e → e₁ ∧ e → e₂ ⟹ e₁ = e₂`. | `Tangle.lean:1053` | -| **T-TypeSafety** | Well-typed closed terms never get stuck (Progress + Preservation corollary). | `Tangle.lean:1303` | - -Each is proven for the **full core fragment**: numerals, strings, booleans, identity, -braid literals, composition, tensor, pipeline, close, addition, equality, variables, -let-binding, the complete echo/product fragment (see §2.5), and decidable type -inference (see §2.7). The "let-free fragment" caveat is retired — TG-1 and TG-2 are both landed. - -### Supporting lemmas - -| ID | Statement | Where | -|----|-----------|-------| -| T-ValueNoStep | Values are normal forms: `IsValue e ⟹ ¬ Step e e'`. | `Tangle.lean:394` | -| T-CanonicalNum | A typed-Num value is `.num n` for some `n`. | `Tangle.lean:405` | -| T-CanonicalStr | A typed-Str value is `.str s` for some `s`. | `Tangle.lean:409` | -| T-CanonicalWord | A typed-Word[n] value is `.identity` (n=0) or `.braidLit gs`. | `Tangle.lean:413` | -| T-CanonicalEcho | A typed-Echo value is `.echoVal r v` for values r, v. | `Tangle.lean:428` | -| T-CanonicalProd | A typed-Prod value is `.pair a b` for values a, b. | `Tangle.lean:443` | -| T-WidthAppend | `width(gs₁ ++ gs₂) = max(width gs₁, width gs₂)`. | `Tangle.lean:466` | -| T-WidthShift | `width(shift gs n) = if gs=[] then 0 else width gs + n`. | `Tangle.lean:485` | -| **T-Weakening** | Inserting a fresh hypothesis at de Bruijn position `Γ₁.length` preserves typing (TG-1). | `Tangle.lean:521` | -| **T-SubstPreserves** | Typing is preserved under capture-avoiding substitution of a typed term for a variable (TG-1). | `Tangle.lean:589` | - -### Type-system and step-relation definitions - -`Tangle.lean` also defines, as inductive types (so they are -themselves proofs of the form "these are the rules"): - -- **`Expr`** — the AST (mirrors `compiler/lib/ast.ml`) -- **`Ty`** — `num`, `str`, `bool`, `word n` -- **`IsValue`** — value predicate -- **`HasType`** — typing judgment, 26 rules: 13 base (`tNum`, `tStr`, `tBool`, - `tIdentity`, `tBraid`, `tComposeWord`, `tTensorWord`, `tPipeline`, - `tCloseWord`, `tAddNum`, `tEqWord`, `tEqNum`, `tEqStr`); 4 echo-close - (`tEchoClose`, `tLower`, `tResidue`, `tEchoVal`); 7 product+echo-binary - (`tPair`, `tFst`, `tSnd`, `tEchoAdd`, `tEchoEqWord`, `tEchoEqNum`, - `tEchoEqStr`); 2 let/var (`tVar`, `tLet`) -- **`Step`** — small-step semantics, 55 rules: 27 base, 9 echo-close/lower/residue, 6 product, 11 echoAdd/echoEq, 2 let (plus a separate 2-constructor `StepStar` reflexive-transitive closure: `refl`, `head`) - -These are the formal spec the OCaml implementation is meant to refine -(see TG-3 below). - -## 2.5 Echo types — structured loss as a type-system feature - -Echo types are integrated into the core type system (not a separate -layer). The design mirrors echo-types' fibre definition -`Echo f y := Σ (x : A), f x ≡ y` (hyperpolymath/echo-types, -`Echo.agda`) in Tangle's simply-typed setting, motivated by Tangle's own -canonical lossy operation. - -**Why `close`.** `close : Word[n] → Word[0]` collapses every braid word -to the identity, discarding the word — exactly the kind of -information-destroying map echo-types is about (cf. `collapse : Bool → ⊤` -in `EchoResidue.agda`). Echo types make that loss *recoverable in the -type system*. - -| Construct | Form | Echo-types analogue | -|-----------|------|---------------------| -| Type former | `Ty.echo ρ τ` — a `τ`-result carrying a `ρ`-residue | `Echo f y` (ρ = domain witness, τ = codomain point) | -| `echoClose e` | `Word[n] → Echo (Word[n]) (Word[0])` | `echo-intro close` | -| `lower e` | `Echo ρ τ → τ` — project to result (forget residue) | the collapse / `proj₂` | -| `residue e` | `Echo ρ τ → ρ` — recover the witness braid | `proj₁` | -| `pair(a, b)` | `α → β → α × β` — product introduction | `Echo.Pair` (product as residue carrier) | -| `fst(e)` | `α × β → α` — first projection | `proj₁` | -| `snd(e)` | `α × β → β` — second projection | `proj₂` | -| `echoAdd(a, b)` | `Num → Num → Echo (Num × Num) Num` — addition with summand residue | `echo-intro add` | -| `echoEq(a, b)` | `ρ → ρ → Echo (ρ × ρ) Bool` — equality with operand residue | `echo-intro eq` | - -**Metatheory.** Progress, Preservation, Determinism, and Type Safety all -cover `echoClose`/`lower`/`residue` (the inductions are exhaustive over -the extended `Step`/`HasType`). A new canonical-forms lemma -`canonical_echo` characterises echo values; `value_no_step` became -structurally recursive because a formed echo `echoClose v` is a value iff -its residue `v` is. - -**Capstone theorems** (the echo-types *content*, `Tangle.lean` §ECHO-TYPES): -- `echo_lower_collapses` — every closed braid lowers to `identity` - (the lossy step, re-derived through the echo). -- `echo_residue_recovers` — `residue (echoClose (braidLit gs)) ⟶ braidLit gs` - (the witness is retained; `close` becomes reversible). -- `echo_distinguishes_collapsed` — distinct braids collapse to the *same* - identity under `lower`, yet their residues stay distinct. This is the - Tangle instantiation of echo-types' non-injectivity barrier - (`collapse-residue-same` + `no-section-collapse-to-residue`). -- `echo_roundtrip_typed` — the round-trip is well-typed: `residue` returns - a `Word[n]`, `lower` returns a `Word[0]`. - -Tracked as obligation **TG-10** in PROOF-NEEDS.md (landed). - -## 2.6 OCaml implementation completeness - -As of 2026-06-14 (PRs #45–#46), the OCaml pipeline (`compiler/lib/`) covers the -complete echo + product fragment described in §2.5: - -| Layer | Echo/product coverage | -|-------|-----------------------| -| `ast.ml` | `EchoClose`, `Lower`, `Residue`, `Pair`, `Fst`, `Snd`, `EchoAdd`, `EchoEq` in `expr`; `TProd`, `TEcho` in `ty` | -| `typecheck.ml` | 8 `infer_expr` rules matching Lean `HasType`; `pp_ty` made `rec` | -| `eval.ml` | `VEcho`, `VPair` values; 8 `eval_expr` arms; `pp_value` made `rec` | -| `lexer.mll` / `parser.mly` / `token.ml` | Keyword tokens + grammar productions for all 8 surface forms | -| `pretty.ml` | Pretty-printers for all 8 forms | -| `test_roundtrip.ml` | TG-4 round-trip property test: 26-entry corpus including all 8 echo/product constructors | - -**Build oracle**: `dune build` + `dune test` green (run `dune runtest` for the -live count — ~597 across 8 suites). The -pre-PR #46 `main` did not compile due to two `Warning 8` exhaustiveness gaps -(both fixed: `strand_type_of_ty` in `typecheck.ml`; debug token printer in `bin/main.ml`). - -**TG-3 landed** (translation validation): the OCaml typechecker is proven to -refine `HasType` on the core fragment — `proofs/TG3Differential.lean` emits 496 -obligations generated from `infer_expr` that Lean's proven `infer` kernel-checks, -plus a closure proof and 1008 OCaml `--check` assertions. The two documented -divergences are `close` (D1) and `bool == bool` (D2). See `proofs/TG3-REFINEMENT.md` -and §TG-3 below. - -## 2.7 Let-binding and decidability (TG-1 + TG-2) - -Both obligations landed in `proofs/Tangle.lean` and are documented in §TG-1 and -§TG-2 of the remaining-obligations section below (those sections now carry LANDED -verdicts). Key structural points: - -- **TG-1 (let-binding)**: `weakening` + `subst_preserves` use the de Bruijn - combined-context invariant — `subst_preserves` types the substitutee in - `Γ₁ ++ Γ₂`, not merely `Γ₂`. This is the genuine inductive invariant; the - `letRed` consumer uses `Γ₁ := []` where both forms coincide. - -- **TG-2 (decidability)**: `infer` is a single structural recursion covering all - 26 `HasType` rules. Both soundness and completeness are proven; `type_unique` - follows as a corollary. The `decidableHasType` instance makes `HasType [] e τ` - a decidable proposition directly usable by Lean's typeclass system. - -## 2.8 Echo-types grade semiring — design note - -`hyperpolymath/echo-types` (commit `f7a965f`, 2026-06-14) added an experimental -ℕ∪{∞} min-plus grade semiring (`experimental/echo-additive/Grade.agda`) and a -variance gate (`VarianceGate.agda`). Key findings and their implications for Tangle: - -- The **combining direction** (`D_r(D_s A) → D_{r+s} A`) has **monadic** variance. - Tangle's `echoAdd`/`echoEq` use exactly this direction: two residues are merged - into a `pair` (the lax monoidal μ map). The current implementation is correct for - this reading. - -- The **splitting direction** (`D_{r+s} A → D_r(D_s A)`) has **comonadic** variance - and requires a full graded adjunction F_r ⊣ U_r. If Tangle ever needs to split an - `Echo(ρ×σ)` value back into independent `Echo(ρ)` and `Echo(σ)`, that is a - non-trivial structural addition — it cannot be derived from the combining map alone. - -- The **grade semiring** (`fin n` = information count, `inf` = total collapse) is a - candidate carrier for a future grade-indexed type former `Echo[n] ρ τ` in Tangle. - `echoAdd` would then have type `Num → Num → Echo[2] (Num×Num) Num` (2 units of - information retained). This is prospective; the experimental subtree is firewalled - until the comparative protocol (monadic vs comonadic) concludes. - -- **No Tangle design change is required now.** The current `Ty.echo`/`Ty.prod` - fragment is faithful to the monadic/combining direction and the experimental work - is explicitly gated (`experimental/echo-additive/` is not imported by any shipped - module in echo-types or Tangle). - -## 3. Remaining obligations (the narrative arc) - -What's not yet proven, why it matters, and what assumption each rests on. - -### TG-1 — Type safety extended to `let`-binding - -**Status: LANDED** (`proofs/Tangle.lean` §METATHEORY, lines 492–668). - -**Claim.** Type safety (Progress, Preservation, Determinism, TypeSafety) extends -to the full core language including `var` and `let`. - -**What was proven.** -- `weakening` (line 521) — inserting a fresh hypothesis `σ` at de Bruijn position - `Γ₁.length` preserves typing, with the term shifted by `shift 1 Γ₁.length`. -- `subst_preserves` (line 589) — typing is closed under replacing the variable at - `Γ₁.length` by a well-typed term `s`. The substitutee is typed in the combined - context `Γ₁ ++ Γ₂` (the genuine inductive invariant; the `letRed` consumer - instantiates `Γ₁ := []`). -- All four main theorems (Progress, Preservation, Determinism, TypeSafety) were - extended with `var` and `letStep`/`letRed` cases. `Step` gained `letStep` and - `letRed`; `HasType` gained `tVar` and `tLet`. - -**Implementation notes.** -- Variable lookup uses `List.getElem?` (not the deprecated `List.get?`); the - append splits go through `List.getElem?_append_left` / `_append_right`. -- Each derivation is taken apart with `cases h; rename_i` rather than - `cases h with | tCtor`, because under `induction e` the binder arguments - unify with the context and positional arm naming doesn't align. -- The `subst_preserves` combined-context invariant closes the `var = Γ₁.length` - case by `exact hs` with no separate shift-composition lemma needed. - -**Assumptions discharged.** -- [[A-TG-1.1]] ✓ — `subst` is defined by structural recursion on `Expr`, covering all 22 constructors. -- [[A-TG-1.2]] ✓ — `weakening` and `subst_preserves` both proven. - -### TG-2 — Decidability of type checking - -**Status: LANDED** (`proofs/Tangle.lean` §TG-2, lines 1399–1604). - -**Claim.** There is a total function `infer : Expr → Option Ty` such -that `infer e = some τ ↔ HasType [] e τ`. - -**What was proven.** -- `infer` (line 1410) — total structural recursion on `Expr`; covers all 26 `HasType` - rules including the echo/product fragment and let-binding. -- `infer_complete` (line 1487) — `HasType Γ e τ → infer Γ e = some τ`. -- `infer_sound` (line 1493) — `infer Γ e = some τ → HasType Γ e τ`. -- `infer_iff_hasType` (line 1588) — the biconditional packaging both directions. -- `type_unique` (line 1593) — `HasType Γ e τ₁ → HasType Γ e τ₂ → τ₁ = τ₂` (follows - from `infer_complete` + `infer_sound`). -- `decidableHasType` (line 1601) — `Decidable (HasType [] e τ)` instance via `infer`. - -**Assumptions discharged.** -- [[A-TG-2.1]] ✓ — `infer` is defined by structural recursion; Lean's termination - checker accepts it without any additional annotation. -- [[A-TG-2.2]] ✓ — `Ty` carries `deriving DecidableEq`; `Ty` comparisons in `infer` - use it directly. - -### TG-3 — OCaml impl refines the Lean spec - -**Status: LANDED** (2026-06-14, translation-validation level). Full write-up: -`proofs/TG3-REFINEMENT.md`. - -**Claim.** For every core-fragment `e` accepted by `compiler/lib/typecheck.ml` -with type `τ`, the Lean-level proposition `HasType [] e (T τ)` holds (and -conversely on rejection), where `T` is the type translation -`TNum↦num … TWord n↦word n, TEcho↦echo, TProd↦prod`. - -**Why valuable.** Bridges the metatheory (Lean) to the implementation (OCaml) — -the two systems are now checked to be the same on the modelled fragment. - -**How it was discharged.** -1. **Reduction (via TG-2).** `infer_iff_hasType` gives `infer ≡ HasType`, so the - claim becomes "OCaml `infer_expr` ≡ Lean `infer` on the core fragment". -2. **Closure proof.** `infer_expr` keeps core terms inside the translatable types - (never `TTangle`), under a strengthened *entire-type-tree* IH. `close` is the - sole core gateway out of `T`'s domain and is excluded. -3. **Machine-checked half.** `proofs/TG3Differential.lean` — 496 obligations - `infer [] e = T(infer_expr e) := by decide`, generated from the OCaml checker - by `compiler/test/tg3/tg3_emit.ml`, verified by `proofs/check-tg3-differential.sh`. -4. **OCaml half.** `compiler/test/tg3` `--check`: 1008 `dune runtest` assertions - (closure invariant, curated pins, named→de Bruijn translation, divergences). - -**Divergences (complete).** D1 `close` (`Tangle[I,I]` vs `word 0`) + family -D1b/c/d through pipeline/compose/add; D2 `bool == bool` (OCaml accepts, Lean -rejects). Both sides pinned. - -**Assumptions / boundary.** -- [[A-TG-3.1]] The core OCaml AST/`ty` is in bijection with the Lean AST/`Ty` - under `T` (`TTangle` has no image — handled by the closure proof). -- Not claimed: a universal Lean theorem over all OCaml runs (route 2 below); - extra-core features are excluded, not modelled; refinement is OCaml→Lean only. -- Future route 2 (_airtight refinement_): mechanise the OCaml algorithm in Lean - and prove equivalence to `HasType` — out of scope here (see §7 of TG3-REFINEMENT.md). - -### TG-4 — Pretty-print/parse round-trip - -**Status: LANDED** (PR #46). `compiler/test/test_roundtrip.ml` is a 26-entry -corpus including all 8 echo/product constructors (52 round-trip runs); the -full suite is green (run `dune runtest` for the live total). - -**Claim.** `parse(pretty e) = e` for every closed value `e`. - -**Why valuable.** Free fuzz oracle. Also the foundation of any "IR -viewer" tooling that re-parses what `pretty` emitted. - -**Assumptions.** -- [[A-TG-4.1]] `pretty.ml`'s bracketing is unambiguous w.r.t. the - grammar. -- [[A-TG-4.2]] Lexer never strips information needed by the parser - (e.g. whitespace within braid literals). - -**How to discharge.** Property test in `compiler/test/` — discharged. - -### TG-5 — `compositional.ml` rewriter preserves types - -**Claim.** Every rewrite in `compiler/lib/compositional.ml` (418 LoC) -preserves typing: `Γ ⊢ e : τ ∧ e ↝ e' ⟹ Γ ⊢ e' : τ`. - -**Why valuable.** That file has zero test coverage (see [B6] in the -bug audit) and is a high-blast-radius refactor target. Type -preservation is the cheapest soundness contract. - -**Assumptions.** -- [[A-TG-5.1]] Each rewrite is a function from `Expr` to `Expr` — - no in-place mutation. -- [[A-TG-5.2]] No rewrite introduces a new free variable. - -**How to discharge.** First, add a test file -(`compiler/test/compositional_test.ml`) covering each rewrite. -Then add Lean-level rewrite-preservation lemmas, one per rewrite, -in a new file `proofs/Compositional.lean` parameterised on -`Tangle.lean`'s `HasType`. - -### TG-6 — WASM compilation preserves semantics - -**Claim.** For every closed well-typed `e`, the source-level -evaluation of `e` and the WASM execution of `compile_to_wasm(e)` -agree on the observable result. - -**Why valuable.** The *compiler correctness* theorem. Warranted because -Tangle claims structural reasoning means *something* on the runtime. -Without this, Tangle's wasm backend is "trust us, the structure -survives." - -**Assumptions.** -- [[A-TG-6.1]] Standard WASM semantics (assumed; specified by Wasm - Cert / Wasm spec). -- [[A-TG-6.2]] No floating-point non-determinism in the source - semantics (Tangle has only Int currently). - -**How to discharge.** Bisimulation between OCaml `eval` and the WASM -small-step. Heavy — this is the high-value research-paper-grade slice -(see typed-wasm proof debt in the estate). - -### TG-7 — Braid-axiom equality in `eqBraids` - -**Claim.** `Step.eqBraids` should decide *braid-group equivalence*, -not list equivalence. I.e., `σ_i σ_j σ_i = σ_j σ_i σ_j when |i-j|=1` -and `σ_i σ_j = σ_j σ_i when |i-j|≥2` should be decidable in finite -generators. - -**Why valuable.** The README claims "program equivalence is defined -by isotopy." Currently `eqBraids` only checks list equality, so -`σ_1 σ_2 σ_1` and `σ_2 σ_1 σ_2` are reported unequal. That's the -trivial reading. - -**Status — LANDED 2026-07-29 (owner ruling #50), with a stated trusted base.** -`==` on braids now decides braid-group equivalence in both engines: - -- **OCaml** — `eval.ml` `Eq` (and `Isotopy`, which for braids denotes the - *same* relation) route through `compiler/lib/braid_equiv.ml` (Dehornoy - handle reduction). `Identity` is `VBraid []`, so identity comparisons flow - through the same case. -- **Lean** — `Step.eqBraids` / `eqIdBraid` / `eqBraidId`, and the three - `echoEq` counterparts, use `braidEquiv` / `isTrivialBraid`: a faithful - in-Lean port of the same procedure, in §BRAID-GROUP EQUIVALENCE of - `Tangle.lean`. - -`σ₁σ₂σ₁ == σ₂σ₁σ₂` is now `true`, which is what the README's "equivalence is -defined by isotopy" always claimed. Progress / Preservation / Determinism were -re-verified **unchanged** — all three need only that the right-hand side is a -*total function into `Bool`*, which `braidEquiv` is; Determinism in particular -is immediate, since a function applied to fixed arguments yields a fixed result. - -> ### ⚠ TRUSTED, NOT PROVEN — the honest boundary -> `braidEquiv` is a **definition**, not an axiom: nothing is postulated, and -> the sorry/axiom gate passes legitimately. But **the gate passing does NOT -> mean this claim is proven.** What is established is that the metatheory -> holds *relative to* `braidEquiv`. What is **not** established is that -> `braidEquiv` correctly **decides** braid-group equality — that is the -> mechanised Garside/Dehornoy correctness proof, which remains research-grade -> and out of scope (#51). -> -> Correctness is currently evidenced **by testing only**: `compiler/test/tg7` -> (2220 assertions — defining relations, 400 constructed-equivalent pairs, -> invariant-distinguished negatives) plus 8 semantics-distinguishing cases in -> `test_eval.ml`. Testing is not proof. -> -> Termination in the Lean port is by an explicit **fuel** bound mirroring the -> OCaml `max_steps`, not by a well-founded measure. Dehornoy reduction does -> terminate, but proving that *is* the research obligation above; fuel keeps -> the definitions total without smuggling in an unproven termination claim. - -**Assumptions.** -- [[A-TG-7.1]] Word problem in the braid group is solvable in - polynomial time on finitely many strands (Birman–Ko–Lee / - Garside-normal-form algorithm — known true). -- [[A-TG-7.2]] `braidEquiv` (Lean) and `braid_equiv.ml` (OCaml) implement - Dehornoy handle reduction *correctly*, and agree with each other. Evidenced - by testing, not proof. **This is the load-bearing unproven assumption of - TG-7.** - -**How to discharge the remainder.** Mechanise the Dehornoy correctness -argument (or a Birman–Ko–Lee normal form) in Lean, prove `braidEquiv u v = -true ↔ u ≡ v` in the braid group, and prove termination to replace the fuel -bound. That retires [[A-TG-7.2]]. - -### TG-8 — Dialect conservativity - -**Claim.** Each dialect under `dialects/` -(`braid-calculus`, `quantum-circuit`, `skein-algebra`, `string-diagram`, -`virtual-knot`) is a **conservative extension** of core Tangle: any -core program embedded into the dialect typechecks iff it typechecked -in core. - -**Why valuable.** Lets dialect work proceed without re-proving safety -each time. Also stops dialect-introduced ambiguities from quietly -weakening core soundness. - -**Assumptions.** -- [[A-TG-8.1]] Each dialect's grammar is a strict superset of core's - EBNF. -- [[A-TG-8.2]] Each dialect's typing rules are *additive* — they only - add new constructors and their typing rules, never modify existing - ones. - -**How to discharge.** Per dialect: define `HasType_dialect` in Lean as -`HasType` plus new rules; prove embedding preservation. - -### TG-9 — LSP diagnostics ⊆ `HasType` failures — **LANDED** - -**Claim.** Every diagnostic emitted by `tangle-lsp` corresponds to a -failure of the `HasType` judgment in `Tangle.lean`. (No -LSP-only diagnostics that the spec doesn't reject.) - -**Why valuable.** Stops IDE drift from the language definition. -Without it, users get red squigglies in the editor for things that -compile, or vice versa. - -**How discharged (by construction, not by proof).** The audit found the -LSP was emitting several **LSP-only false positives** from a hand-rolled -lexical scan: it skipped `--` comments (Tangle uses `#` / `(* *)`), -counted delimiters inside string literals, incremented block-depth on -every `def` (firing "unclosed block" on every multi-def file), and -flagged function parameters as "possibly undefined". None of these -corresponded to a `HasType` failure. - -The refactor removes all hand-rolled diagnostics and routes the LSP -through the real compiler: -- `compiler/lib/check.ml` (`check_source`) is the single diagnostic - source — parse-with-recovery + `Typecheck.check_program`. -- `tanglec --check` exposes it as `SEVERITY⇥LINE⇥COL⇥MESSAGE`. -- `tangle-lsp` shells out to `tanglec --check` and forwards exactly those - diagnostics (`run_compiler_diagnostics`); the lexical scan now only - extracts definitions/references for navigation. If the binary is - absent it emits nothing — `∅ ⊆ HasType failures`, never a false positive. - -So the subset relation holds *by construction*: the LSP cannot author a -diagnostic the compiler would not produce. - -**Evidence.** `compiler/test/test_check.ml` (the diagnostic source is -exactly parse + type failures) and `tangle-lsp`'s unit tests -(`parse_check_line`, `analyze` authors no diagnostics, and a gated -end-to-end delegation test against a real `tanglec`). - -**Locations.** Type errors scoped to a definition now carry that `def`'s -source line (`def_line`, threaded from the parser through `check_program`), -and the former duplicate diagnostic (pass 1b + pass 2 both reporting a def -error) is removed. Statement-level errors (assertions / computations / -weave blocks) are not yet located and still surface at the file top; column -spans for expressions remain future work. None of this affects the subset -property — only where a diagnostic points. - -## 4. The "stupid proof" exclusions - -For completeness, we explicitly do **not** pursue: - -- _"`Expr` has exactly these constructors"_ — enforced by the inductive - definition. -- _"Compose is left-associative"_ — surface syntax decision, not a - semantic claim. -- _"`compile_to_wasm` returns a Vec"_ — Rust type assertion. -- _"`generatorWidth (g :: gs) ≥ g.idx + 1`"_ — implied by T-WidthAppend - + cons semantics, no extra proof gains anything. - -## 5. How to add a new obligation - -1. Add a row to [PROOF-NEEDS.md](PROOF-NEEDS.md) with `TG-N` id, - category, prover, priority, effort. -2. Add the narrative entry here with statement, _why valuable_, - status, **assumptions**, _how to discharge_. Assumptions block - is non-optional. -3. Each new assumption gets an entry in [ASSUMPTIONS.md](ASSUMPTIONS.md) - with `A-TG-N.M` id and MATH/DESIGN/EMPIRICAL/CRYPTO classification. - -## 6. References - -- Implementation: [`compiler/lib/`](compiler/lib/) (OCaml, 2649 LoC). -- Formal core: [`proofs/Tangle.lean`](proofs/Tangle.lean) (Lean 4, - 560 LoC, all `Qed`). -- Spec: [`docs/spec/FORMAL-SEMANTICS.md`](docs/spec/FORMAL-SEMANTICS.md). -- Decisions: [`docs/spec/DECISIONS-LOCKED.md`](docs/spec/DECISIONS-LOCKED.md). -- Companion narratives: - - `hyperpolymath/krl/PROOF-NARRATIVE.md` — surface-language obligations - - `hyperpolymath/quandledb/PROOF-NARRATIVE.md` — quandle / DB proofs diff --git a/PROOF-NEEDS.adoc b/PROOF-NEEDS.adoc new file mode 100644 index 0000000..1e49c70 --- /dev/null +++ b/PROOF-NEEDS.adoc @@ -0,0 +1,372 @@ +== Proof Requirements — Tangle + +____ +Single coherent story: PROOF-NARRATIVE.md. Assumption registry: +ASSUMPTIONS.md. This file is the *per-obligation checklist*. +____ + +=== Proof tier + +*Tier:* T1 — Critical. Tangle owns the type system. KRL and QuandleDB +rest on Tangle’s metatheory. The core (including let-binding) has been +mechanised; the remaining gap is implementation-refinement and +WASM/dialect proofs. + +=== Current state + +* *LOC*: ~18,000 (OCaml + Rust + Tangle DSL + Lean proofs) +* *Languages*: OCaml (compiler), Rust (tangle-wasm), Lean 4 (proofs), +Tangle DSL (lib/stdlib + examples) +* *Existing mechanised proofs*: `+proofs/Tangle.lean+` (~1604 LoC, 22+ +results, all `+Qed+`) +* *Dangerous patterns*: None detected + +=== What is already proven + +Tracked in link:PROOF-NARRATIVE.md#2-proven-now[PROOF-NARRATIVE.md §2] +and `+proofs/Tangle.lean+`: + +[width="100%",cols="24%,47%,29%",options="header",] +|=== +|ID |Result |LoC +|T-Progress |Every well-typed closed term is a value or steps |~80 + +|T-Preservation |Stepping preserves types |~180 + +|T-Determinism |Step relation is deterministic |~250 + +|T-TypeSafety |Corollary: well-typed terms never get stuck |~3 + +|T-Weakening |Context insertion preserves typing (TG-1) |~70 + +|T-SubstPreserves |Substitution preserves typing (TG-1) |~100 + +|`+infer+` + `+infer_sound+`/`+infer_complete+`/`+infer_iff_hasType+` +|Algorithmic type inference ≡ HasType (TG-2) |~120 + +|`+type_unique+` + `+decidableHasType+` |Type uniqueness + Decidable +instance (TG-2) |~15 + +|+ canonical lemmas |canonical-num/str/word/echo/prod, value-no-step, +width-append/shift, echo capstones, echoAdd/echoEq capstones |~250 +|=== + +*Coverage:* the *full core fragment* of Tangle — `+Num+`, `+Str+`, +`+Bool+`, `+Identity+`, `+BraidLit+`, `+Compose+`, `+Tensor+`, +`+Pipeline+`, `+Close+`, `+Add+`, `+Eq+`, `+Var+`, `+Let+`, plus the +*echo-types fragment* (`+EchoClose+`, `+Lower+`, `+Residue+`, +`+EchoAdd+`, `+EchoEq+`) and the *product type* (`+Pair+`, `+Fst+`, +`+Snd+`). 26 typing rules, 55 step rules. All four theorems cover the +full fragment including let-binding (TG-1) and the echo/product fragment +(TG-10). Type checking is decidable (TG-2). + +=== What remains + +Cross-referenced to +link:PROOF-NARRATIVE.md#3-remaining-obligations-the-narrative-arc[PROOF-NARRATIVE.md +§3]. + +[width="100%",cols="9%,18%,17%,13%,17%,13%,13%",options="header",] +|=== +|# |Statement |Category |Prover |Priority |Effort |Status +|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+`) + +|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+`) + +|TG-3 |OCaml `+typecheck.ml+` refines the Lean `+HasType+` spec |TP +|Lean 4 + translation validation |P1 |— |*LANDED* +(translation-validation level — +link:proofs/TG3-REFINEMENT.md[`+proofs/TG3-REFINEMENT.md+`]). Reduced +via TG-2 (`+infer ≡ HasType+`) to "`OCaml `+infer_expr+` ≡ Lean +`+infer+` on the core fragment`", then discharged by: (a) a closure +proof (core fragment never yields `+TTangle+`, strengthened tree-IH); +(b) 496 Lean kernel-checked obligations in +link:proofs/TG3Differential.lean[`+proofs/TG3Differential.lean+`] +generated from `+infer_expr+` by `+compiler/test/tg3/tg3_emit.ml+` +(`+by decide+`; run `+proofs/check-tg3-differential.sh+`); (c) 1008 +OCaml `+--check+` assertions (`+dune runtest+`). Complete divergence +catalogue: *D1* `+close+` (OCaml `+Tangle[I,I]+` vs Lean `+word 0+` — +sole boundary gateway, + downstream D1b/c/d) and *D2* `+bool==bool+` +(OCaml accepts, Lean rejects). Extra-core feature list (model-later / +declare-non-core) in TG3-REFINEMENT §3. Not claimed: a universal Lean +proof over all OCaml runs (would require reflecting `+typecheck.ml+`); +refinement is OCaml→Lean only + +|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+`, 26-entry corpus including 8 +echo/product constructors; 52 round-trip runs) + +|TG-5 |`+compositional.ml+` (418 LoC) rewriter preserves types |TP +|OCaml property test |P2 |— |*LANDED* +(`+compiler/test/tg5/tg5_invariants.ml+`, 189 assertions in +`+dune runtest+`). compositional is below the Ty layer, so "`preserves +types`" = preserves the PD-lowering structural invariants + echo +residue-recovery: `+OpenWord+`/`+ClosedDiagram+`/`+EchoClosed+` each +pinned (closedness, `+\|crossings\|+`=unit-length, source unit-expanded, +*verbatim residue* for `+EchoClose+` with +`+expand(residue)=diagram word+` and echo-diagram pdv1-identical to +plain `+close+`), error paths, count pins. Lean IR model = optional +later rung + +|TG-6 |WASM compilation preserves semantics (source eval ≡ wasm exec) +|TP / ALG |differential + Lean bisimulation |P1 |— |*RUNG LANDED +(differential)*: `+compiler/tangle-wasm/tests/differential.rs+` EXECUTES +the generated wasm with the `+wasmi+` interpreter (dev-dep) and checks +the braid strand-permutation equals an independent reference model +(trefoil, non-commuting pairs, braid-relation pairs, 5-strand weave). +Validates codegen vs the permutation semantics; not a cross-binary diff +against `+eval.ml+`, and Markov helpers untested. Full source↔wasm +bisimulation (WasmCert) remains research-grade + +|TG-7 |`+Step.eqBraids+` decides braid-group equivalence (not list +equality) |ALG / DOM |OCaml + Lean 4 |P2 |— |*SEMANTICS LANDED +2026-07-29* (owner ruling #50 → (a) true braid-group equivalence). +`+==+` on braids now decides braid-group equality in BOTH engines: OCaml +`+eval.ml+` `+Eq+`/`+Isotopy+` route through +`+compiler/lib/braid_equiv.ml+`; Lean +`+Step.eqBraids+`/`+eqIdBraid+`/`+eqBraidId+` (and the three `+echoEq+` +counterparts) use `+braidEquiv+`, a faithful in-Lean port of the same +Dehornoy procedure. Progress/Preservation/Determinism re-verified +unchanged (they need only a total function into `+Bool+`). Tested: +`+compiler/test/tg7+` 2220 assertions + 8 new semantics-distinguishing +cases in `+test_eval.ml+`. *Remaining (research-grade): the mechanised +Garside/Dehornoy correctness proof — `+braidEquiv+` is TRUSTED, NOT +PROVEN; the Step relation is proven only RELATIVE to it* + +|TG-11 |Epistemic types: `+Epi[k, rho, tau]+` former + +`+warrant+`/`+epiVal+`/`+evidence+`, with +Progress/Preservation/Determinism/TypeSafety extended to cover them, and +NON-FACTIVITY established (no elimination delivers the claim) |TP / DOM +|Lean 4 |P1 |- |*LANDED*: `+proofs/Tangle.lean+` §EPISTEMIC. Six +capstones: `+epi_evidence_recovers+`, `+epi_claim_is_opaque+`, +`+epi_only_yields_evidence+`, `+epi_distinguishes_standpoints+`, +`+epi_roundtrip_typed+`, `+epi_over_echo_typed+`. Mirrors +`+hyperpolymath/epistemic-types+` (Warrant.agda / Base.agda / +EchoBridge.agda). TG-3 extended: 4 new pins, differential regenerated +and kernel-checked (496 obligations, 0 errors) + +|TG-8 |Each dialect (braid-calculus, quantum-circuit, skein-algebra, +string-diagram, virtual-knot) is a conservative extension of core |TP +|OCaml model + Lean per-dialect |P3 |— |*TEMPLATE LANDED +(virtual-knot)*: `+compiler/lib/dialect_vk.ml+` models VBₙ ⊃ Bₙ as core ++ a virtual layer that DELEGATES to `+Braid_equiv+` on the real +fragment, so conservativity holds by construction; `+compiler/test/tg8+` +(2311 assertions) verifies faithful embedding, core-delegation, +invariant agreement, proper extension, virtual involution, honest +undecided-frontier. Remaining: surface-syntax parser integration, the +other 4 dialects (replicate the template), and a Lean conservativity +proof + +|TG-9 |LSP diagnostics are a subset of `+HasType+` failures (no LSP-only +diagnostics) |INV |Audit + refactor |P2 |— |*LANDED* (`+tangle-lsp+` +delegates all diagnostics to `+tanglec --check+` ⇒ +`+compiler/lib/check.ml+`; hand-rolled LSP-only false positives removed. +Subset holds by construction. Tests: `+test_check.ml+` + tangle-lsp +unit/delegation tests) + +|TG-10 |Echo-types integrated into the type system: `+Echo[ρ,τ]+` former ++ `+echoClose+`/`+lower+`/`+residue+`/`+echoAdd+`/`+echoEq+` + product +type (`+pair+`/`+fst+`/`+snd+`), with +Progress/Preservation/Determinism/TypeSafety extended to cover them and +the non-injectivity / residue-recovery capstones proven |TP / DOM |Lean +4 |P1 |— |*LANDED* (`+proofs/Tangle.lean+` §ECHO-TYPES) +|=== + +For full per-obligation statements, _why valuable_, and the assumptions +each rests on, see PROOF-NARRATIVE.md. + +=== Scoping of the remaining obligations (2026-06-14) + +Concrete approach, effort, risk, and dependencies for what is left after +TG-0/1/2/3/4/5/9/10 landed. *Landable rungs of TG-6, TG-7, and TG-8 also +landed* (2026-06-14): TG-6 a `+wasmi+` differential test; TG-7 an +out-of-band `+braid_equiv+` checker; TG-8 a virtual-knot +conservative-extension template. What genuinely remains is +*research-grade*: TG-8’s _surface-syntax integration + other 4 dialects ++ Lean conservativity proof_; TG-6’s _full source↔wasm bisimulation_; +and TG-7’s _Lean correctness proof_. (TG-7’s *semantics change is no +longer owner-gated — it was ruled and landed 2026-07-29*, see #50 and +the TG-7 row above.) + +==== TG-3 — OCaml `+typecheck.ml+` refines Lean `+HasType+` — ✅ *LANDED 2026-06-14* + +* *Key lever (used):* TG-2 proves Lean `+infer ≡ HasType+`, so +refinement reduced to *OCaml `+infer_expr+` ≡ Lean `+infer+` on the +shared core fragment*. +* *Delivered:* (1) closure proof — the core fragment never yields +`+TTangle+` under `+infer_expr+` (strengthened _entire-type-tree_ IH; +`+close+` is the sole boundary gateway, excluded); (2) machine-checked +half — `+proofs/TG3Differential.lean+`, 496 obligations +`+infer [] e = := by decide+`, generated from the +OCaml checker by `+compiler/test/tg3/tg3_emit.ml+`, kernel-verified by +`+proofs/check-tg3-differential.sh+` (wired into `+lean-proofs.yml+`); +(3) OCaml side — 1008 `+dune runtest+` assertions (closure invariant, +curated pins, de Bruijn translation, divergence behaviours). Full +write-up + extra-core list + divergence catalogue: +`+proofs/TG3-REFINEMENT.md+`. +* *Divergences (complete):* D1 `+close+` (Tangle[I,I] vs word 0) + +family D1b/c/d; D2 `+bool==bool+` (OCaml accepts / Lean rejects). Both +pinned both sides. +* *Honest boundary:* translation validation over a broad corpus + a +structural argument — NOT a universal Lean theorem over all OCaml runs +(needs reflecting `+typecheck.ml+`). Extra-core features excluded, not +modelled. OCaml→Lean only. + +==== TG-5 — `+compositional.ml+` rewriter preserves types — ✅ *LANDED 2026-06-14* + +* *Delivered:* `+compiler/test/tg5/tg5_invariants.ml+` (189 assertions, +in `+dune runtest+`). compositional has no `+Ty+`; "`preserves types`" +is realised as preserving the PD-lowering structural invariants + the +echo residue-recovery property. Per-variant pins: `+OpenWord+` +unit-expanded; `+ClosedDiagram+` closed/`+components=[]+`/source +unit-expanded/`+|crossings|=|source|=unit-count+`; `+EchoClosed+` +residue *verbatim* (exponents preserved, e.g. `+echoClose(s1^3)+` keeps +`+[s1^3]+` while the diagram is the 3-crossing unit closure), +`+expand(residue)=diagram word+`, and echo-diagram pdv1-identical to +plain `+close+`. Plus error-path message pins and concrete +crossing-count pins. +* *Honest boundary:* asserts ONLY invariants the lowering guarantees — +NOT arc balance, planarity, or crossing-index validity (the code makes +no such claim). A Lean model of the PD IR + a mechanised preservation +theorem is an optional later rung (Lean currently has no planar-diagram +type). + +==== TG-7 — `+eqBraids+` decides braid-group equivalence — 🟡 *RUNG LANDED, semantics OWNER-GATED* + +* ✅ *Non-semantic rung landed 2026-06-14*: +`+compiler/lib/braid_equiv.ml+` (`+equiv+`/`+is_trivial+`) decides +braid-group equivalence via Dehornoy handle reduction, _out-of-band_ — +`+==+` / `+Step.eqBraids+` are untouched. Validated by +`+compiler/test/tg7/tg7_braid_equiv.ml+` (2220 assertions): the defining +relations, 400 constructed-equivalent pairs (writhe/permutation +invariants guard the generator), and invariant-distinguished negatives. +Correctness is by-testing; a Lean Garside/Dehornoy proof is the +research-grade rung. +* The only `+eqBraids+` is the Lean `+Step+` rule +`+eq (braidLit gs₁) (braidLit gs₂) → boolLit (gs₁ == gs₂)+` = *list +equality*; OCaml `+eval.ml+` matches it. +* Moving to Dehornoy handle reduction would *change the observable +semantics of `+==+` on braids* (terms group-equal but not list-equal +would newly compare true) on BOTH the OCaml evaluator AND the Lean +`+Step+` relation, rippling into the Determinism/Preservation proofs. +*This is a language-design decision, not just a proof — it must not be +auto-landed.* +* *Owner decision needed:* (a) change `+==+` semantics to braid-group +equivalence, or (b) keep `+==+` as-is and add an _out-of-band_ +`+braid_equiv+` checker (Dehornoy/BKL normal form) that does NOT touch +`+==+`. The smallest non-semantic step is (b): an OCaml +`+braid_equiv : gen list -> gen list -> bool+` with tests, no semantic +change. Lean correctness (Garside/Dehornoy) remains research-grade +either way. + +==== TG-8 — each dialect is a conservative extension of core — 🟡 *TEMPLATE LANDED (virtual-knot)* + +* ✅ *Conservativity template landed 2026-06-14*: +`+compiler/lib/dialect_vk.ml+` models the virtual-knot dialect (VBₙ ⊃ Bₙ +— braids plus involutive virtual crossings) as *core + a virtual layer +that delegates to `+Braid_equiv+` (TG-7) on the real fragment*, so +conservativity holds _by construction_ (the dialect cannot change core +typing/semantics). `+compiler/test/tg8/tg8_conservativity.ml+` (2311 +assertions) verifies: faithful embedding (`+project∘embed=id+`); the +dialect decides core terms exactly as the core procedure; invariant +agreement (permutation/writhe); proper extension (a virtual crossing is +a genuinely-new non-real element; vᵢvᵢ=ε); and an honest +undecided-frontier (irreducible mixed virtual content is reported +`+None+`, never guessed). +* *Honest scope:* this is the dialect’s semantic core + conservativity +bridge, built as a separate module (no core-AST/Lean-oracle edits, +avoiding the `+Warning 8+` cascade). It is NOT yet a surface-syntax +parser integration, and VBₙ equivalence is a sound _partial_ decider +(full VBₙ word problem is research-grade). +* *Remaining:* surface syntax (`+lexer+`/`+parser+`/`+ast+`/`+eval+`); +replicate the template to the other four dialects; a mechanised Lean +conservativity proof. + +==== TG-6 — WASM compilation preserves semantics — 🟡 *RUNG LANDED (differential)* + +* ✅ *Differential rung landed 2026-06-14*: +`+compiler/tangle-wasm/tests/differential.rs+` adds `+wasmi+` (pure-Rust +interpreter) as a dev-dependency, EXECUTES the generated wasm modules +with reference host primitives (`+alloc_strands+` = identity init, +`+swap_strands+` = cell swap), and checks the resulting strand +permutation equals an independent in-Rust reference model — over +trefoil, non-commuting pairs (`+s1s2+` ≠ `+s2s1+`), braid-relation pairs +(`+s1s2s1+` = `+s2s1s2+`), and a 5-strand weave. Runs via +`+cargo test+`. +* *Honest scope:* validates the _codegen_ against the permutation +semantics (catches wrong crossing indices / call order / strand count / +non-instantiable modules); it is NOT a cross-binary diff against +`+compiler/lib/eval.ml+`, and the Markov-move helpers are not yet +exercised. +* *Remaining (research-grade):* a full source↔wasm bisimulation proof +(WasmCert / Wasm-spec); and, if desired, a true cross-binary +differential that drives `+eval.ml+` and the wasm over a shared corpus. + +=== Proof categories + +[width="100%",cols="24%,36%,40%",options="header",] +|=== +|Code |Meaning |Applies? +|*TP* |Typing proofs |Yes +|*INV* |Invariant proofs (round-trip, LSP discipline) |Yes +|*SEC* |Security proofs |No +|*CONC* |Concurrency proofs |No +|*ALG* |Algorithm proofs (decidability, eqBraids, WASM compile) |Yes +|*ABI* |ABI/FFI proofs |Out of scope (compiler-internal) +|*DOM* |Domain proofs (braid-group, isotopy) |Yes +|=== + +=== Dangerous patterns (BANNED) + +CI rejects any PR introducing these: + +[cols=",,",options="header",] +|=== +|Pattern |Language |Meaning +|`+believe_me+` |Idris2 |Unsafe cast +|`+assert_total+` |Idris2 |Skip totality check +|`+postulate+` |Idris2 / Agda |Unproven axiom +|`+sorry+` |Lean 4 |Incomplete proof +|`+axiom+` (project-level) |Lean 4 |Unproven postulate +|`+Admitted+` |Coq |Incomplete proof +|`+unsafeCoerce+` |Haskell |Unsafe cast +|`+Obj.magic+` |OCaml |Unsafe cast +|`+unsafe+` (unaudited) |Rust |Unsafe block without safety comment +|=== + +Enforced by `+panic-attack assail --proofs-only+`. + +=== Recommended prover + +* *Lean 4* for the core metatheory (already chosen; +`+proofs/Tangle.lean+`). +* *Lean 4* for `+infer+`-decidability and +`+compositional+`-preservation. +* *Lean 4 + Wasm-spec / WasmCert* for WASM compilation correctness. + +=== Template ABI cleanup (2026-03-29) + +Template ABI files (Idris2 `+Types.idr+`, `+Layout.idr+`, +`+Foreign.idr+`) were removed in March 2026 — they contained only RSR +template scaffolding with unresolved placeholders and no domain-specific +proofs. This decision still stands; ABI proofs are out of scope here +(Tangle is compiler-internal; the FFI boundary is in KRL’s repo). + +=== References + +* Implementation: link:compiler/lib/[`+compiler/lib/+`], +link:compiler/tangle-wasm/[`+compiler/tangle-wasm/+`], +link:compiler/tangle-lsp/[`+compiler/tangle-lsp/+`]. +* Formal core: link:proofs/Tangle.lean[`+proofs/Tangle.lean+`]. +* Spec: +link:docs/spec/FORMAL-SEMANTICS.md[`+docs/spec/FORMAL-SEMANTICS.md+`]. +* Companion narratives: `+hyperpolymath/krl/PROOF-NARRATIVE.md+`, +`+hyperpolymath/quandledb/PROOF-NARRATIVE.md+`. diff --git a/PROOF-NEEDS.md b/PROOF-NEEDS.md deleted file mode 100644 index eaa19f8..0000000 --- a/PROOF-NEEDS.md +++ /dev/null @@ -1,224 +0,0 @@ - -# Proof Requirements — Tangle - -> Single coherent story: [PROOF-NARRATIVE.md](PROOF-NARRATIVE.md). -> Assumption registry: [ASSUMPTIONS.md](ASSUMPTIONS.md). -> This file is the **per-obligation checklist**. - -## Proof tier - -**Tier:** T1 — Critical. -Tangle owns the type system. KRL and QuandleDB rest on Tangle's -metatheory. The core (including let-binding) has been mechanised; the remaining gap is implementation-refinement and WASM/dialect proofs. - -## Current state - -- **LOC**: ~18,000 (OCaml + Rust + Tangle DSL + Lean proofs) -- **Languages**: OCaml (compiler), Rust (tangle-wasm), Lean 4 (proofs), - Tangle DSL (lib/stdlib + examples) -- **Existing mechanised proofs**: `proofs/Tangle.lean` (~1604 LoC, 22+ - results, all `Qed`) -- **Dangerous patterns**: None detected - -## What is already proven - -Tracked in [PROOF-NARRATIVE.md §2](PROOF-NARRATIVE.md#2-proven-now) -and `proofs/Tangle.lean`: - -| ID | Result | LoC | -|----|--------|-----| -| T-Progress | Every well-typed closed term is a value or steps | ~80 | -| T-Preservation | Stepping preserves types | ~180 | -| T-Determinism | Step relation is deterministic | ~250 | -| T-TypeSafety | Corollary: well-typed terms never get stuck | ~3 | -| T-Weakening | Context insertion preserves typing (TG-1) | ~70 | -| T-SubstPreserves | Substitution preserves typing (TG-1) | ~100 | -| `infer` + `infer_sound`/`infer_complete`/`infer_iff_hasType` | Algorithmic type inference ≡ HasType (TG-2) | ~120 | -| `type_unique` + `decidableHasType` | Type uniqueness + Decidable instance (TG-2) | ~15 | -| + canonical lemmas | canonical-num/str/word/echo/prod, value-no-step, width-append/shift, echo capstones, echoAdd/echoEq capstones | ~250 | - -**Coverage:** the **full core fragment** of Tangle — `Num`, `Str`, `Bool`, `Identity`, -`BraidLit`, `Compose`, `Tensor`, `Pipeline`, `Close`, `Add`, `Eq`, `Var`, `Let`, -plus the **echo-types fragment** (`EchoClose`, `Lower`, `Residue`, `EchoAdd`, -`EchoEq`) and the **product type** (`Pair`, `Fst`, `Snd`). 26 typing rules, -55 step rules. All four theorems cover the full fragment including let-binding (TG-1) -and the echo/product fragment (TG-10). Type checking is decidable (TG-2). - -## What remains - -Cross-referenced to [PROOF-NARRATIVE.md §3](PROOF-NARRATIVE.md#3-remaining-obligations-the-narrative-arc). - -| # | Statement | Category | Prover | Priority | Effort | Status | -|---|-----------|----------|--------|----------|--------|--------| -| 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`) | -| 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`) | -| TG-3 | OCaml `typecheck.ml` refines the Lean `HasType` spec | TP | Lean 4 + translation validation | P1 | — | **LANDED** (translation-validation level — [`proofs/TG3-REFINEMENT.md`](proofs/TG3-REFINEMENT.md)). Reduced via TG-2 (`infer ≡ HasType`) to "OCaml `infer_expr` ≡ Lean `infer` on the core fragment", then discharged by: (a) a closure proof (core fragment never yields `TTangle`, strengthened tree-IH); (b) 496 Lean kernel-checked obligations in [`proofs/TG3Differential.lean`](proofs/TG3Differential.lean) generated from `infer_expr` by `compiler/test/tg3/tg3_emit.ml` (`by decide`; run `proofs/check-tg3-differential.sh`); (c) 1008 OCaml `--check` assertions (`dune runtest`). Complete divergence catalogue: **D1** `close` (OCaml `Tangle[I,I]` vs Lean `word 0` — sole boundary gateway, + downstream D1b/c/d) and **D2** `bool==bool` (OCaml accepts, Lean rejects). Extra-core feature list (model-later / declare-non-core) in TG3-REFINEMENT §3. Not claimed: a universal Lean proof over all OCaml runs (would require reflecting `typecheck.ml`); refinement is OCaml→Lean only | -| 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`, 26-entry corpus including 8 echo/product constructors; 52 round-trip runs) | -| TG-5 | `compositional.ml` (418 LoC) rewriter preserves types | TP | OCaml property test | P2 | — | **LANDED** (`compiler/test/tg5/tg5_invariants.ml`, 189 assertions in `dune runtest`). compositional is below the Ty layer, so "preserves types" = preserves the PD-lowering structural invariants + echo residue-recovery: `OpenWord`/`ClosedDiagram`/`EchoClosed` each pinned (closedness, `\|crossings\|`=unit-length, source unit-expanded, **verbatim residue** for `EchoClose` with `expand(residue)=diagram word` and echo-diagram pdv1-identical to plain `close`), error paths, count pins. Lean IR model = optional later rung | -| TG-6 | WASM compilation preserves semantics (source eval ≡ wasm exec) | TP / ALG | differential + Lean bisimulation | P1 | — | **RUNG LANDED (differential)**: `compiler/tangle-wasm/tests/differential.rs` EXECUTES the generated wasm with the `wasmi` interpreter (dev-dep) and checks the braid strand-permutation equals an independent reference model (trefoil, non-commuting pairs, braid-relation pairs, 5-strand weave). Validates codegen vs the permutation semantics; not a cross-binary diff against `eval.ml`, and Markov helpers untested. Full source↔wasm bisimulation (WasmCert) remains research-grade | -| TG-7 | `Step.eqBraids` decides braid-group equivalence (not list equality) | ALG / DOM | OCaml + Lean 4 | P2 | — | **SEMANTICS LANDED 2026-07-29** (owner ruling #50 → (a) true braid-group equivalence). `==` on braids now decides braid-group equality in BOTH engines: OCaml `eval.ml` `Eq`/`Isotopy` route through `compiler/lib/braid_equiv.ml`; Lean `Step.eqBraids`/`eqIdBraid`/`eqBraidId` (and the three `echoEq` counterparts) use `braidEquiv`, a faithful in-Lean port of the same Dehornoy procedure. Progress/Preservation/Determinism re-verified unchanged (they need only a total function into `Bool`). Tested: `compiler/test/tg7` 2220 assertions + 8 new semantics-distinguishing cases in `test_eval.ml`. **Remaining (research-grade): the mechanised Garside/Dehornoy correctness proof — `braidEquiv` is TRUSTED, NOT PROVEN; the Step relation is proven only RELATIVE to it** | -| TG-11 | Epistemic types: `Epi[k, rho, tau]` former + `warrant`/`epiVal`/`evidence`, with Progress/Preservation/Determinism/TypeSafety extended to cover them, and NON-FACTIVITY established (no elimination delivers the claim) | TP / DOM | Lean 4 | P1 | - | **LANDED**: `proofs/Tangle.lean` §EPISTEMIC. Six capstones: `epi_evidence_recovers`, `epi_claim_is_opaque`, `epi_only_yields_evidence`, `epi_distinguishes_standpoints`, `epi_roundtrip_typed`, `epi_over_echo_typed`. Mirrors `hyperpolymath/epistemic-types` (Warrant.agda / Base.agda / EchoBridge.agda). TG-3 extended: 4 new pins, differential regenerated and kernel-checked (496 obligations, 0 errors) | -| TG-8 | Each dialect (braid-calculus, quantum-circuit, skein-algebra, string-diagram, virtual-knot) is a conservative extension of core | TP | OCaml model + Lean per-dialect | P3 | — | **TEMPLATE LANDED (virtual-knot)**: `compiler/lib/dialect_vk.ml` models VBₙ ⊃ Bₙ as core + a virtual layer that DELEGATES to `Braid_equiv` on the real fragment, so conservativity holds by construction; `compiler/test/tg8` (2311 assertions) verifies faithful embedding, core-delegation, invariant agreement, proper extension, virtual involution, honest undecided-frontier. Remaining: surface-syntax parser integration, the other 4 dialects (replicate the template), and a Lean conservativity proof | -| TG-9 | LSP diagnostics are a subset of `HasType` failures (no LSP-only diagnostics) | INV | Audit + refactor | P2 | — | **LANDED** (`tangle-lsp` delegates all diagnostics to `tanglec --check` ⇒ `compiler/lib/check.ml`; hand-rolled LSP-only false positives removed. Subset holds by construction. Tests: `test_check.ml` + tangle-lsp unit/delegation tests) | -| TG-10 | Echo-types integrated into the type system: `Echo[ρ,τ]` former + `echoClose`/`lower`/`residue`/`echoAdd`/`echoEq` + product type (`pair`/`fst`/`snd`), with Progress/Preservation/Determinism/TypeSafety extended to cover them and the non-injectivity / residue-recovery capstones proven | TP / DOM | Lean 4 | P1 | — | **LANDED** (`proofs/Tangle.lean` §ECHO-TYPES) | - -For full per-obligation statements, _why valuable_, and the -assumptions each rests on, see PROOF-NARRATIVE.md. - -## Scoping of the remaining obligations (2026-06-14) - -Concrete approach, effort, risk, and dependencies for what is left after -TG-0/1/2/3/4/5/9/10 landed. **Landable rungs of TG-6, TG-7, and TG-8 also -landed** (2026-06-14): TG-6 a `wasmi` differential test; TG-7 an out-of-band -`braid_equiv` checker; TG-8 a virtual-knot conservative-extension template. What -genuinely remains is **research-grade**: TG-8's *surface-syntax integration + -other 4 dialects + Lean conservativity proof*; TG-6's *full source↔wasm -bisimulation*; and TG-7's *Lean correctness proof*. (TG-7's **semantics -change is no longer owner-gated — it was ruled and landed 2026-07-29**, see -#50 and the TG-7 row above.) - -### TG-3 — OCaml `typecheck.ml` refines Lean `HasType` — ✅ **LANDED 2026-06-14** -- **Key lever (used):** TG-2 proves Lean `infer ≡ HasType`, so refinement - reduced to **OCaml `infer_expr` ≡ Lean `infer` on the shared core fragment**. -- **Delivered:** (1) closure proof — the core fragment never yields `TTangle` - under `infer_expr` (strengthened *entire-type-tree* IH; `close` is the sole - boundary gateway, excluded); (2) machine-checked half — `proofs/TG3Differential.lean`, - 496 obligations `infer [] e = := by decide`, generated from - the OCaml checker by `compiler/test/tg3/tg3_emit.ml`, kernel-verified by - `proofs/check-tg3-differential.sh` (wired into `lean-proofs.yml`); (3) OCaml - side — 1008 `dune runtest` assertions (closure invariant, curated pins, de - Bruijn translation, divergence behaviours). Full write-up + extra-core list + - divergence catalogue: `proofs/TG3-REFINEMENT.md`. -- **Divergences (complete):** D1 `close` (Tangle[I,I] vs word 0) + family - D1b/c/d; D2 `bool==bool` (OCaml accepts / Lean rejects). Both pinned both sides. -- **Honest boundary:** translation validation over a broad corpus + a structural - argument — NOT a universal Lean theorem over all OCaml runs (needs reflecting - `typecheck.ml`). Extra-core features excluded, not modelled. OCaml→Lean only. - -### TG-5 — `compositional.ml` rewriter preserves types — ✅ **LANDED 2026-06-14** -- **Delivered:** `compiler/test/tg5/tg5_invariants.ml` (189 assertions, in - `dune runtest`). compositional has no `Ty`; "preserves types" is realised as - preserving the PD-lowering structural invariants + the echo residue-recovery - property. Per-variant pins: `OpenWord` unit-expanded; `ClosedDiagram` - closed/`components=[]`/source unit-expanded/`|crossings|=|source|=unit-count`; - `EchoClosed` residue **verbatim** (exponents preserved, e.g. `echoClose(s1^3)` - keeps `[s1^3]` while the diagram is the 3-crossing unit closure), - `expand(residue)=diagram word`, and echo-diagram pdv1-identical to plain - `close`. Plus error-path message pins and concrete crossing-count pins. -- **Honest boundary:** asserts ONLY invariants the lowering guarantees — NOT arc - balance, planarity, or crossing-index validity (the code makes no such claim). - A Lean model of the PD IR + a mechanised preservation theorem is an optional - later rung (Lean currently has no planar-diagram type). - -### TG-7 — `eqBraids` decides braid-group equivalence — 🟡 **RUNG LANDED, semantics OWNER-GATED** -- ✅ **Non-semantic rung landed 2026-06-14**: `compiler/lib/braid_equiv.ml` - (`equiv`/`is_trivial`) decides braid-group equivalence via Dehornoy handle - reduction, *out-of-band* — `==` / `Step.eqBraids` are untouched. Validated by - `compiler/test/tg7/tg7_braid_equiv.ml` (2220 assertions): the defining - relations, 400 constructed-equivalent pairs (writhe/permutation invariants - guard the generator), and invariant-distinguished negatives. Correctness is - by-testing; a Lean Garside/Dehornoy proof is the research-grade rung. -- The only `eqBraids` is the Lean `Step` rule `eq (braidLit gs₁) (braidLit gs₂) - → boolLit (gs₁ == gs₂)` = **list equality**; OCaml `eval.ml` matches it. -- Moving to Dehornoy handle reduction would **change the observable semantics of - `==` on braids** (terms group-equal but not list-equal would newly compare - true) on BOTH the OCaml evaluator AND the Lean `Step` relation, rippling into - the Determinism/Preservation proofs. **This is a language-design decision, not - just a proof — it must not be auto-landed.** -- **Owner decision needed:** (a) change `==` semantics to braid-group - equivalence, or (b) keep `==` as-is and add an *out-of-band* `braid_equiv` - checker (Dehornoy/BKL normal form) that does NOT touch `==`. The smallest - non-semantic step is (b): an OCaml `braid_equiv : gen list -> gen list -> bool` - with tests, no semantic change. Lean correctness (Garside/Dehornoy) remains - research-grade either way. - -### TG-8 — each dialect is a conservative extension of core — 🟡 **TEMPLATE LANDED (virtual-knot)** -- ✅ **Conservativity template landed 2026-06-14**: `compiler/lib/dialect_vk.ml` - models the virtual-knot dialect (VBₙ ⊃ Bₙ — braids plus involutive virtual - crossings) as **core + a virtual layer that delegates to `Braid_equiv` (TG-7) - on the real fragment**, so conservativity holds *by construction* (the dialect - cannot change core typing/semantics). `compiler/test/tg8/tg8_conservativity.ml` - (2311 assertions) verifies: faithful embedding (`project∘embed=id`); the dialect - decides core terms exactly as the core procedure; invariant agreement - (permutation/writhe); proper extension (a virtual crossing is a genuinely-new - non-real element; vᵢvᵢ=ε); and an honest undecided-frontier (irreducible mixed - virtual content is reported `None`, never guessed). -- **Honest scope:** this is the dialect's semantic core + conservativity bridge, - built as a separate module (no core-AST/Lean-oracle edits, avoiding the - `Warning 8` cascade). It is NOT yet a surface-syntax parser integration, and - VBₙ equivalence is a sound *partial* decider (full VBₙ word problem is - research-grade). -- **Remaining:** surface syntax (`lexer`/`parser`/`ast`/`eval`); replicate the - template to the other four dialects; a mechanised Lean conservativity proof. - -### TG-6 — WASM compilation preserves semantics — 🟡 **RUNG LANDED (differential)** -- ✅ **Differential rung landed 2026-06-14**: `compiler/tangle-wasm/tests/differential.rs` - adds `wasmi` (pure-Rust interpreter) as a dev-dependency, EXECUTES the - generated wasm modules with reference host primitives (`alloc_strands` = - identity init, `swap_strands` = cell swap), and checks the resulting strand - permutation equals an independent in-Rust reference model — over trefoil, - non-commuting pairs (`s1s2` ≠ `s2s1`), braid-relation pairs (`s1s2s1` = - `s2s1s2`), and a 5-strand weave. Runs via `cargo test`. -- **Honest scope:** validates the *codegen* against the permutation semantics - (catches wrong crossing indices / call order / strand count / non-instantiable - modules); it is NOT a cross-binary diff against `compiler/lib/eval.ml`, and the - Markov-move helpers are not yet exercised. -- **Remaining (research-grade):** a full source↔wasm bisimulation proof - (WasmCert / Wasm-spec); and, if desired, a true cross-binary differential that - drives `eval.ml` and the wasm over a shared corpus. - -## Proof categories - -| Code | Meaning | Applies? | -|------|---------|----------| -| **TP** | Typing proofs | Yes | -| **INV** | Invariant proofs (round-trip, LSP discipline) | Yes | -| **SEC** | Security proofs | No | -| **CONC** | Concurrency proofs | No | -| **ALG** | Algorithm proofs (decidability, eqBraids, WASM compile) | Yes | -| **ABI** | ABI/FFI proofs | Out of scope (compiler-internal) | -| **DOM** | Domain proofs (braid-group, isotopy) | Yes | - -## Dangerous patterns (BANNED) - -CI rejects any PR introducing these: - -| Pattern | Language | Meaning | -|---------|----------|---------| -| `believe_me` | Idris2 | Unsafe cast | -| `assert_total` | Idris2 | Skip totality check | -| `postulate` | Idris2 / Agda | Unproven axiom | -| `sorry` | Lean 4 | Incomplete proof | -| `axiom` (project-level) | Lean 4 | Unproven postulate | -| `Admitted` | Coq | Incomplete proof | -| `unsafeCoerce` | Haskell | Unsafe cast | -| `Obj.magic` | OCaml | Unsafe cast | -| `unsafe` (unaudited) | Rust | Unsafe block without safety comment | - -Enforced by `panic-attack assail --proofs-only`. - -## Recommended prover - -- **Lean 4** for the core metatheory (already chosen; `proofs/Tangle.lean`). -- **Lean 4** for `infer`-decidability and `compositional`-preservation. -- **Lean 4 + Wasm-spec / WasmCert** for WASM compilation correctness. - -## Template ABI cleanup (2026-03-29) - -Template ABI files (Idris2 `Types.idr`, `Layout.idr`, `Foreign.idr`) -were removed in March 2026 — they contained only RSR template -scaffolding with unresolved placeholders and no domain-specific proofs. -This decision still stands; ABI proofs are out of scope here (Tangle -is compiler-internal; the FFI boundary is in KRL's repo). - -## References - -- Implementation: [`compiler/lib/`](compiler/lib/), [`compiler/tangle-wasm/`](compiler/tangle-wasm/), [`compiler/tangle-lsp/`](compiler/tangle-lsp/). -- Formal core: [`proofs/Tangle.lean`](proofs/Tangle.lean). -- Spec: [`docs/spec/FORMAL-SEMANTICS.md`](docs/spec/FORMAL-SEMANTICS.md). -- Companion narratives: - `hyperpolymath/krl/PROOF-NARRATIVE.md`, - `hyperpolymath/quandledb/PROOF-NARRATIVE.md`. diff --git a/READINESS.adoc b/READINESS.adoc new file mode 100644 index 0000000..e3d8d41 --- /dev/null +++ b/READINESS.adoc @@ -0,0 +1,134 @@ +== Component Readiness — Tangle (language) + +*Current Grade:* D *Assessed:* 2026-07-21 (demoted C → D) *Standard:* +link:../standards/component-readiness-grades/[CRG v2.0 STRICT] + +=== Why the grade moved C → D + +Grade C means _self-validated in the home context_; the D → C promotion +trigger is _"`dogfood it hard in the home context.`"_ The previous +assessment cited exactly one piece of dogfooding evidence: + +____ +*Dogfooding:* Used internally as host for the KRL (Knot Resolution +Language) DSL +____ + +*That is not true.* KRL is not built on Tangle. KRL is QuandleDB’s +resolution language, developed jointly with QuandleDB; it neither +compiles to nor depends on Tangle, and the `+TangleIR+` layer that was +supposed to connect them does not exist in any source file in either +repository. See the erratum in `+AFFIRMATION.adoc+`. + +With that claim withdrawn there is no dogfooding evidence, so C is not +supported. Two further corrections to the previous assessment: + +* *"`CI: Clean`" was false.* At the time of this assessment `+main+` was +failing Governance and both Jekyll Pages workflows. +* *The test suites are not run by CI.* Eight OCaml test files exist +under `+compiler/test/+`, but no workflow in this repository invokes +`+dune+` or `+cargo test+`. Their passing state is unverified by this +repository’s own CI. + +This is a correction to the record, not a regression in the work. The +formal core in particular got _stronger_ this cycle — see below. + +''''' + +=== Grade rationale (evidence for D) + +Grade D: _"`works on some inputs, some cases, or some configurations, +but not systematically … either needs to be narrowed in scope so that +its documented capabilities match its actual capabilities, or needs the +inconsistencies fixed.`"_ Narrowing the documented scope is exactly what +this revision does. + +==== Verified evidence + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|Artefact |Check |Result +|`+proofs/Tangle.lean+` |`+cd proofs && lean Tangle.lean+` (the repo’s +own documented oracle) |*exit 0, no errors* + +|`+proofs/Tangle.lean+` |`+sorry+` count |*0* + +|`+proofs/Tangle.lean+` |`+axiom+` count |*0* + +|Theorems |`+progress+`, `+preservation+`, `+determinism+`, +`+type_safety+`, `+infer_sound+`, `+infer_complete+`, +`+infer_iff_hasType+` |all present with real proof terms + +|Dependencies |`+import+` lines in `+Tangle.lean+` |*0* — +self-contained, no Mathlib +|=== + +Run on 2026-07-21 with the pinned toolchain +(`+leanprover/lean4:v4.14.0+`). This is worth stating precisely: a Lean +file full of `+axiom+` stubs compiles cleanly while proving nothing, so +"`the build is green`" and "`the theorems are proved`" are different +claims. Here they coincide, and that was checked. + +==== Present but unverified + +* *OCaml compiler* (`+compiler/+`) — lexer, parser, AST, typechecker, +evaluator, pretty-printer, REPL, braid equivalence, LSP and WASM +targets. Not built by any workflow. +* *Test suites* — 8 files under `+compiler/test/+` (`+test_parser+`, +`+test_typecheck+`, `+test_eval+`, `+test_e2e+`, `+test_property+`, +`+test_compositional+`, `+test_check+`, `+test_roundtrip+`) plus +`+tg3+`/`+tg5+`/`+tg7+`/ `+tg8+` directories. Not run by any workflow. +* *Rust / Zig components* — 18 `+.rs+`, 3 `+.zig+`. Not built by any +workflow. +* *Five dialects* — grammar sketches only. + +==== Structural evidence + +* Per-directory README annotation across `+compiler/+`, `+dialects/+`, +`+docs/+`. +* RSR compliance: `+0-AI-MANIFEST.a2ml+`, `+.machine_readable/6a2/+`, +workflows, SECURITY / CONTRIBUTING / CODE_OF_CONDUCT, +`+EXPLAINME.adoc+`, `+TEST-NEEDS.md+`, `+PROOF-NEEDS.md+`. + +''''' + +=== Gaps preventing higher grades + +==== Blocks C (self-validated in the home context) + +[arabic] +. *No CI gate on the implementation.* The OCaml compiler, its 8 test +suites, and the Rust and Zig components are not built or run by any +workflow. Until they are, "`works reliably`" is not an evidenced claim. +This is the single highest-value fix available to this repository. +. *No dogfooding.* Nothing is currently built on Tangle. The previous +claim to the contrary was false. + +==== Blocks B (6+ diverse external targets) + +* No external language users outside hyperpolymath. +* No external submissions to language research venues confirming the +phase separation or compositional PD model. + +==== Blocks A + +* Requires B first. + +''''' + +=== What to do next + +[arabic] +. *Add a workflow that runs `+dune build && dune test+`.* Eight test +suites already exist; nothing executes them. This is the cheapest +available uplift and is a precondition for any claim above D. +. Add a workflow that builds the Rust and Zig components. +. Build something real on Tangle, in its own right — a braid-group +calculus, a category-theory calculus, a quantum-circuit calculus. The +five dialects are the natural candidates and currently exist only as +grammar sketches. Note that this must be genuine dogfooding of _Tangle_; +KRL does not count and never did. + +=== Review cycle + +Reassess when the compiler is built and its tests are run by CI. diff --git a/READINESS.md b/READINESS.md deleted file mode 100644 index c150e38..0000000 --- a/READINESS.md +++ /dev/null @@ -1,121 +0,0 @@ - - - -# Component Readiness — Tangle (language) - -**Current Grade:** D -**Assessed:** 2026-07-21 (demoted C → D) -**Standard:** [CRG v2.0 STRICT](../standards/component-readiness-grades/) - -## Why the grade moved C → D - -Grade C means *self-validated in the home context*; the D → C promotion trigger -is *"dogfood it hard in the home context."* The previous assessment cited -exactly one piece of dogfooding evidence: - -> **Dogfooding:** Used internally as host for the KRL (Knot Resolution Language) DSL - -**That is not true.** KRL is not built on Tangle. KRL is QuandleDB's resolution -language, developed jointly with QuandleDB; it neither compiles to nor depends -on Tangle, and the `TangleIR` layer that was supposed to connect them does not -exist in any source file in either repository. See the erratum in -`AFFIRMATION.adoc`. - -With that claim withdrawn there is no dogfooding evidence, so C is not -supported. Two further corrections to the previous assessment: - -- **"CI: Clean" was false.** At the time of this assessment `main` was failing - Governance and both Jekyll Pages workflows. -- **The test suites are not run by CI.** Eight OCaml test files exist under - `compiler/test/`, but no workflow in this repository invokes `dune` or - `cargo test`. Their passing state is unverified by this repository's own CI. - -This is a correction to the record, not a regression in the work. The formal -core in particular got *stronger* this cycle — see below. - ---- - -## Grade rationale (evidence for D) - -Grade D: *"works on some inputs, some cases, or some configurations, but not -systematically … either needs to be narrowed in scope so that its documented -capabilities match its actual capabilities, or needs the inconsistencies -fixed."* Narrowing the documented scope is exactly what this revision does. - -### Verified evidence - -| Artefact | Check | Result | -|---|---|---| -| `proofs/Tangle.lean` | `cd proofs && lean Tangle.lean` (the repo's own documented oracle) | **exit 0, no errors** | -| `proofs/Tangle.lean` | `sorry` count | **0** | -| `proofs/Tangle.lean` | `axiom` count | **0** | -| Theorems | `progress`, `preservation`, `determinism`, `type_safety`, `infer_sound`, `infer_complete`, `infer_iff_hasType` | all present with real proof terms | -| Dependencies | `import` lines in `Tangle.lean` | **0** — self-contained, no Mathlib | - -Run on 2026-07-21 with the pinned toolchain (`leanprover/lean4:v4.14.0`). This -is worth stating precisely: a Lean file full of `axiom` stubs compiles cleanly -while proving nothing, so "the build is green" and "the theorems are proved" are -different claims. Here they coincide, and that was checked. - -### Present but unverified - -- **OCaml compiler** (`compiler/`) — lexer, parser, AST, typechecker, evaluator, - pretty-printer, REPL, braid equivalence, LSP and WASM targets. Not built by - any workflow. -- **Test suites** — 8 files under `compiler/test/` (`test_parser`, - `test_typecheck`, `test_eval`, `test_e2e`, `test_property`, - `test_compositional`, `test_check`, `test_roundtrip`) plus `tg3`/`tg5`/`tg7`/ - `tg8` directories. Not run by any workflow. -- **Rust / Zig components** — 18 `.rs`, 3 `.zig`. Not built by any workflow. -- **Five dialects** — grammar sketches only. - -### Structural evidence - -- Per-directory README annotation across `compiler/`, `dialects/`, `docs/`. -- RSR compliance: `0-AI-MANIFEST.a2ml`, `.machine_readable/6a2/`, workflows, - SECURITY / CONTRIBUTING / CODE_OF_CONDUCT, `EXPLAINME.adoc`, `TEST-NEEDS.md`, - `PROOF-NEEDS.md`. - ---- - -## Gaps preventing higher grades - -### Blocks C (self-validated in the home context) - -1. **No CI gate on the implementation.** The OCaml compiler, its 8 test suites, - and the Rust and Zig components are not built or run by any workflow. Until - they are, "works reliably" is not an evidenced claim. This is the single - highest-value fix available to this repository. -2. **No dogfooding.** Nothing is currently built on Tangle. The previous claim - to the contrary was false. - -### Blocks B (6+ diverse external targets) - -- No external language users outside hyperpolymath. -- No external submissions to language research venues confirming the phase - separation or compositional PD model. - -### Blocks A - -- Requires B first. - ---- - -## What to do next - -1. **Add a workflow that runs `dune build && dune test`.** Eight test suites - already exist; nothing executes them. This is the cheapest available uplift - and is a precondition for any claim above D. -2. Add a workflow that builds the Rust and Zig components. -3. Build something real on Tangle, in its own right — a braid-group calculus, a - category-theory calculus, a quantum-circuit calculus. The five dialects are - the natural candidates and currently exist only as grammar sketches. - Note that this must be genuine dogfooding of *Tangle*; KRL does not count and - never did. - -## Review cycle - -Reassess when the compiler is built and its tests are run by CI. diff --git a/REQUIRES_INITIALISATION.adoc b/REQUIRES_INITIALISATION.adoc new file mode 100644 index 0000000..04b9eee --- /dev/null +++ b/REQUIRES_INITIALISATION.adoc @@ -0,0 +1,105 @@ +== REQUIRES INITIALISATION + +*This repository is not finished being set up.* 7 substitution token(s) +across 1 file(s) still have no value. + +=== Why this is not already done + +This repo was created from `+hyperpolymath/rsr-template-repo+`. The mint +(`+just repo-init+`) fills every token that has a single mechanical +answer — owner, repo, author, dates, licence, branch — and it has done +so here. + +The tokens below are the ones it _deliberately cannot_ answer. They need +a decision or a fact that exists only in your head: what this project is +for, what command builds it, which port the service listens on, whether +a PGP key is held at all. The template’s own token vocabulary says as +much — you cannot sensibly answer "`required invariants`" in a +thirty-second bootstrap. + +They were left *visibly unfilled on purpose*. The alternatives were both +worse: inventing plausible values would put confident falsehoods into a +security policy and an architecture document, and silently deleting the +sections would hide the fact that a decision is owed. A visible gap is +honest; a fabricated answer is not. + +=== Do not delete this file until every item below is resolved + +This file is the only marker that the work is outstanding. Deleting it +early does not finish the setup, it just conceals it — and the next +person or agent to arrive will reasonably assume the repo is complete. + +* *If you are a person:* delete this file yourself once the last item is +done. +* *If you are an agent:* resolve what you legitimately can, leave the +rest, and delete this file only when no token below remains anywhere in +the tree. Do not delete it to make a gate go green. + +Re-running the estate top-up tool will remove this file automatically +once nothing is outstanding, so the safest way to finish is to fix the +tokens and let the check confirm it. + +=== What is needed, and where it goes + +==== `+{{BUILD_CMD}}+` + +The exact command that builds this project. + +Appears in: + +* `+AFFIRMATION.adoc+` + +==== `+{{BUILD_OUTPUT_PATH}}+` + +Where the build artefact lands. + +Appears in: + +* `+AFFIRMATION.adoc+` + +==== `+{{DEPS}}+` + +Prose summary of runtime/build dependencies. + +Appears in: + +* `+AFFIRMATION.adoc+` + +==== `+{{LANG_STACK}}+` + +The language stack, in prose. + +Appears in: + +* `+AFFIRMATION.adoc+` + +==== `+{{MUST_INVARIANTS}}+` + +The invariants this project guarantees. Not answerable in a bootstrap; +it is the point of the repo. + +Appears in: + +* `+AFFIRMATION.adoc+` + +==== `+{{PROJECT_UNIQUE_STRENGTH}}+` + +What this does that its alternatives do not. + +Appears in: + +* `+AFFIRMATION.adoc+` + +==== `+{{TEST_CMD}}+` + +The exact command that runs its tests. + +Appears in: + +* `+AFFIRMATION.adoc+` + +''''' + +Generated by the estate top-up pass. Rationale and the governing rulings +are in `+hyperpolymath/standards+`; the token vocabulary is +`+.machine_readable/ai/PLACEHOLDERS.adoc+` in `+rsr-template-repo+`. diff --git a/REQUIRES_INITIALISATION.md b/REQUIRES_INITIALISATION.md deleted file mode 100644 index 373a864..0000000 --- a/REQUIRES_INITIALISATION.md +++ /dev/null @@ -1,102 +0,0 @@ - - -# REQUIRES INITIALISATION - -**This repository is not finished being set up.** 7 substitution token(s) across 1 file(s) still have no value. - -## Why this is not already done - -This repo was created from `hyperpolymath/rsr-template-repo`. The mint -(`just repo-init`) fills every token that has a single mechanical answer — -owner, repo, author, dates, licence, branch — and it has done so here. - -The tokens below are the ones it *deliberately cannot* answer. They need a -decision or a fact that exists only in your head: what this project is for, -what command builds it, which port the service listens on, whether a PGP key -is held at all. The template's own token vocabulary says as much — you cannot -sensibly answer "required invariants" in a thirty-second bootstrap. - -They were left **visibly unfilled on purpose**. The alternatives were both -worse: inventing plausible values would put confident falsehoods into a -security policy and an architecture document, and silently deleting the -sections would hide the fact that a decision is owed. A visible gap is -honest; a fabricated answer is not. - -## Do not delete this file until every item below is resolved - -This file is the only marker that the work is outstanding. Deleting it early -does not finish the setup, it just conceals it — and the next person or agent -to arrive will reasonably assume the repo is complete. - -- **If you are a person:** delete this file yourself once the last item is done. -- **If you are an agent:** resolve what you legitimately can, leave the rest, - and delete this file only when no token below remains anywhere in the tree. - Do not delete it to make a gate go green. - -Re-running the estate top-up tool will remove this file automatically once -nothing is outstanding, so the safest way to finish is to fix the tokens and -let the check confirm it. - -## What is needed, and where it goes - -### `{{BUILD_CMD}}` - -The exact command that builds this project. - -Appears in: - -- `AFFIRMATION.adoc` - -### `{{BUILD_OUTPUT_PATH}}` - -Where the build artefact lands. - -Appears in: - -- `AFFIRMATION.adoc` - -### `{{DEPS}}` - -Prose summary of runtime/build dependencies. - -Appears in: - -- `AFFIRMATION.adoc` - -### `{{LANG_STACK}}` - -The language stack, in prose. - -Appears in: - -- `AFFIRMATION.adoc` - -### `{{MUST_INVARIANTS}}` - -The invariants this project guarantees. Not answerable in a bootstrap; it is the point of the repo. - -Appears in: - -- `AFFIRMATION.adoc` - -### `{{PROJECT_UNIQUE_STRENGTH}}` - -What this does that its alternatives do not. - -Appears in: - -- `AFFIRMATION.adoc` - -### `{{TEST_CMD}}` - -The exact command that runs its tests. - -Appears in: - -- `AFFIRMATION.adoc` - ---- - -Generated by the estate top-up pass. Rationale and the governing rulings are -in `hyperpolymath/standards`; the token vocabulary is -`.machine_readable/ai/PLACEHOLDERS.adoc` in `rsr-template-repo`. diff --git a/SECURITY.adoc b/SECURITY.adoc new file mode 100644 index 0000000..8319a6a --- /dev/null +++ b/SECURITY.adoc @@ -0,0 +1,433 @@ +== Security Policy + +We take security seriously. We appreciate your efforts to responsibly +disclose vulnerabilities and will make every effort to acknowledge your +contributions. + +=== Table of Contents + +* link:#reporting-a-vulnerability[Reporting a Vulnerability] +* link:#what-to-include[What to Include] +* link:#response-timeline[Response Timeline] +* link:#disclosure-policy[Disclosure Policy] +* link:#scope[Scope] +* link:#safe-harbour[Safe Harbour] +* link:#recognition[Recognition] +* link:#security-updates[Security Updates] +* link:#security-best-practices[Security Best Practices] + +''''' + +=== Reporting a Vulnerability + +==== Preferred Method: GitHub Security Advisories + +The preferred method for reporting security vulnerabilities is through +GitHub’s Security Advisory feature: + +[arabic] +. Navigate to +https://github.com/hyperpolymath/tangle/security/advisories/new[Report a +Vulnerability] +. Click *"`Report a vulnerability`"* +. Complete the form with as much detail as possible +. Submit — we’ll receive a private notification + +This method ensures: + +* End-to-end encryption of your report +* Private discussion space for collaboration +* Coordinated disclosure tooling +* Automatic credit when the advisory is published + +==== Alternative: Email + +If you cannot use GitHub Security Advisories, email us directly at +j.d.a.jewell@open.ac.uk. No PGP key is currently published; for an +encrypted channel, request one via a GitHub Security Advisory. + +____ +*⚠️ Important:* Do not report security vulnerabilities through public +GitHub issues, pull requests, discussions, or social media. +____ + +''''' + +=== What to Include + +A good vulnerability report helps us understand and reproduce the issue +quickly. + +==== Required Information + +* *Description*: Clear explanation of the vulnerability +* *Impact*: What an attacker could achieve (confidentiality, integrity, +availability) +* *Affected versions*: Which versions/commits are affected +* *Reproduction steps*: Detailed steps to reproduce the issue + +==== Helpful Additional Information + +* *Proof of concept*: Code, scripts, or screenshots demonstrating the +vulnerability +* *Attack scenario*: Realistic attack scenario showing exploitability +* *CVSS score*: Your assessment of severity (use +https://www.first.org/cvss/calculator/3.1[CVSS 3.1 Calculator]) +* *CWE ID*: Common Weakness Enumeration identifier if known +* *Suggested fix*: If you have ideas for remediation +* *References*: Links to related vulnerabilities, research, or +advisories + +==== Example Report Structure + +[source,markdown] +---- +## Summary +[One-sentence description of the vulnerability] + +## Vulnerability Type +[e.g., SQL Injection, XSS, SSRF, Path Traversal, etc.] + +## Affected Component +[File path, function name, API endpoint, etc.] + +## Affected Versions +[Version range or specific commits] + +## Severity Assessment +- CVSS 3.1 Score: [X.X] +- CVSS Vector: [CVSS:3.1/AV:X/AC:X/PR:X/UI:X/S:X/C:X/I:X/A:X] + +## Description +[Detailed technical description] + +## Steps to Reproduce +1. [First step] +2. [Second step] +3. [...] + +## Proof of Concept +[Code, curl commands, screenshots, etc.] + +## Impact +[What can an attacker achieve?] + +## Suggested Remediation +[Optional: your ideas for fixing] + +## References +[Links to related issues, CVEs, research] +---- + +''''' + +=== Response Timeline + +We commit to the following response times: + +[width="100%",cols="24%,35%,41%",options="header",] +|=== +|Stage |Timeframe |Description +|*Initial Response* |48 hours |We acknowledge receipt and confirm we’re +investigating + +|*Triage* |7 days |We assess severity, confirm the vulnerability, and +estimate timeline + +|*Status Update* |Every 7 days |Regular updates on remediation progress + +|*Resolution* |90 days |Target for fix development and release (complex +issues may take longer) + +|*Disclosure* |90 days |Public disclosure after fix is available +(coordinated with you) +|=== + +____ +*Note:* These are targets, not guarantees. Complex vulnerabilities may +require more time. We’ll communicate openly about any delays. +____ + +''''' + +=== Disclosure Policy + +We follow *coordinated disclosure* (also known as responsible +disclosure): + +[arabic] +. *You report* the vulnerability privately +. *We acknowledge* and begin investigation +. *We develop* a fix and prepare a release +. *We coordinate* disclosure timing with you +. *We publish* security advisory and fix simultaneously +. *You may publish* your research after disclosure + +==== Our Commitments + +* We will not take legal action against researchers who follow this +policy +* We will work with you to understand and resolve the issue +* We will credit you in the security advisory (unless you prefer +anonymity) +* We will notify you before public disclosure +* We will publish advisories with sufficient detail for users to assess +risk + +==== Your Commitments + +* Report vulnerabilities promptly after discovery +* Give us reasonable time to address the issue before disclosure +* Do not access, modify, or delete data beyond what’s necessary to +demonstrate the vulnerability +* Do not degrade service availability (no DoS testing on production) +* Do not share vulnerability details with others until coordinated +disclosure + +==== Disclosure Timeline + +.... +Day 0 You report vulnerability +Day 1-2 We acknowledge receipt +Day 7 We confirm vulnerability and share initial assessment +Day 7-90 We develop and test fix +Day 90 Coordinated public disclosure + (earlier if fix is ready; later by mutual agreement) +.... + +If we cannot reach agreement on disclosure timing, we default to 90 days +from your initial report. + +''''' + +=== Scope + +==== In Scope ✅ + +The following are within scope for security research: + +* This repository (`+hyperpolymath/tangle+`) and all its code +* Official releases and packages published from this repository +* Documentation that could lead to security issues +* Build and deployment configurations in this repository +* Dependencies (report here, we’ll coordinate with upstream) + +==== Out of Scope ❌ + +The following are *not* in scope: + +* Third-party services we integrate with (report directly to them) +* Social engineering attacks against maintainers +* Physical security +* Denial of service attacks against production infrastructure +* Spam, phishing, or other non-technical attacks +* Issues already reported or publicly known +* Theoretical vulnerabilities without proof of concept + +==== Qualifying Vulnerabilities + +We’re particularly interested in: + +* Remote code execution +* SQL injection, command injection, code injection +* Authentication/authorisation bypass +* Cross-site scripting (XSS) and cross-site request forgery (CSRF) +* Server-side request forgery (SSRF) +* Path traversal / local file inclusion +* Information disclosure (credentials, PII, secrets) +* Cryptographic weaknesses +* Deserialisation vulnerabilities +* Memory safety issues (buffer overflows, use-after-free, etc.) +* Supply chain vulnerabilities (dependency confusion, etc.) +* Significant logic flaws + +==== Non-Qualifying Issues + +The following generally do not qualify as security vulnerabilities: + +* Missing security headers on non-sensitive pages +* Clickjacking on pages without sensitive actions +* Self-XSS (requires victim to paste code) +* Missing rate limiting (unless it enables a specific attack) +* Username/email enumeration (unless high-risk context) +* Missing cookie flags on non-sensitive cookies +* Software version disclosure +* Verbose error messages (unless exposing secrets) +* Best practice deviations without demonstrable impact + +''''' + +=== Safe Harbour + +We support security research conducted in good faith. + +==== Our Promise + +If you conduct security research in accordance with this policy: + +* ✅ We will not initiate legal action against you +* ✅ We will not report your activity to law enforcement +* ✅ We will work with you in good faith to resolve issues +* ✅ We consider your research authorised under the Computer Fraud and +Abuse Act (CFAA), UK Computer Misuse Act, and similar laws +* ✅ We waive any potential claim against you for circumvention of +security controls + +==== Good Faith Requirements + +To qualify for safe harbour, you must: + +* Comply with this security policy +* Report vulnerabilities promptly +* Avoid privacy violations (do not access others’ data) +* Avoid service degradation (no destructive testing) +* Not exploit vulnerabilities beyond proof-of-concept +* Not use vulnerabilities for profit (beyond bug bounties where offered) + +____ +*⚠️ Important:* This safe harbour does not extend to third-party +systems. Always check their policies before testing. +____ + +''''' + +=== Recognition + +We believe in recognising security researchers who help us improve. + +==== Hall of Fame + +Researchers who report valid vulnerabilities will be acknowledged in our +link:SECURITY-ACKNOWLEDGMENTS.md[Security Acknowledgments] (unless they +prefer anonymity). + +Recognition includes: + +* Your name (or chosen alias) +* Link to your website/profile (optional) +* Brief description of the vulnerability class +* Date of report + +==== What We Offer + +* ✅ Public credit in security advisories +* ✅ Acknowledgment in release notes +* ✅ Entry in our Hall of Fame +* ✅ Reference/recommendation letter upon request (for significant +findings) + +==== What We Don’t Currently Offer + +* ❌ Monetary bug bounties +* ❌ Hardware or swag +* ❌ Paid security research contracts + +____ +*Note:* We’re a community project with limited resources. Your +contributions help everyone who uses this software. +____ + +''''' + +=== Security Updates + +==== Receiving Updates + +To stay informed about security updates: + +* *Watch this repository*: Click "`Watch`" → "`Custom`" → Select +"`Security alerts`" +* *GitHub Security Advisories*: Published at +https://github.com/hyperpolymath/tangle/security/advisories[Security +Advisories] +* *Release notes*: Security fixes noted in link:CHANGELOG.md[CHANGELOG] + +==== Update Policy + +[cols=",",options="header",] +|=== +|Severity |Response +|*Critical/High* |Patch release as soon as fix is ready +|*Medium* |Included in next scheduled release (or earlier) +|*Low* |Included in next scheduled release +|=== + +==== Supported Versions + +[cols=",,",options="header",] +|=== +|Version |Supported |Notes +|`+main+` branch |✅ Yes |Latest development +|Latest release |✅ Yes |Current stable +|Previous minor release |✅ Yes |Security fixes backported +|Older versions |❌ No |Please upgrade +|=== + +''''' + +=== Security Best Practices + +When using tangle, we recommend: + +==== General + +* Keep dependencies up to date +* Use the latest stable release +* Subscribe to security notifications +* Review configuration against security documentation +* Follow principle of least privilege + +==== For Contributors + +* Never commit secrets, credentials, or API keys +* Use signed commits (`+git config commit.gpgsign true+`) +* Review dependencies before adding them +* Run security linters locally before pushing +* Report any concerns about existing code + +''''' + +=== Additional Resources + +* https://github.com/hyperpolymath/tangle/security/advisories[Security +Advisories] +* link:CHANGELOG.md[Changelog] +* link:CONTRIBUTING.md[Contributing Guidelines] +* https://cve.mitre.org/[CVE Database] +* https://www.first.org/cvss/calculator/3.1[CVSS Calculator] + +''''' + +=== Contact + +[width="100%",cols="50%,50%",options="header",] +|=== +|Purpose |Contact +|*Security issues* +|https://github.com/hyperpolymath/tangle/security/advisories/new[Report +via GitHub] or j.d.a.jewell@open.ac.uk + +|*General questions* +|https://github.com/hyperpolymath/tangle/discussions[GitHub Discussions] + +|*Other enquiries* |See link:README.md[README] for contact information +|=== + +''''' + +=== Policy Changes + +This security policy may be updated from time to time. Significant +changes will be: + +* Committed to this repository with a clear commit message +* Noted in the changelog +* Announced via GitHub Discussions (for major changes) + +''''' + +_Thank you for helping keep tangle and its users safe._ 🛡️ + +''''' + +Last updated: 2026 · Policy version: 1.0.0 diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index e5dc9cf..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,377 +0,0 @@ - -# Security Policy - -We take security seriously. We appreciate your efforts to responsibly disclose vulnerabilities and will make every effort to acknowledge your contributions. - -## Table of Contents - -- [Reporting a Vulnerability](#reporting-a-vulnerability) -- [What to Include](#what-to-include) -- [Response Timeline](#response-timeline) -- [Disclosure Policy](#disclosure-policy) -- [Scope](#scope) -- [Safe Harbour](#safe-harbour) -- [Recognition](#recognition) -- [Security Updates](#security-updates) -- [Security Best Practices](#security-best-practices) - ---- - -## Reporting a Vulnerability - -### Preferred Method: GitHub Security Advisories - -The preferred method for reporting security vulnerabilities is through GitHub's Security Advisory feature: - -1. Navigate to [Report a Vulnerability](https://github.com/hyperpolymath/tangle/security/advisories/new) -2. Click **"Report a vulnerability"** -3. Complete the form with as much detail as possible -4. Submit — we'll receive a private notification - -This method ensures: - -- End-to-end encryption of your report -- Private discussion space for collaboration -- Coordinated disclosure tooling -- Automatic credit when the advisory is published - -### Alternative: Email - -If you cannot use GitHub Security Advisories, email us directly at -j.d.a.jewell@open.ac.uk. No PGP key is currently -published; for an encrypted channel, request one via a GitHub Security -Advisory. - -> **⚠️ Important:** Do not report security vulnerabilities through public GitHub issues, pull requests, discussions, or social media. - ---- - -## What to Include - -A good vulnerability report helps us understand and reproduce the issue quickly. - -### Required Information - -- **Description**: Clear explanation of the vulnerability -- **Impact**: What an attacker could achieve (confidentiality, integrity, availability) -- **Affected versions**: Which versions/commits are affected -- **Reproduction steps**: Detailed steps to reproduce the issue - -### Helpful Additional Information - -- **Proof of concept**: Code, scripts, or screenshots demonstrating the vulnerability -- **Attack scenario**: Realistic attack scenario showing exploitability -- **CVSS score**: Your assessment of severity (use [CVSS 3.1 Calculator](https://www.first.org/cvss/calculator/3.1)) -- **CWE ID**: Common Weakness Enumeration identifier if known -- **Suggested fix**: If you have ideas for remediation -- **References**: Links to related vulnerabilities, research, or advisories - -### Example Report Structure - -```markdown -## Summary -[One-sentence description of the vulnerability] - -## Vulnerability Type -[e.g., SQL Injection, XSS, SSRF, Path Traversal, etc.] - -## Affected Component -[File path, function name, API endpoint, etc.] - -## Affected Versions -[Version range or specific commits] - -## Severity Assessment -- CVSS 3.1 Score: [X.X] -- CVSS Vector: [CVSS:3.1/AV:X/AC:X/PR:X/UI:X/S:X/C:X/I:X/A:X] - -## Description -[Detailed technical description] - -## Steps to Reproduce -1. [First step] -2. [Second step] -3. [...] - -## Proof of Concept -[Code, curl commands, screenshots, etc.] - -## Impact -[What can an attacker achieve?] - -## Suggested Remediation -[Optional: your ideas for fixing] - -## References -[Links to related issues, CVEs, research] -``` - ---- - -## Response Timeline - -We commit to the following response times: - -| Stage | Timeframe | Description | -|-------|-----------|-------------| -| **Initial Response** | 48 hours | We acknowledge receipt and confirm we're investigating | -| **Triage** | 7 days | We assess severity, confirm the vulnerability, and estimate timeline | -| **Status Update** | Every 7 days | Regular updates on remediation progress | -| **Resolution** | 90 days | Target for fix development and release (complex issues may take longer) | -| **Disclosure** | 90 days | Public disclosure after fix is available (coordinated with you) | - -> **Note:** These are targets, not guarantees. Complex vulnerabilities may require more time. We'll communicate openly about any delays. - ---- - -## Disclosure Policy - -We follow **coordinated disclosure** (also known as responsible disclosure): - -1. **You report** the vulnerability privately -2. **We acknowledge** and begin investigation -3. **We develop** a fix and prepare a release -4. **We coordinate** disclosure timing with you -5. **We publish** security advisory and fix simultaneously -6. **You may publish** your research after disclosure - -### Our Commitments - -- We will not take legal action against researchers who follow this policy -- We will work with you to understand and resolve the issue -- We will credit you in the security advisory (unless you prefer anonymity) -- We will notify you before public disclosure -- We will publish advisories with sufficient detail for users to assess risk - -### Your Commitments - -- Report vulnerabilities promptly after discovery -- Give us reasonable time to address the issue before disclosure -- Do not access, modify, or delete data beyond what's necessary to demonstrate the vulnerability -- Do not degrade service availability (no DoS testing on production) -- Do not share vulnerability details with others until coordinated disclosure - -### Disclosure Timeline - -``` -Day 0 You report vulnerability -Day 1-2 We acknowledge receipt -Day 7 We confirm vulnerability and share initial assessment -Day 7-90 We develop and test fix -Day 90 Coordinated public disclosure - (earlier if fix is ready; later by mutual agreement) -``` - -If we cannot reach agreement on disclosure timing, we default to 90 days from your initial report. - ---- - -## Scope - -### In Scope ✅ - -The following are within scope for security research: - -- This repository (`hyperpolymath/tangle`) and all its code -- Official releases and packages published from this repository -- Documentation that could lead to security issues -- Build and deployment configurations in this repository -- Dependencies (report here, we'll coordinate with upstream) - -### Out of Scope ❌ - -The following are **not** in scope: - -- Third-party services we integrate with (report directly to them) -- Social engineering attacks against maintainers -- Physical security -- Denial of service attacks against production infrastructure -- Spam, phishing, or other non-technical attacks -- Issues already reported or publicly known -- Theoretical vulnerabilities without proof of concept - -### Qualifying Vulnerabilities - -We're particularly interested in: - -- Remote code execution -- SQL injection, command injection, code injection -- Authentication/authorisation bypass -- Cross-site scripting (XSS) and cross-site request forgery (CSRF) -- Server-side request forgery (SSRF) -- Path traversal / local file inclusion -- Information disclosure (credentials, PII, secrets) -- Cryptographic weaknesses -- Deserialisation vulnerabilities -- Memory safety issues (buffer overflows, use-after-free, etc.) -- Supply chain vulnerabilities (dependency confusion, etc.) -- Significant logic flaws - -### Non-Qualifying Issues - -The following generally do not qualify as security vulnerabilities: - -- Missing security headers on non-sensitive pages -- Clickjacking on pages without sensitive actions -- Self-XSS (requires victim to paste code) -- Missing rate limiting (unless it enables a specific attack) -- Username/email enumeration (unless high-risk context) -- Missing cookie flags on non-sensitive cookies -- Software version disclosure -- Verbose error messages (unless exposing secrets) -- Best practice deviations without demonstrable impact - ---- - -## Safe Harbour - -We support security research conducted in good faith. - -### Our Promise - -If you conduct security research in accordance with this policy: - -- ✅ We will not initiate legal action against you -- ✅ We will not report your activity to law enforcement -- ✅ We will work with you in good faith to resolve issues -- ✅ We consider your research authorised under the Computer Fraud and Abuse Act (CFAA), UK Computer Misuse Act, and similar laws -- ✅ We waive any potential claim against you for circumvention of security controls - -### Good Faith Requirements - -To qualify for safe harbour, you must: - -- Comply with this security policy -- Report vulnerabilities promptly -- Avoid privacy violations (do not access others' data) -- Avoid service degradation (no destructive testing) -- Not exploit vulnerabilities beyond proof-of-concept -- Not use vulnerabilities for profit (beyond bug bounties where offered) - -> **⚠️ Important:** This safe harbour does not extend to third-party systems. Always check their policies before testing. - ---- - -## Recognition - -We believe in recognising security researchers who help us improve. - -### Hall of Fame - -Researchers who report valid vulnerabilities will be acknowledged in our [Security Acknowledgments](SECURITY-ACKNOWLEDGMENTS.md) (unless they prefer anonymity). - -Recognition includes: - -- Your name (or chosen alias) -- Link to your website/profile (optional) -- Brief description of the vulnerability class -- Date of report - -### What We Offer - -- ✅ Public credit in security advisories -- ✅ Acknowledgment in release notes -- ✅ Entry in our Hall of Fame -- ✅ Reference/recommendation letter upon request (for significant findings) - -### What We Don't Currently Offer - -- ❌ Monetary bug bounties -- ❌ Hardware or swag -- ❌ Paid security research contracts - -> **Note:** We're a community project with limited resources. Your contributions help everyone who uses this software. - ---- - -## Security Updates - -### Receiving Updates - -To stay informed about security updates: - -- **Watch this repository**: Click "Watch" → "Custom" → Select "Security alerts" -- **GitHub Security Advisories**: Published at [Security Advisories](https://github.com/hyperpolymath/tangle/security/advisories) -- **Release notes**: Security fixes noted in [CHANGELOG](CHANGELOG.md) - -### Update Policy - -| Severity | Response | -|----------|----------| -| **Critical/High** | Patch release as soon as fix is ready | -| **Medium** | Included in next scheduled release (or earlier) | -| **Low** | Included in next scheduled release | - -### Supported Versions - - - -| Version | Supported | Notes | -|---------|-----------|-------| -| `main` branch | ✅ Yes | Latest development | -| Latest release | ✅ Yes | Current stable | -| Previous minor release | ✅ Yes | Security fixes backported | -| Older versions | ❌ No | Please upgrade | - ---- - -## Security Best Practices - -When using tangle, we recommend: - -### General - -- Keep dependencies up to date -- Use the latest stable release -- Subscribe to security notifications -- Review configuration against security documentation -- Follow principle of least privilege - -### For Contributors - -- Never commit secrets, credentials, or API keys -- Use signed commits (`git config commit.gpgsign true`) -- Review dependencies before adding them -- Run security linters locally before pushing -- Report any concerns about existing code - ---- - -## Additional Resources - -- [Security Advisories](https://github.com/hyperpolymath/tangle/security/advisories) -- [Changelog](CHANGELOG.md) -- [Contributing Guidelines](CONTRIBUTING.md) -- [CVE Database](https://cve.mitre.org/) -- [CVSS Calculator](https://www.first.org/cvss/calculator/3.1) - ---- - -## Contact - -| Purpose | Contact | -|---------|---------| -| **Security issues** | [Report via GitHub](https://github.com/hyperpolymath/tangle/security/advisories/new) or j.d.a.jewell@open.ac.uk | -| **General questions** | [GitHub Discussions](https://github.com/hyperpolymath/tangle/discussions) | -| **Other enquiries** | See [README](README.md) for contact information | - ---- - -## Policy Changes - -This security policy may be updated from time to time. Significant changes will be: - -- Committed to this repository with a clear commit message -- Noted in the changelog -- Announced via GitHub Discussions (for major changes) - ---- - -*Thank you for helping keep tangle and its users safe.* 🛡️ - ---- - -Last updated: 2026 · Policy version: 1.0.0 diff --git a/TEST-NEEDS.adoc b/TEST-NEEDS.adoc new file mode 100644 index 0000000..2b4c04c --- /dev/null +++ b/TEST-NEEDS.adoc @@ -0,0 +1,69 @@ +== TEST-NEEDS: tangle + +=== CRG Grade: C — ACHIEVED 2026-04-04 + +=== Current State + +[width="100%",cols="40%,26%,34%",options="header",] +|=== +|Category |Count |Details +|*Source modules* |11 |Rust: ast, ast_jtv, lexer, parser, parser_jtv, +eval, lib, main, sexpr + 3 Idris2 ABI + +|*Unit tests (inline)* |252 |lexer=151, parser=40, parser_jtv=32, +eval=29 + +|*Integration tests* |0 |None + +|*E2E tests* |0 |None + +|*Benchmarks* |4 files |bench_lexer.rs (135L), bench_parser_rust.rs +(106L), bench_lexer.ml (113L), bench_parser.ml (88L) + +|*Fuzz tests* |2 |fuzz_lexer.rs, fuzz_parser.rs +|=== + +=== What’s Missing + +==== E2E Tests + +* [ ] No test that parses a Tangle program and evaluates it end-to-end +* [ ] No test for the sexpr output format +* [ ] No test for the main binary + +==== Aspect Tests + +* [ ] *Security*: No injection/escape tests for the parser +* [ ] *Performance*: Benchmarks exist – need to verify they actually run +* [ ] *Concurrency*: N/A for a language parser +* [ ] *Error handling*: No tests for error recovery, partial parse, +unterminated strings + +==== Build & Execution + +* [ ] OCaml benchmarks (bench_lexer.ml, bench_parser.ml) – does OCaml +build config exist? +* [ ] No Idris2 ABI compilation test + +==== Benchmarks Status + +* [x] bench_lexer.rs (135 lines) – appears real +* [x] bench_parser_rust.rs (106 lines) – appears real +* [?] bench_lexer.ml (113 lines) – needs OCaml build verification +* [?] bench_parser.ml (88 lines) – needs OCaml build verification + +==== Self-Tests + +* [ ] No self-diagnostic mode + +=== FLAGGED ISSUES + +* *252 inline unit tests is good* for a parser/lexer +* *Benchmarks appear genuine* – best benchmark setup among scanned repos +* *Fuzz tests exist* – rare and commendable +* *ast.rs, ast_jtv.rs, sexpr.rs have 0 tests* – structural modules +untested +* *No integration/E2E despite having eval* – can’t verify programs +actually run correctly + +=== Priority: P2 (MEDIUM) – solid unit/bench/fuzz foundation, needs E2E and integration diff --git a/TEST-NEEDS.md b/TEST-NEEDS.md deleted file mode 100644 index df03e96..0000000 --- a/TEST-NEEDS.md +++ /dev/null @@ -1,53 +0,0 @@ - -# TEST-NEEDS: tangle - -## CRG Grade: C — ACHIEVED 2026-04-04 - -## Current State - -| Category | Count | Details | -|----------|-------|---------| -| **Source modules** | 11 | Rust: ast, ast_jtv, lexer, parser, parser_jtv, eval, lib, main, sexpr + 3 Idris2 ABI | -| **Unit tests (inline)** | 252 | lexer=151, parser=40, parser_jtv=32, eval=29 | -| **Integration tests** | 0 | None | -| **E2E tests** | 0 | None | -| **Benchmarks** | 4 files | bench_lexer.rs (135L), bench_parser_rust.rs (106L), bench_lexer.ml (113L), bench_parser.ml (88L) | -| **Fuzz tests** | 2 | fuzz_lexer.rs, fuzz_parser.rs | - -## What's Missing - -### E2E Tests -- [ ] No test that parses a Tangle program and evaluates it end-to-end -- [ ] No test for the sexpr output format -- [ ] No test for the main binary - -### Aspect Tests -- [ ] **Security**: No injection/escape tests for the parser -- [ ] **Performance**: Benchmarks exist -- need to verify they actually run -- [ ] **Concurrency**: N/A for a language parser -- [ ] **Error handling**: No tests for error recovery, partial parse, unterminated strings - -### Build & Execution -- [ ] OCaml benchmarks (bench_lexer.ml, bench_parser.ml) -- does OCaml build config exist? -- [ ] No Idris2 ABI compilation test - -### Benchmarks Status -- [x] bench_lexer.rs (135 lines) -- appears real -- [x] bench_parser_rust.rs (106 lines) -- appears real -- [?] bench_lexer.ml (113 lines) -- needs OCaml build verification -- [?] bench_parser.ml (88 lines) -- needs OCaml build verification - -### Self-Tests -- [ ] No self-diagnostic mode - -## FLAGGED ISSUES -- **252 inline unit tests is good** for a parser/lexer -- **Benchmarks appear genuine** -- best benchmark setup among scanned repos -- **Fuzz tests exist** -- rare and commendable -- **ast.rs, ast_jtv.rs, sexpr.rs have 0 tests** -- structural modules untested -- **No integration/E2E despite having eval** -- can't verify programs actually run correctly - -## Priority: P2 (MEDIUM) -- solid unit/bench/fuzz foundation, needs E2E and integration diff --git a/TOPOLOGY.adoc b/TOPOLOGY.adoc new file mode 100644 index 0000000..e8f52b6 --- /dev/null +++ b/TOPOLOGY.adoc @@ -0,0 +1,41 @@ +== TOPOLOGY.md — tangle + +=== Purpose + +TANGLE is a Turing-complete topological programming language where +programs are represented as tangles—isotopy classes of braided strands +in 3D space. Computation proceeds via strand braiding with interactions +at crossings, leveraging deep connections between topology, algebra, and +computation. Knot invariants (Jones polynomial) enable novel reasoning +about program equivalence. + +=== Module Map + +.... +tangle/ +├── src/ # Core language implementation +│ ├── parser/ # Tangle source parser +│ ├── topology/ # Topological representation +│ ├── invariants/ # Knot invariant computation +│ ├── evaluator/ # Execution engine +│ └── backend/ # Code generation +├── examples/ # Example Tangle programs +├── tests/ # Language conformance tests +└── docs/ # Language specification +.... + +=== Data Flow + +.... +[Tangle Source] ──► [Parser] ──► [Topological Representation] ──► [Invariant Extraction] + ↓ + [Braiding Evaluation] ──► [Computation Result] +.... + +=== Key Concepts + +* *Strands*: Data-carrying topological objects +* *Crossings*: Interaction points where strands compute +* *Braiding*: Control flow via strand arrangement +* *Knot Invariants*: Jones polynomial for program analysis +* *Isotopy Classes*: Equivalent programs have same invariants diff --git a/TOPOLOGY.md b/TOPOLOGY.md deleted file mode 100644 index 6204489..0000000 --- a/TOPOLOGY.md +++ /dev/null @@ -1,42 +0,0 @@ - - - -# TOPOLOGY.md — tangle - -## Purpose - -TANGLE is a Turing-complete topological programming language where programs are represented as tangles—isotopy classes of braided strands in 3D space. Computation proceeds via strand braiding with interactions at crossings, leveraging deep connections between topology, algebra, and computation. Knot invariants (Jones polynomial) enable novel reasoning about program equivalence. - -## Module Map - -``` -tangle/ -├── src/ # Core language implementation -│ ├── parser/ # Tangle source parser -│ ├── topology/ # Topological representation -│ ├── invariants/ # Knot invariant computation -│ ├── evaluator/ # Execution engine -│ └── backend/ # Code generation -├── examples/ # Example Tangle programs -├── tests/ # Language conformance tests -└── docs/ # Language specification -``` - -## Data Flow - -``` -[Tangle Source] ──► [Parser] ──► [Topological Representation] ──► [Invariant Extraction] - ↓ - [Braiding Evaluation] ──► [Computation Result] -``` - -## Key Concepts - -- **Strands**: Data-carrying topological objects -- **Crossings**: Interaction points where strands compute -- **Braiding**: Control flow via strand arrangement -- **Knot Invariants**: Jones polynomial for program analysis -- **Isotopy Classes**: Equivalent programs have same invariants diff --git a/compiler/tangle-lsp/docs/lsp-diagnostic-categories.adoc b/compiler/tangle-lsp/docs/lsp-diagnostic-categories.adoc new file mode 100644 index 0000000..664b8c4 --- /dev/null +++ b/compiler/tangle-lsp/docs/lsp-diagnostic-categories.adoc @@ -0,0 +1,124 @@ +== `+tangle-lsp+` diagnostic categories + +This file documents the four categories `+tangle-lsp+` diagnostics fall +into. Together with the updated assumption `+A-TG-9.1+` in the repo-root +`+ASSUMPTIONS.md+`, they formalise the *TG-9 Option B* resolution from +issue #28. + +The bigger picture: obligation *TG-9* in `+PROOF-NARRATIVE.md+` says +every LSP diagnostic should correspond to a failure of the `+HasType+` +typing judgment in `+proofs/Tangle.lean+`. The 2026-06-01 audit (issue +#28) found that 6 of 7 diagnostic call sites have no `+HasType+` +counterpart. There were two options for closing the gap: + +* *Option A* — route every diagnostic through +`+compiler/lib/typecheck.ml+` via an OCaml↔Rust FFI. Higher engineering +cost; the most principled. +* *Option B* — accept LSP-only diagnostics, document the categories, and +tag each call site with which category it belongs to. Lower cost; what +this file describes. + +Option B keeps the diagnostics where they help users while making the +"`this is not a `+HasType+` failure`" status explicit. Option A is +queued in #28 for follow-up. + +=== The categories + +Each is denoted in the `+Diagnostic.source+` field as +`+tangle-lsp[CATEGORY]+`. + +==== `+PARSE_ERROR+` + +Grammar-level rejection. Corresponds to the parser refusing malformed +input. Not a `+HasType+` failure but a legitimate language-level +rejection. + +Examples: - Unbalanced parentheses, brackets, braces. + +Source location markers in `+backend.rs+`: - `+tangle-lsp[PARSE_ERROR]+` +— 3 sites (paren / bracket / brace). + +==== `+MISSPELLING_HINT+` + +IDE-convenience hint. The user typed something close to a keyword. No +spec counterpart — the spec doesn’t know about misspellings. + +Examples: - `+comput+` instead of `+compute+`. - `+asert+` instead of +`+assert+`. + +Source location markers in `+backend.rs+`: - +`+tangle-lsp[MISSPELLING_HINT]+` — 1 site. + +==== `+STRUCTURAL_HINT+` + +LSP-only structural heuristic. Tracks block nesting, weave-block +balance, etc. without a corresponding `+HasType+` rule. The `+weave+` +keyword in particular is part of a proposed v0.2 dialect not yet in the +core typing relation. + +Examples: - Unclosed `+weave+` block. - Suspicious block nesting depth. + +Source location markers in `+backend.rs+`: - +`+tangle-lsp[STRUCTURAL_HINT]+` — 2 sites. + +==== `+NAME_HINT+` + +Possibly-undefined-reference hint. Implemented as `+HINT+` severity (the +softest LSP level) because identifiers may resolve via future imports +the lexical pass can’t see. The OCaml typechecker raises a hard +exception on unbound variables; this LSP hint is the softer IDE-side +analogue. + +Source location markers in `+backend.rs+`: - `+tangle-lsp[NAME_HINT]+` — +1 site. + +=== How to add a new diagnostic + +[arabic] +. Pick a category. If none fits, propose a new category in a PR that +updates this file *and* `+ASSUMPTIONS.md+` A-TG-9.1. +. Tag the `+Diagnostic.source+` field with `+tangle-lsp[CATEGORY]+`. +. Add a `+// [CATEGORY]+` comment immediately above the +`+self.diagnostics.push(...)+` call so reviewers can audit the category +set at-a-glance. + +=== How this discharges TG-9 (Option B) + +`+A-TG-9.1+` previously said _"``+tangle-lsp+` reuses +`+compiler/lib/ typecheck.ml+` as the diagnostic engine (no LSP-only +diagnostics)`"_. That was false; the audit (#28) confirmed it. + +Option B updates `+A-TG-9.1+` to: + +____ +`+tangle-lsp+` emits diagnostics in *four documented categories* +(`+PARSE_ERROR+`, `+MISSPELLING_HINT+`, `+STRUCTURAL_HINT+`, +`+NAME_HINT+`); only `+PARSE_ERROR+` corresponds to a grammar-level +rejection. The other three are LSP-only by design, documented in +`+compiler/tangle-lsp/docs/lsp-diagnostic-categories.md+`. +____ + +This is a discipline shift: instead of pretending the LSP refines the +spec, we acknowledge the gap and document each step out. Option A (real +refinement via FFI to `+typecheck.ml+`) remains the long-term target and +is tracked in #28. + +=== CI gate (proposed; queued for follow-up) + +A grep-based CI check could enforce: + +[source,bash] +---- +grep -rE 'self\.diagnostics\.push' compiler/tangle-lsp/src/ | + grep -v 'tangle-lsp\[(PARSE_ERROR|MISSPELLING_HINT|STRUCTURAL_HINT|NAME_HINT)\]' +---- + +Any unmatched diagnostic line means an untagged emission site. This +would be a 1d follow-up PR. + +=== Cross-references + +* `+PROOF-NARRATIVE.md+` §3 TG-9 +* `+ASSUMPTIONS.md+` A-TG-9.1 (updated by this PR) +* Issue #28 — TG-9 audit findings + Options A/B +* `+compiler/tangle-lsp/src/backend.rs+` — 7 call sites, all now tagged diff --git a/compiler/tangle-lsp/docs/lsp-diagnostic-categories.md b/compiler/tangle-lsp/docs/lsp-diagnostic-categories.md deleted file mode 100644 index 484fd1b..0000000 --- a/compiler/tangle-lsp/docs/lsp-diagnostic-categories.md +++ /dev/null @@ -1,127 +0,0 @@ - -# `tangle-lsp` diagnostic categories - -This file documents the four categories `tangle-lsp` diagnostics fall -into. Together with the updated assumption `A-TG-9.1` in the repo-root -`ASSUMPTIONS.md`, they formalise the **TG-9 Option B** resolution from -issue #28. - -The bigger picture: obligation **TG-9** in `PROOF-NARRATIVE.md` says -every LSP diagnostic should correspond to a failure of the `HasType` -typing judgment in `proofs/Tangle.lean`. The 2026-06-01 audit -(issue #28) found that 6 of 7 diagnostic call sites have no `HasType` -counterpart. There were two options for closing the gap: - -- **Option A** — route every diagnostic through `compiler/lib/typecheck.ml` - via an OCaml↔Rust FFI. Higher engineering cost; the most principled. -- **Option B** — accept LSP-only diagnostics, document the categories, - and tag each call site with which category it belongs to. Lower cost; - what this file describes. - -Option B keeps the diagnostics where they help users while making the -"this is not a `HasType` failure" status explicit. Option A is queued -in #28 for follow-up. - -## The categories - -Each is denoted in the `Diagnostic.source` field as -`tangle-lsp[CATEGORY]`. - -### `PARSE_ERROR` - -Grammar-level rejection. Corresponds to the parser refusing malformed -input. Not a `HasType` failure but a legitimate language-level -rejection. - -Examples: -- Unbalanced parentheses, brackets, braces. - -Source location markers in `backend.rs`: -- `tangle-lsp[PARSE_ERROR]` — 3 sites (paren / bracket / brace). - -### `MISSPELLING_HINT` - -IDE-convenience hint. The user typed something close to a keyword. -No spec counterpart — the spec doesn't know about misspellings. - -Examples: -- `comput` instead of `compute`. -- `asert` instead of `assert`. - -Source location markers in `backend.rs`: -- `tangle-lsp[MISSPELLING_HINT]` — 1 site. - -### `STRUCTURAL_HINT` - -LSP-only structural heuristic. Tracks block nesting, weave-block -balance, etc. without a corresponding `HasType` rule. The `weave` -keyword in particular is part of a proposed v0.2 dialect not yet in -the core typing relation. - -Examples: -- Unclosed `weave` block. -- Suspicious block nesting depth. - -Source location markers in `backend.rs`: -- `tangle-lsp[STRUCTURAL_HINT]` — 2 sites. - -### `NAME_HINT` - -Possibly-undefined-reference hint. Implemented as `HINT` severity (the -softest LSP level) because identifiers may resolve via future imports -the lexical pass can't see. The OCaml typechecker raises a hard -exception on unbound variables; this LSP hint is the softer IDE-side -analogue. - -Source location markers in `backend.rs`: -- `tangle-lsp[NAME_HINT]` — 1 site. - -## How to add a new diagnostic - -1. Pick a category. If none fits, propose a new category in a PR that - updates this file **and** `ASSUMPTIONS.md` A-TG-9.1. -2. Tag the `Diagnostic.source` field with `tangle-lsp[CATEGORY]`. -3. Add a `// [CATEGORY]` comment immediately above the - `self.diagnostics.push(...)` call so reviewers can audit the - category set at-a-glance. - -## How this discharges TG-9 (Option B) - -`A-TG-9.1` previously said _"`tangle-lsp` reuses `compiler/lib/ -typecheck.ml` as the diagnostic engine (no LSP-only diagnostics)"_. -That was false; the audit (#28) confirmed it. - -Option B updates `A-TG-9.1` to: - -> `tangle-lsp` emits diagnostics in **four documented categories** -> (`PARSE_ERROR`, `MISSPELLING_HINT`, `STRUCTURAL_HINT`, `NAME_HINT`); -> only `PARSE_ERROR` corresponds to a grammar-level rejection. The -> other three are LSP-only by design, documented in -> `compiler/tangle-lsp/docs/lsp-diagnostic-categories.md`. - -This is a discipline shift: instead of pretending the LSP refines the -spec, we acknowledge the gap and document each step out. Option A -(real refinement via FFI to `typecheck.ml`) remains the long-term -target and is tracked in #28. - -## CI gate (proposed; queued for follow-up) - -A grep-based CI check could enforce: - -```bash -grep -rE 'self\.diagnostics\.push' compiler/tangle-lsp/src/ | - grep -v 'tangle-lsp\[(PARSE_ERROR|MISSPELLING_HINT|STRUCTURAL_HINT|NAME_HINT)\]' -``` - -Any unmatched diagnostic line means an untagged emission site. This -would be a 1d follow-up PR. - -## Cross-references - -- `PROOF-NARRATIVE.md` §3 TG-9 -- `ASSUMPTIONS.md` A-TG-9.1 (updated by this PR) -- Issue #28 — TG-9 audit findings + Options A/B -- `compiler/tangle-lsp/src/backend.rs` — 7 call sites, all now tagged diff --git a/dialects/README.adoc b/dialects/README.adoc new file mode 100644 index 0000000..b956ab8 --- /dev/null +++ b/dialects/README.adoc @@ -0,0 +1,78 @@ +== Tangle Dialects — hosted DSL scaffolds + +Tangle is a Turing-complete topological programming language. It is NOT +a DSL host by accident — it was designed to support compositional +calculi grounded in knot theory, category theory, and related algebraic +structures. + +This directory holds _scaffolds_ for DSLs that could be hosted on +Tangle. Each scaffold is an EBNF grammar sketch — evidence that the idea +is coherent and could be built out, not a complete implementation. + +=== The pattern + +When a DSL matures from sketch → alpha implementation: + +[arabic] +. Start with an EBNF grammar sketch here (`+grammar-sketch.ebnf+`) +. Write 1-3 example programs +. When ready to implement, decide whether it stays in-tree or graduates +to its own repository +. Implement the parser in Tangle’s OCaml front end or a sibling language +. Define its IR type + +No dialect has yet made this journey, so there is no precedent to follow +— these are all still at step 1. + +These sketches set out what a general multi-DSL host _would_ cover. They +do not yet evidence the claim: nothing here is implemented, and nothing +is currently built on Tangle. Implementing one of them end to end is +what would turn the claim into evidence. + +=== Current scaffolds + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|Dialect |Status |Domain +|link:braid-calculus/[braid-calculus] |sketch |Artin braid group Bn +calculus + +|link:quantum-circuit/[quantum-circuit] |sketch |Quantum circuit +compositional calculus + +|link:string-diagram/[string-diagram] |sketch |Monoidal/braided category +string diagrams + +|link:virtual-knot/[virtual-knot] |sketch |Kauffman virtual knot +calculus (extends braid-calculus with virtual crossings) + +|link:skein-algebra/[skein-algebra] |sketch |Skein algebra calculus +(Jones/HOMFLY-PT/Alexander; connects to Skein.jl + KnotTheory.jl) +|=== + +=== Relationship to KRL + +*KRL is not a Tangle dialect and never was.* It was previously listed +here as one that had "`graduated`" to its own repository; that was part +of a wider conflation of the two projects, corrected in `+README.adoc+` +and in the erratum to `+AFFIRMATION.adoc+`. + +KRL is the resolution language for +https://github.com/hyperpolymath/quandledb[QuandleDB], developed jointly +with it, and lives at +https://github.com/hyperpolymath/krl[hyperpolymath/krl]. It does not +compile to, lower into, or otherwise depend on Tangle. The two share a +subject matter, not an architecture. + +The scaffolds listed above are Tangle’s own dialects. + +=== Contribution + +To propose a new DSL scaffold: + +[arabic] +. Create `+dialects//+` with at minimum `+grammar-sketch.ebnf+` +. Write `+dialects//README.md+` explaining the domain + 1-2 +example programs +. Link from this README +. Keep it to a sketch — no implementation yet diff --git a/dialects/README.md b/dialects/README.md deleted file mode 100644 index 1cc271e..0000000 --- a/dialects/README.md +++ /dev/null @@ -1,67 +0,0 @@ - -# Tangle Dialects — hosted DSL scaffolds - -Tangle is a Turing-complete topological programming language. It is NOT -a DSL host by accident — it was designed to support compositional -calculi grounded in knot theory, category theory, and related algebraic -structures. - -This directory holds *scaffolds* for DSLs that could be hosted on Tangle. -Each scaffold is an EBNF grammar sketch — evidence that the idea is -coherent and could be built out, not a complete implementation. - -## The pattern - -When a DSL matures from sketch → alpha implementation: - -1. Start with an EBNF grammar sketch here (`grammar-sketch.ebnf`) -2. Write 1-3 example programs -3. When ready to implement, decide whether it stays in-tree or graduates to - its own repository -4. Implement the parser in Tangle's OCaml front end or a sibling language -5. Define its IR type - -No dialect has yet made this journey, so there is no precedent to follow — -these are all still at step 1. - -These sketches set out what a general multi-DSL host *would* cover. They do not -yet evidence the claim: nothing here is implemented, and nothing is currently -built on Tangle. Implementing one of them end to end is what would turn the -claim into evidence. - -## Current scaffolds - -| Dialect | Status | Domain | -|---|---|---| -| [braid-calculus](braid-calculus/) | sketch | Artin braid group Bn calculus | -| [quantum-circuit](quantum-circuit/) | sketch | Quantum circuit compositional calculus | -| [string-diagram](string-diagram/) | sketch | Monoidal/braided category string diagrams | -| [virtual-knot](virtual-knot/) | sketch | Kauffman virtual knot calculus (extends braid-calculus with virtual crossings) | -| [skein-algebra](skein-algebra/) | sketch | Skein algebra calculus (Jones/HOMFLY-PT/Alexander; connects to Skein.jl + KnotTheory.jl) | - -## Relationship to KRL - -**KRL is not a Tangle dialect and never was.** It was previously listed here as -one that had "graduated" to its own repository; that was part of a wider -conflation of the two projects, corrected in `README.adoc` and in the erratum to -`AFFIRMATION.adoc`. - -KRL is the resolution language for -[QuandleDB](https://github.com/hyperpolymath/quandledb), developed jointly with -it, and lives at [hyperpolymath/krl](https://github.com/hyperpolymath/krl). It -does not compile to, lower into, or otherwise depend on Tangle. The two share a -subject matter, not an architecture. - -The scaffolds listed above are Tangle's own dialects. - -## Contribution - -To propose a new DSL scaffold: - -1. Create `dialects//` with at minimum `grammar-sketch.ebnf` -2. Write `dialects//README.md` explaining the domain + 1-2 example programs -3. Link from this README -4. Keep it to a sketch — no implementation yet diff --git a/dialects/braid-calculus/README.adoc b/dialects/braid-calculus/README.adoc new file mode 100644 index 0000000..b629289 --- /dev/null +++ b/dialects/braid-calculus/README.adoc @@ -0,0 +1,41 @@ +== Braid Calculus — Tangle DSL Sketch + +*Status:* sketch. Grammar drafted; no parser or implementation yet. + +=== Domain + +A direct surface language for working in Artin braid groups Bₙ. Distinct +from KRL by being narrower: braids only, no closure, no knot +classification. The quotient map Bₙ → Knots is explicit via a `+close+` +primitive that hands off to KRL. + +=== What it supports + +* Generators σᵢ (braid crossings) with exponent +* Inverses σᵢ⁻¹ +* Multiplication of braid words +* Conjugation +* Markov moves (for knot invariant construction) + +=== What it does NOT do + +* Closure to knots (that’s KRL’s job — use `+as krl.close(b)+`) +* Invariant computation (that’s KnotTheory.jl’s job) +* Persistence (that’s Skein.jl’s job) + +=== Example + +[source,braid] +---- +let s1 = sigma 1 +let s2 = sigma 2 +let trefoil_braid = s1 * s1 * s1 +let trefoil_conj = s2 * trefoil_braid * inverse s2 +is_markov_equivalent(trefoil_braid, trefoil_conj) +---- + +=== See also + +* `+grammar-sketch.ebnf+` — formal grammar +* `+../../../krl/+` — knot resolution language (consumes braid words via +`+close+`) diff --git a/dialects/braid-calculus/README.md b/dialects/braid-calculus/README.md deleted file mode 100644 index eccf837..0000000 --- a/dialects/braid-calculus/README.md +++ /dev/null @@ -1,43 +0,0 @@ - -# Braid Calculus — Tangle DSL Sketch - -**Status:** sketch. Grammar drafted; no parser or implementation yet. - -## Domain - -A direct surface language for working in Artin braid groups Bₙ. -Distinct from KRL by being narrower: braids only, no closure, no knot -classification. The quotient map Bₙ → Knots is explicit via a `close` -primitive that hands off to KRL. - -## What it supports - -- Generators σᵢ (braid crossings) with exponent -- Inverses σᵢ⁻¹ -- Multiplication of braid words -- Conjugation -- Markov moves (for knot invariant construction) - -## What it does NOT do - -- Closure to knots (that's KRL's job — use `as krl.close(b)`) -- Invariant computation (that's KnotTheory.jl's job) -- Persistence (that's Skein.jl's job) - -## Example - -```braid -let s1 = sigma 1 -let s2 = sigma 2 -let trefoil_braid = s1 * s1 * s1 -let trefoil_conj = s2 * trefoil_braid * inverse s2 -is_markov_equivalent(trefoil_braid, trefoil_conj) -``` - -## See also - -- `grammar-sketch.ebnf` — formal grammar -- `../../../krl/` — knot resolution language (consumes braid words via `close`) diff --git a/dialects/quantum-circuit/README.adoc b/dialects/quantum-circuit/README.adoc new file mode 100644 index 0000000..c9709a3 --- /dev/null +++ b/dialects/quantum-circuit/README.adoc @@ -0,0 +1,40 @@ +== Quantum Circuit Calculus — Tangle DSL Sketch + +*Status:* sketch. Grammar drafted; no parser or implementation yet. + +=== Domain + +Compositional quantum-circuit calculus. Quantum gates map naturally to +Tangle’s compositional operations (sequential = gate-in-time, parallel = +gate-in-space via tensor product). + +=== What it supports + +* Standard gates (H, X, Y, Z, CNOT, T, S, Swap) +* Parameterised gates (Rx(θ), Ry(θ), Rz(θ), U3(θ, φ, λ)) +* Sequential composition (;) +* Parallel composition (⊗) via tensor +* Measurement operators + +=== What it does NOT do + +* Classical simulation (defer to Yao.jl / Qiskit) +* Hardware-specific calibration +* Noise modelling + +=== Example + +[source,qc] +---- +-- Bell state preparation +let bell = H on 0 ; CNOT (0, 1) ; + +-- Grover iteration kernel +let oracle = Z on 1 ; +let diffuser = (H on 0) ⊗ (H on 1) ; Z on 0 ; (H on 0) ⊗ (H on 1) ; +let grover_step = oracle ; diffuser ; +---- + +=== See also + +* `+grammar-sketch.ebnf+` — formal grammar diff --git a/dialects/quantum-circuit/README.md b/dialects/quantum-circuit/README.md deleted file mode 100644 index 91f147d..0000000 --- a/dialects/quantum-circuit/README.md +++ /dev/null @@ -1,43 +0,0 @@ - -# Quantum Circuit Calculus — Tangle DSL Sketch - -**Status:** sketch. Grammar drafted; no parser or implementation yet. - -## Domain - -Compositional quantum-circuit calculus. Quantum gates map naturally -to Tangle's compositional operations (sequential = gate-in-time, -parallel = gate-in-space via tensor product). - -## What it supports - -- Standard gates (H, X, Y, Z, CNOT, T, S, Swap) -- Parameterised gates (Rx(θ), Ry(θ), Rz(θ), U3(θ, φ, λ)) -- Sequential composition (;) -- Parallel composition (⊗) via tensor -- Measurement operators - -## What it does NOT do - -- Classical simulation (defer to Yao.jl / Qiskit) -- Hardware-specific calibration -- Noise modelling - -## Example - -```qc --- Bell state preparation -let bell = H on 0 ; CNOT (0, 1) ; - --- Grover iteration kernel -let oracle = Z on 1 ; -let diffuser = (H on 0) ⊗ (H on 1) ; Z on 0 ; (H on 0) ⊗ (H on 1) ; -let grover_step = oracle ; diffuser ; -``` - -## See also - -- `grammar-sketch.ebnf` — formal grammar diff --git a/dialects/skein-algebra/README.adoc b/dialects/skein-algebra/README.adoc new file mode 100644 index 0000000..ce14bbc --- /dev/null +++ b/dialects/skein-algebra/README.adoc @@ -0,0 +1,127 @@ +== Skein Algebra — Tangle DSL Sketch + +*Status:* sketch. Grammar drafted; no parser or implementation yet. + +=== Domain + +Skein algebras and skein modules. Given a 3-manifold M and a commutative +ring R with distinguished elements, the _skein module_ Sk(M; R) is the +free R-module on isotopy classes of framed links in M, quotiented by the +local skein relations. When M = Σ × [0,1] for a surface Σ, this acquires +an algebra structure (via stacking) and is called the _skein algebra_ of +Σ. + +This is why `+Skein.jl+` is named what it is: it is the persistence and +indexing layer for the knot-invariant stack, and knot polynomials arise +precisely from evaluating skein algebra elements. + +=== The three classical skein relations + +[cols=",,",options="header",] +|=== +|Name |Relation |Polynomial family +|HOMFLY-PT |P(L+) = a⁻¹ P(L₀) + z P(L-) |HOMFLY-PT (2-variable) +|Kauffman bracket |⟨L+⟩ = A ⟨L0⟩ + A⁻¹ ⟨L∞⟩ |Jones (via trace) +|Conway–Alexander |∇(L+) − ∇(L-) = z ∇(L₀) |Alexander (1-variable) +|=== + +Each defines a different skein module. This DSL is parametrised: the +`+using skein+` declaration chooses which relations are in scope. + +=== What it supports + +* Parameter declarations (the ring variables: `+A+`, `+q+`, `+z+`, etc.) +* Generator declarations (named framed link generators) +* Skein relation declarations (local rewriting rules) +* Linear combination expressions over the parameter ring +* Algebra product (stacking, written `+*+`) +* Predefined skein styles: `+homflypt+`, `+jones+`, `+alexander+` +* `+evaluate+` — apply a representation to produce a polynomial value +* Named element lookup against Skein.jl database (`+lookup+`) + +=== What it does NOT do + +* Categorical coherence proofs (those need Idris2/Agda/Lean) +* Computation of the skein algebra of an arbitrary 3-manifold (only link +complements and handlebodies are in scope for now) +* Quantum group module structure (future extension via TypeLL) + +=== Example + +[source,sk] +---- +-- Work in the Jones skein of S³ with parameter A +using jones ; +parameter A ; + +-- The Jones skein relation (Kauffman bracket normalised form) +-- Already built-in when "using jones" is declared. + +-- Define the trefoil as a generator (matches Skein.jl name "3_1") +generator trefoil : framed_link ; +relation trefoil = L+ ; -- shorthand: trefoil_braid closed + +-- Compute the Jones polynomial: evaluate the generator in the +-- standard Burau / Temperley-Lieb representation +evaluate (jones_rep, trefoil) ; + +-- Linear combination: HOMFLY-PT of (2 * unknot - trefoil) +using homflypt ; +parameter a, z ; +let combo = 2 * unknot - trefoil ; +evaluate (homflypt_rep, combo) ; + +-- Temperley-Lieb generators (quotient of Hecke algebra) +-- e₁ e₂ e₁ = e₁ (TL relation) +generator e1, e2 : framed_link ; +relation (e1 * e2 * e1) = (delta * e1) ; -- delta = -A² - A⁻² +relation (e1 * e1) = (delta * e1) ; + +-- Lookup a named knot's skein polynomial from Skein.jl +lookup "3_1" jones_rep ; +lookup "8_18" homflypt_rep ; +---- + +=== Connection to TangleIR + +Skein algebra elements lower to TangleIR as follows: + +* A _framed link generator_ lowers to a closed `+TangleIR+` (via +`+close_tangle+`) +* A _linear combination_ stays in the skein layer — it is a formal sum +of TangleIR values with ring-element coefficients, not a single IR +* A _relation_ is a rewrite rule on TangleIR that mirrors Reidemeister +simplification but is parametrised by the ring variables +* `+evaluate(rep, e)+` calls into KnotTheory.jl for the actual +polynomial + +The three skein styles (`+jones+`, `+homflypt+`, `+alexander+`) +correspond to the three polynomial families already computed by +KnotTheory.jl. + +=== Relationship to other dialects + +* *KRL*: KRL builds tangles (open diagrams); skein-algebra works with +_closed_ links (elements of the skein module). KRL’s `+close+` operation +is the bridge — `+close+` a KRL tangle to get a skein element. +* *string-diagram*: the Temperley-Lieb generators e₁…eₙ₋₁ are morphisms +in a pivotal monoidal category — a special case of string-diagram +calculus with the skein relation as the extra axiom. +* *Skein.jl*: the persistence layer. `+lookup+` queries it; `+evaluate+` +writes computed polynomials back to it. +* *KnotTheory.jl*: the computation layer. `+evaluate(jones_rep, e)+` +routes to `+jones_polynomial+` in KnotTheory.jl. + +=== See also + +* `+grammar-sketch.ebnf+` — formal grammar +* Przytycki, J.H. & Traczyk, P. (1987). _Invariants of links of Conway +type_. Kobe J. Math. 4, 115–139. (HOMFLY-PT relation) +* Kauffman, L.H. (1987). _State models and the Jones polynomial_. +Topology 26(3), 395–407. (Kauffman bracket) +* `+../../KRLAdapter.jl/+` — adapter that lowers KRL → TangleIR (same IR +target) +* `+../string-diagram/+` — monoidal category calculus (TL algebra is a +special case) +* `+../../krl/+` — knot resolution language (constructs the TangleIR +inputs) diff --git a/dialects/skein-algebra/README.md b/dialects/skein-algebra/README.md deleted file mode 100644 index a3f33d9..0000000 --- a/dialects/skein-algebra/README.md +++ /dev/null @@ -1,124 +0,0 @@ - - - -# Skein Algebra — Tangle DSL Sketch - -**Status:** sketch. Grammar drafted; no parser or implementation yet. - -## Domain - -Skein algebras and skein modules. Given a 3-manifold M and a -commutative ring R with distinguished elements, the *skein module* -Sk(M; R) is the free R-module on isotopy classes of framed links in M, -quotiented by the local skein relations. When M = Σ × [0,1] for a -surface Σ, this acquires an algebra structure (via stacking) and is -called the *skein algebra* of Σ. - -This is why `Skein.jl` is named what it is: it is the persistence and -indexing layer for the knot-invariant stack, and knot polynomials -arise precisely from evaluating skein algebra elements. - -## The three classical skein relations - -| Name | Relation | Polynomial family | -|---|---|---| -| HOMFLY-PT | P(L+) = a⁻¹ P(L₀) + z P(L-) | HOMFLY-PT (2-variable) | -| Kauffman bracket | ⟨L+⟩ = A ⟨L0⟩ + A⁻¹ ⟨L∞⟩ | Jones (via trace) | -| Conway–Alexander | ∇(L+) − ∇(L-) = z ∇(L₀) | Alexander (1-variable) | - -Each defines a different skein module. This DSL is parametrised: the -`using skein` declaration chooses which relations are in scope. - -## What it supports - -- Parameter declarations (the ring variables: `A`, `q`, `z`, etc.) -- Generator declarations (named framed link generators) -- Skein relation declarations (local rewriting rules) -- Linear combination expressions over the parameter ring -- Algebra product (stacking, written `*`) -- Predefined skein styles: `homflypt`, `jones`, `alexander` -- `evaluate` — apply a representation to produce a polynomial value -- Named element lookup against Skein.jl database (`lookup`) - -## What it does NOT do - -- Categorical coherence proofs (those need Idris2/Agda/Lean) -- Computation of the skein algebra of an arbitrary 3-manifold (only - link complements and handlebodies are in scope for now) -- Quantum group module structure (future extension via TypeLL) - -## Example - -```sk --- Work in the Jones skein of S³ with parameter A -using jones ; -parameter A ; - --- The Jones skein relation (Kauffman bracket normalised form) --- Already built-in when "using jones" is declared. - --- Define the trefoil as a generator (matches Skein.jl name "3_1") -generator trefoil : framed_link ; -relation trefoil = L+ ; -- shorthand: trefoil_braid closed - --- Compute the Jones polynomial: evaluate the generator in the --- standard Burau / Temperley-Lieb representation -evaluate (jones_rep, trefoil) ; - --- Linear combination: HOMFLY-PT of (2 * unknot - trefoil) -using homflypt ; -parameter a, z ; -let combo = 2 * unknot - trefoil ; -evaluate (homflypt_rep, combo) ; - --- Temperley-Lieb generators (quotient of Hecke algebra) --- e₁ e₂ e₁ = e₁ (TL relation) -generator e1, e2 : framed_link ; -relation (e1 * e2 * e1) = (delta * e1) ; -- delta = -A² - A⁻² -relation (e1 * e1) = (delta * e1) ; - --- Lookup a named knot's skein polynomial from Skein.jl -lookup "3_1" jones_rep ; -lookup "8_18" homflypt_rep ; -``` - -## Connection to TangleIR - -Skein algebra elements lower to TangleIR as follows: - -- A *framed link generator* lowers to a closed `TangleIR` (via `close_tangle`) -- A *linear combination* stays in the skein layer — it is a formal sum - of TangleIR values with ring-element coefficients, not a single IR -- A *relation* is a rewrite rule on TangleIR that mirrors Reidemeister - simplification but is parametrised by the ring variables -- `evaluate(rep, e)` calls into KnotTheory.jl for the actual polynomial - -The three skein styles (`jones`, `homflypt`, `alexander`) correspond -to the three polynomial families already computed by KnotTheory.jl. - -## Relationship to other dialects - -- **KRL**: KRL builds tangles (open diagrams); skein-algebra works with - *closed* links (elements of the skein module). KRL's `close` operation - is the bridge — `close` a KRL tangle to get a skein element. -- **string-diagram**: the Temperley-Lieb generators e₁…eₙ₋₁ are - morphisms in a pivotal monoidal category — a special case of - string-diagram calculus with the skein relation as the extra axiom. -- **Skein.jl**: the persistence layer. `lookup` queries it; - `evaluate` writes computed polynomials back to it. -- **KnotTheory.jl**: the computation layer. `evaluate(jones_rep, e)` - routes to `jones_polynomial` in KnotTheory.jl. - -## See also - -- `grammar-sketch.ebnf` — formal grammar -- Przytycki, J.H. & Traczyk, P. (1987). *Invariants of links of Conway type*. - Kobe J. Math. 4, 115–139. (HOMFLY-PT relation) -- Kauffman, L.H. (1987). *State models and the Jones polynomial*. - Topology 26(3), 395–407. (Kauffman bracket) -- `../../KRLAdapter.jl/` — adapter that lowers KRL → TangleIR (same IR target) -- `../string-diagram/` — monoidal category calculus (TL algebra is a special case) -- `../../krl/` — knot resolution language (constructs the TangleIR inputs) diff --git a/dialects/string-diagram/README.adoc b/dialects/string-diagram/README.adoc new file mode 100644 index 0000000..ca2229e --- /dev/null +++ b/dialects/string-diagram/README.adoc @@ -0,0 +1,53 @@ +== String Diagram Calculus — Tangle DSL Sketch + +*Status:* sketch. Grammar drafted; no parser or implementation yet. + +=== Domain + +Monoidal/braided category string diagrams. Surface syntax for working +with morphisms in a symmetric or braided monoidal category, with +composition (∘), tensor (⊗), identity, and structural morphisms +(associator, unitor, braiding). + +=== What it supports + +* Object and morphism declarations +* Sequential composition (∘, or `+then+`) +* Tensor product (⊗, or `+tensor+`) +* Identity morphism on an object +* Braiding / symmetry +* Unit object / unitor +* Associator + +=== What it does NOT do + +* Type checking beyond domain/codomain matching (would need TypeLL for +that) +* Categorical coherence proofs (would need Agda/Lean) +* Graphical rendering + +=== Example + +[source,sd] +---- +object A, B, C ; +morphism f : A -> B ; +morphism g : B -> C ; +morphism h : A -> A ; + +let gf = f then g ; -- sequential composition A -> C +let f_id = f tensor (id A) ; -- parallel with identity +let braid = braiding A B ; -- symmetric structure +---- + +=== Connection to TangleIR + +String diagrams generalise tangles: a tangle is a specific string +diagram in a braided monoidal category where objects are "`strands`" and +morphisms are crossings/caps/cups. KRL’s `+close+`, `+tensor+`, +`+mirror+` operations correspond to categorical operations on string +diagrams. + +=== See also + +* `+grammar-sketch.ebnf+` — formal grammar diff --git a/dialects/string-diagram/README.md b/dialects/string-diagram/README.md deleted file mode 100644 index a4aef09..0000000 --- a/dialects/string-diagram/README.md +++ /dev/null @@ -1,54 +0,0 @@ - -# String Diagram Calculus — Tangle DSL Sketch - -**Status:** sketch. Grammar drafted; no parser or implementation yet. - -## Domain - -Monoidal/braided category string diagrams. Surface syntax for working -with morphisms in a symmetric or braided monoidal category, with -composition (∘), tensor (⊗), identity, and structural morphisms -(associator, unitor, braiding). - -## What it supports - -- Object and morphism declarations -- Sequential composition (∘, or `then`) -- Tensor product (⊗, or `tensor`) -- Identity morphism on an object -- Braiding / symmetry -- Unit object / unitor -- Associator - -## What it does NOT do - -- Type checking beyond domain/codomain matching (would need TypeLL for that) -- Categorical coherence proofs (would need Agda/Lean) -- Graphical rendering - -## Example - -```sd -object A, B, C ; -morphism f : A -> B ; -morphism g : B -> C ; -morphism h : A -> A ; - -let gf = f then g ; -- sequential composition A -> C -let f_id = f tensor (id A) ; -- parallel with identity -let braid = braiding A B ; -- symmetric structure -``` - -## Connection to TangleIR - -String diagrams generalise tangles: a tangle is a specific string -diagram in a braided monoidal category where objects are "strands" and -morphisms are crossings/caps/cups. KRL's `close`, `tensor`, `mirror` -operations correspond to categorical operations on string diagrams. - -## See also - -- `grammar-sketch.ebnf` — formal grammar diff --git a/dialects/virtual-knot/README.adoc b/dialects/virtual-knot/README.adoc new file mode 100644 index 0000000..938c21e --- /dev/null +++ b/dialects/virtual-knot/README.adoc @@ -0,0 +1,121 @@ +== Virtual Knot Calculus — Tangle DSL Sketch + +*Status:* sketch. Grammar drafted; no parser or implementation yet. + +=== Domain + +Virtual knot calculus, following Kauffman (1999). Virtual knots extend +classical braid/knot theory by adding a second, purely formal crossing +type — the _virtual crossing_ — which arises when a knot diagram on a +higher-genus surface Σ_g is projected to the plane. Virtual crossings +are NOT real crossings; they are placeholders recording where strands +pass each other in the diagram without interacting. + +This DSL is strictly an extension of `+braid-calculus/+`. Every +braid-calculus program is valid virtual-knot source; the converse is +false — virtual crossings have no classical counterpart. + +=== Key concepts + +==== Classical vs virtual crossings + +[cols=",,",options="header",] +|=== +|Generator |Symbol |Meaning +|`+sigma n+` |σₙ |Positive classical crossing at strand n +|`+sigma_inv n+` |σₙ⁻¹ |Negative classical crossing at strand n +|`+virtual n+` |νₙ |Virtual crossing at strand n (unsigned) +|=== + +Virtual crossings obey the _virtual Reidemeister moves_ (vR1–vR3) but +are immune to the classical R3 move when mixed with classical crossings. +The _forbidden move_ — letting a classical crossing pass a virtual one +via an R3-like move — is explicitly banned; including it collapses +virtual knot theory to classical. + +==== Detour move + +Any arc that passes through only virtual crossings can be rerouted +freely (the _detour move_). This is virtual knot theory’s analogue of +the classical isotopy invariance under planar isotopy. + +==== Gauss codes + +Virtual knots are conveniently specified by their Gauss codes — an +alternative to braid words. The Gauss code records, for each crossing, +whether the strand is over or under, and the sign. Virtual crossings +appear in the Gauss code as unsigned entries. This DSL supports both +notations. + +=== What it supports + +* Classical generators σᵢ, σᵢ⁻¹ with integer strand index +* Virtual generators νᵢ (unsigned) at strand index +* Braid-word multiplication (`+*+`) +* Inverse of a braid word +* Closure to a virtual knot diagram (`+close+`) +* Gauss code literals for direct specification +* Predicate: `+is_classical?+` (tests whether a virtual knot is +equivalent to a classical one — decidable for small Gauss codes) + +=== What it does NOT do + +* Perform the forbidden move (explicitly excluded — doing so collapses +the theory) +* Classical knot invariants directly (hand off to KRL → KnotTheory.jl) +* Slice genus computation (open problem for virtual knots) +* Arrow calculus (Kauffman’s signed arrow variant — future extension) + +=== Example + +[source,vk] +---- +-- The virtual trefoil: a Gauss code unrealisable on S² +-- Gauss code: O1+ U2+ O2+ U1+ O3+ U3+ (virtual at positions 2,3) +let vtrefoil = gauss_code [O 1 +, U 2 +, virtual 2, U 1 +, O 3 +, U 3 +] ; + +-- A classical knot expressed as a virtual braid word +let trefoil_braid = sigma 1 * sigma 1 * sigma 1 ; + +-- Mixed classical-virtual braid (the forbidden move is NOT applied here) +let mixed = sigma 1 * virtual 2 * sigma_inv 1 ; + +-- Test whether a virtual knot is equivalent to a classical knot +is_classical? vtrefoil ; -- expected: false +is_classical? (close trefoil_braid) ; -- expected: true + +-- Closure of a virtual braid +let closed_mixed = close mixed ; +---- + +=== Connection to TangleIR + +In TangleIR terms, virtual crossings can be represented as +`+CrossingIR+` nodes with `+sign = 0+` (a value unused by classical +crossings, which use ±1). The lowering rule is: + +.... +virtual_gen(n) → CrossingIR(id, 0, (1,2,3,4)) -- sign = 0 +.... + +The detour move corresponds to a rewrite on the `+crossings+` vector +that removes consecutive virtual crossings on the same arc pair. A +future `+simplify_virtual_ir+` function would implement this. + +=== Relationship to other dialects + +* *braid-calculus*: this dialect extends it — every braid-calculus +program parses as valid virtual-knot source +* *KRL*: classical virtual knots that pass `+is_classical?+` can be +exported to KRL for invariant computation via `+as krl+` +* *string-diagram*: virtual knots are morphisms in a _free braided +monoidal category without the Yang-Baxter equation on virtual crossings_ + +=== See also + +* `+grammar-sketch.ebnf+` — formal grammar +* Kauffman, L.H. (1999). _Virtual Knot Theory_. European J. +Combinatorics, 20(7), 663–690. +* `+../../krl/+` — knot resolution language (classical knots only) +* `+../braid-calculus/+` — classical Artin braid group (this dialect +extends it) diff --git a/dialects/virtual-knot/README.md b/dialects/virtual-knot/README.md deleted file mode 100644 index 08c8695..0000000 --- a/dialects/virtual-knot/README.md +++ /dev/null @@ -1,120 +0,0 @@ - - - -# Virtual Knot Calculus — Tangle DSL Sketch - -**Status:** sketch. Grammar drafted; no parser or implementation yet. - -## Domain - -Virtual knot calculus, following Kauffman (1999). Virtual knots extend -classical braid/knot theory by adding a second, purely formal crossing -type — the *virtual crossing* — which arises when a knot diagram on a -higher-genus surface Σ_g is projected to the plane. Virtual crossings -are NOT real crossings; they are placeholders recording where strands -pass each other in the diagram without interacting. - -This DSL is strictly an extension of `braid-calculus/`. Every -braid-calculus program is valid virtual-knot source; the converse -is false — virtual crossings have no classical counterpart. - -## Key concepts - -### Classical vs virtual crossings - -| Generator | Symbol | Meaning | -|---|---|---| -| `sigma n` | σₙ | Positive classical crossing at strand n | -| `sigma_inv n` | σₙ⁻¹ | Negative classical crossing at strand n | -| `virtual n` | νₙ | Virtual crossing at strand n (unsigned) | - -Virtual crossings obey the *virtual Reidemeister moves* (vR1–vR3) but -are immune to the classical R3 move when mixed with classical crossings. -The *forbidden move* — letting a classical crossing pass a virtual one -via an R3-like move — is explicitly banned; including it collapses -virtual knot theory to classical. - -### Detour move - -Any arc that passes through only virtual crossings can be rerouted -freely (the *detour move*). This is virtual knot theory's analogue of -the classical isotopy invariance under planar isotopy. - -### Gauss codes - -Virtual knots are conveniently specified by their Gauss codes — an -alternative to braid words. The Gauss code records, for each crossing, -whether the strand is over or under, and the sign. Virtual crossings -appear in the Gauss code as unsigned entries. This DSL supports both -notations. - -## What it supports - -- Classical generators σᵢ, σᵢ⁻¹ with integer strand index -- Virtual generators νᵢ (unsigned) at strand index -- Braid-word multiplication (`*`) -- Inverse of a braid word -- Closure to a virtual knot diagram (`close`) -- Gauss code literals for direct specification -- Predicate: `is_classical?` (tests whether a virtual knot is equivalent - to a classical one — decidable for small Gauss codes) - -## What it does NOT do - -- Perform the forbidden move (explicitly excluded — doing so collapses - the theory) -- Classical knot invariants directly (hand off to KRL → KnotTheory.jl) -- Slice genus computation (open problem for virtual knots) -- Arrow calculus (Kauffman's signed arrow variant — future extension) - -## Example - -```vk --- The virtual trefoil: a Gauss code unrealisable on S² --- Gauss code: O1+ U2+ O2+ U1+ O3+ U3+ (virtual at positions 2,3) -let vtrefoil = gauss_code [O 1 +, U 2 +, virtual 2, U 1 +, O 3 +, U 3 +] ; - --- A classical knot expressed as a virtual braid word -let trefoil_braid = sigma 1 * sigma 1 * sigma 1 ; - --- Mixed classical-virtual braid (the forbidden move is NOT applied here) -let mixed = sigma 1 * virtual 2 * sigma_inv 1 ; - --- Test whether a virtual knot is equivalent to a classical knot -is_classical? vtrefoil ; -- expected: false -is_classical? (close trefoil_braid) ; -- expected: true - --- Closure of a virtual braid -let closed_mixed = close mixed ; -``` - -## Connection to TangleIR - -In TangleIR terms, virtual crossings can be represented as -`CrossingIR` nodes with `sign = 0` (a value unused by classical -crossings, which use ±1). The lowering rule is: - - virtual_gen(n) → CrossingIR(id, 0, (1,2,3,4)) -- sign = 0 - -The detour move corresponds to a rewrite on the `crossings` vector -that removes consecutive virtual crossings on the same arc pair. A -future `simplify_virtual_ir` function would implement this. - -## Relationship to other dialects - -- **braid-calculus**: this dialect extends it — every braid-calculus program - parses as valid virtual-knot source -- **KRL**: classical virtual knots that pass `is_classical?` can be - exported to KRL for invariant computation via `as krl` -- **string-diagram**: virtual knots are morphisms in a *free braided - monoidal category without the Yang-Baxter equation on virtual crossings* - -## See also - -- `grammar-sketch.ebnf` — formal grammar -- Kauffman, L.H. (1999). *Virtual Knot Theory*. European J. Combinatorics, 20(7), 663–690. -- `../../krl/` — knot resolution language (classical knots only) -- `../braid-calculus/` — classical Artin braid group (this dialect extends it) diff --git a/docs/echo-types-ocaml-pipeline.adoc b/docs/echo-types-ocaml-pipeline.adoc new file mode 100644 index 0000000..77f6764 --- /dev/null +++ b/docs/echo-types-ocaml-pipeline.adoc @@ -0,0 +1,213 @@ +== Echo Types — OCaml Pipeline Integration + +____ +*Status*: Complete (PRs #45, #46, merged 2026-06-14). This page is the +developer reference for the echo/product type integration in the OCaml +compiler pipeline. For the formal metatheory see +link:../PROOF-NARRATIVE.md[PROOF-NARRATIVE.md §2.5] and +link:../proofs/Tangle.lean[`+proofs/Tangle.lean+` §ECHO-TYPES]. For the +cross-repo contract with QuandleDB see +link:spec/ECHO-TANGLEIR-THREADING.md[ECHO-TANGLEIR-THREADING.md]. +____ + +''''' + +=== 1. What are echo types? + +Echo types make structured loss *recoverable at the type level*. +Tangle’s canonical lossy operation is `+close : Word[n] → Word[0]+`, +which collapses any braid to the identity, discarding the word. An +`+Echo ρ τ+` value is a pair: + +* *result* (`+τ+`) — what the lossy operation produces +* *residue* (`+ρ+`) — the pre-closure braid, retained in the type + +The design mirrors `+Echo f y := Σ (x : A), f x ≡ y+` from +`+hyperpolymath/echo-types+` (`+Echo.agda+`) in Tangle’s simply-typed +setting. + +The *product type* `+ρ × σ+` serves as the residue carrier for binary +lossy operations: `+echoAdd+` keeps both summands, `+echoEq+` keeps both +operands. + +''''' + +=== 2. Surface syntax + +[width="100%",cols="45%,22%,33%",options="header",] +|=== +|Expression |Type |Meaning +|`+echoClose(e)+` |`+Word[n] → Echo (Word[n]) (Word[0])+` |Close a +braid, retaining the original as residue + +|`+lower(e)+` |`+Echo ρ τ → τ+` |Project to the result (forget the +residue) + +|`+residue(e)+` |`+Echo ρ τ → ρ+` |Recover the witness braid + +|`+pair(a, b)+` |`+α → β → α × β+` |Construct a product + +|`+fst(e)+` |`+α × β → α+` |First projection + +|`+snd(e)+` |`+α × β → β+` |Second projection + +|`+echoAdd(a, b)+` |`+Num → Num → Echo (Num × Num) Num+` |Addition +retaining summand pair as residue + +|`+echoEq(a, b)+` |`+ρ → ρ → Echo (ρ × ρ) Bool+` |Equality retaining +operand pair as residue +|=== + +''''' + +=== 3. OCaml pipeline layers + +==== 3.1 AST (`+compiler/lib/ast.ml+`) + +[source,ocaml] +---- +type expr = + ... + | EchoClose of expr + | Lower of expr + | Residue of expr + | Pair of expr * expr + | Fst of expr + | Snd of expr + | EchoAdd of expr * expr + | EchoEq of expr * expr + +type ty = + ... + | TProd of ty * ty (* ρ × σ — product residue carrier *) + | TEcho of ty * ty (* Echo ρ τ *) +---- + +==== 3.2 Typechecker (`+compiler/lib/typecheck.ml+`) + +Eight new `+infer_expr+` cases, all mirroring Lean `+HasType+`: + +[width="100%",cols="32%,30%,38%",options="header",] +|=== +|OCaml rule |Lean rule |Type produced +|`+EchoClose e+` |`+tEchoClose+` +|`+TEcho (TEcho(Word[n], inferred_width), TWord 0)+` → simplified to +`+TEcho(ρ, TWord 0)+` + +|`+Lower e+` |`+tLower+` |`+τ+` (from `+TEcho ρ τ+`) + +|`+Residue e+` |`+tResidue+` |`+ρ+` (from `+TEcho ρ τ+`) + +|`+Pair(a, b)+` |`+tPair+` |`+TProd(α, β)+` + +|`+Fst e+` |`+tFst+` |`+α+` (from `+TProd α β+`) + +|`+Snd e+` |`+tSnd+` |`+β+` (from `+TProd α β+`) + +|`+EchoAdd(a, b)+` |`+tEchoAdd+` |`+TEcho(TProd(TNum, TNum), TNum)+` + +|`+EchoEq(a, b)+` |`+tEchoEqWord/Num/Str+` +|`+TEcho(TProd(ρ, ρ), TBool)+` +|=== + +==== 3.3 Evaluator (`+compiler/lib/eval.ml+`) + +New value forms: + +[source,ocaml] +---- +type value = + ... + | VEcho of value * value (* (residue, result) — Option B uniform form *) + | VPair of value * value (* product value *) +---- + +Echo values use the *Option B* uniform shape: `+VEcho(residue, result)+` +in all cases. `+echoClose+` produces `+VEcho(v, VBraid [])+`, where +`+VBraid []+` is Tangle’s identity value (Word[0], the same point +`+close+`/`+Identity+` yields). `+echoAdd+` produces +`+VEcho(VPair(VInt n1, VInt n2), VInt(n1 + n2))+`. `+echoEq+` produces +`+VEcho(VPair(v1, v2), VBool(v1 = v2))+`. + +==== 3.4 Lexer / parser / tokens + +Tokens (`+compiler/lib/token.ml+`): `+ECHOCLOSE+`, `+LOWER+`, +`+RESIDUE+`, `+PAIR+`, `+FST+`, `+SND+`, `+ECHOADD+`, `+ECHOEQ+` + +All 8 keywords are registered in the lexer (`+lexer.mll+`) and have +dedicated grammar productions in `+parser.mly+` following the existing +unary (`+KW LPAREN expr RPAREN+`) and binary +(`+KW LPAREN expr COMMA expr RPAREN+`) patterns. + +==== 3.5 Pretty printer (`+compiler/lib/pretty.ml+`) + +All 8 forms pretty-print to the same surface syntax that the parser +accepts, satisfying the TG-4 round-trip obligation. + +''''' + +=== 4. Round-trip guarantee (TG-4) + +`+compiler/test/test_roundtrip.ml+` tests `+parse(pretty(e)) = e+` and +`+pretty(parse(pretty(parse(s)))) = pretty(parse(s))+` for every +constructor. + +Echo/product entries: `+echoClose+`, `+lower+`, `+residue+`, `+pair+`, +`+fst+`, `+snd+`, `+echoAdd+`, `+echoEq+` — 16 test cases (8 basic + 8 +idempotent), all passing as of PR #46. + +''''' + +=== 5. Proof coverage + +The formal spec (`+proofs/Tangle.lean+`) covers the complete +echo+product fragment: + +[width="100%",cols="57%,43%",options="header",] +|=== +|Lean theorem |Coverage +|`+T-Progress+` |All 8 echo/product expression forms + +|`+T-Preservation+` |All 8 echo/product expression forms + +|`+T-Determinism+` |All 8 echo/product expression forms + +|`+T-TypeSafety+` |Corollary (progress + preservation) + +|`+echo_lower_collapses+` |Every closed braid lowers to `+identity+` + +|`+echo_residue_recovers+` +|`+residue(echoClose(braid[gs])) →* braid[gs]+` + +|`+echo_distinguishes_collapsed+` |Distinct braids keep distinct +residues after `+lower+` + +|`+echo_roundtrip_typed+` |Round-trip is well-typed +|=== + +The OCaml typechecker is proven to refine `+HasType+` on the core +fragment at the translation-validation level (TG-3, *landed* — see +link:../proofs/TG3-REFINEMENT.md[`+proofs/TG3-REFINEMENT.md+`]): +`+proofs/TG3Differential.lean+` emits 496 obligations +`+infer [] e = := by decide+` that Lean’s proven +`+infer+` kernel-checks, and the echo/product ops above are all in the +validated core. The two documented divergences are `+close+` (OCaml +`+Tangle[I,I]+` vs Lean `+Word[0]+`) and `+Bool == Bool+` (OCaml +extra-core convenience; Lean rejects). + +''''' + +=== 6. Known gaps and future work + +[width="100%",cols="34%,66%",options="header",] +|=== +|Gap |Tracking +|TG-3 universal proof (reflect `+typecheck.ml+` in Lean) — current +discharge is translation validation over a core-fragment corpus +|PROOF-NEEDS.md TG-3 / TG3-REFINEMENT.md §7 + +|TangleIR: thread echo residue into the *Julia* schema (OCaml +`+EchoClosed+` node landed) |ECHO-TANGLEIR-THREADING.md + +|`+echoClose+` in WASM backend |tangle-wasm (not yet implemented) +|=== diff --git a/docs/echo-types-ocaml-pipeline.md b/docs/echo-types-ocaml-pipeline.md deleted file mode 100644 index a5b8d52..0000000 --- a/docs/echo-types-ocaml-pipeline.md +++ /dev/null @@ -1,161 +0,0 @@ - -# Echo Types — OCaml Pipeline Integration - -> **Status**: Complete (PRs #45, #46, merged 2026-06-14). -> This page is the developer reference for the echo/product type integration -> in the OCaml compiler pipeline. For the formal metatheory see -> [PROOF-NARRATIVE.md §2.5](../PROOF-NARRATIVE.md) and -> [`proofs/Tangle.lean` §ECHO-TYPES](../proofs/Tangle.lean). -> For the cross-repo contract with QuandleDB see -> [ECHO-TANGLEIR-THREADING.md](spec/ECHO-TANGLEIR-THREADING.md). - ---- - -## 1. What are echo types? - -Echo types make structured loss **recoverable at the type level**. Tangle's -canonical lossy operation is `close : Word[n] → Word[0]`, which collapses any -braid to the identity, discarding the word. An `Echo ρ τ` value is a pair: - -- **result** (`τ`) — what the lossy operation produces -- **residue** (`ρ`) — the pre-closure braid, retained in the type - -The design mirrors `Echo f y := Σ (x : A), f x ≡ y` from -`hyperpolymath/echo-types` (`Echo.agda`) in Tangle's simply-typed setting. - -The **product type** `ρ × σ` serves as the residue carrier for binary lossy -operations: `echoAdd` keeps both summands, `echoEq` keeps both operands. - ---- - -## 2. Surface syntax - -| Expression | Type | Meaning | -|------------|------|---------| -| `echoClose(e)` | `Word[n] → Echo (Word[n]) (Word[0])` | Close a braid, retaining the original as residue | -| `lower(e)` | `Echo ρ τ → τ` | Project to the result (forget the residue) | -| `residue(e)` | `Echo ρ τ → ρ` | Recover the witness braid | -| `pair(a, b)` | `α → β → α × β` | Construct a product | -| `fst(e)` | `α × β → α` | First projection | -| `snd(e)` | `α × β → β` | Second projection | -| `echoAdd(a, b)` | `Num → Num → Echo (Num × Num) Num` | Addition retaining summand pair as residue | -| `echoEq(a, b)` | `ρ → ρ → Echo (ρ × ρ) Bool` | Equality retaining operand pair as residue | - ---- - -## 3. OCaml pipeline layers - -### 3.1 AST (`compiler/lib/ast.ml`) - -```ocaml -type expr = - ... - | EchoClose of expr - | Lower of expr - | Residue of expr - | Pair of expr * expr - | Fst of expr - | Snd of expr - | EchoAdd of expr * expr - | EchoEq of expr * expr - -type ty = - ... - | TProd of ty * ty (* ρ × σ — product residue carrier *) - | TEcho of ty * ty (* Echo ρ τ *) -``` - -### 3.2 Typechecker (`compiler/lib/typecheck.ml`) - -Eight new `infer_expr` cases, all mirroring Lean `HasType`: - -| OCaml rule | Lean rule | Type produced | -|-----------|-----------|--------------| -| `EchoClose e` | `tEchoClose` | `TEcho (TEcho(Word[n], inferred_width), TWord 0)` → simplified to `TEcho(ρ, TWord 0)` | -| `Lower e` | `tLower` | `τ` (from `TEcho ρ τ`) | -| `Residue e` | `tResidue` | `ρ` (from `TEcho ρ τ`) | -| `Pair(a, b)` | `tPair` | `TProd(α, β)` | -| `Fst e` | `tFst` | `α` (from `TProd α β`) | -| `Snd e` | `tSnd` | `β` (from `TProd α β`) | -| `EchoAdd(a, b)` | `tEchoAdd` | `TEcho(TProd(TNum, TNum), TNum)` | -| `EchoEq(a, b)` | `tEchoEqWord/Num/Str` | `TEcho(TProd(ρ, ρ), TBool)` | - -### 3.3 Evaluator (`compiler/lib/eval.ml`) - -New value forms: - -```ocaml -type value = - ... - | VEcho of value * value (* (residue, result) — Option B uniform form *) - | VPair of value * value (* product value *) -``` - -Echo values use the **Option B** uniform shape: `VEcho(residue, result)` in all -cases. `echoClose` produces `VEcho(v, VBraid [])`, where `VBraid []` is Tangle's -identity value (Word[0], the same point `close`/`Identity` yields). `echoAdd` -produces `VEcho(VPair(VInt n1, VInt n2), VInt(n1 + n2))`. `echoEq` produces -`VEcho(VPair(v1, v2), VBool(v1 = v2))`. - -### 3.4 Lexer / parser / tokens - -Tokens (`compiler/lib/token.ml`): -`ECHOCLOSE`, `LOWER`, `RESIDUE`, `PAIR`, `FST`, `SND`, `ECHOADD`, `ECHOEQ` - -All 8 keywords are registered in the lexer (`lexer.mll`) and have dedicated -grammar productions in `parser.mly` following the existing unary -(`KW LPAREN expr RPAREN`) and binary (`KW LPAREN expr COMMA expr RPAREN`) patterns. - -### 3.5 Pretty printer (`compiler/lib/pretty.ml`) - -All 8 forms pretty-print to the same surface syntax that the parser accepts, -satisfying the TG-4 round-trip obligation. - ---- - -## 4. Round-trip guarantee (TG-4) - -`compiler/test/test_roundtrip.ml` tests `parse(pretty(e)) = e` and -`pretty(parse(pretty(parse(s)))) = pretty(parse(s))` for every constructor. - -Echo/product entries: -`echoClose`, `lower`, `residue`, `pair`, `fst`, `snd`, `echoAdd`, `echoEq` -— 16 test cases (8 basic + 8 idempotent), all passing as of PR #46. - ---- - -## 5. Proof coverage - -The formal spec (`proofs/Tangle.lean`) covers the complete echo+product fragment: - -| Lean theorem | Coverage | -|-------------|----------| -| `T-Progress` | All 8 echo/product expression forms | -| `T-Preservation` | All 8 echo/product expression forms | -| `T-Determinism` | All 8 echo/product expression forms | -| `T-TypeSafety` | Corollary (progress + preservation) | -| `echo_lower_collapses` | Every closed braid lowers to `identity` | -| `echo_residue_recovers` | `residue(echoClose(braid[gs])) →* braid[gs]` | -| `echo_distinguishes_collapsed` | Distinct braids keep distinct residues after `lower` | -| `echo_roundtrip_typed` | Round-trip is well-typed | - -The OCaml typechecker is proven to refine `HasType` on the core fragment at the -translation-validation level (TG-3, **landed** — see -[`proofs/TG3-REFINEMENT.md`](../proofs/TG3-REFINEMENT.md)): `proofs/TG3Differential.lean` -emits 496 obligations `infer [] e = := by decide` that Lean's -proven `infer` kernel-checks, and the echo/product ops above are all in the -validated core. The two documented divergences are `close` (OCaml `Tangle[I,I]` -vs Lean `Word[0]`) and `Bool == Bool` (OCaml extra-core convenience; Lean rejects). - ---- - -## 6. Known gaps and future work - -| Gap | Tracking | -|-----|----------| -| TG-3 universal proof (reflect `typecheck.ml` in Lean) — current discharge is translation validation over a core-fragment corpus | PROOF-NEEDS.md TG-3 / TG3-REFINEMENT.md §7 | -| TangleIR: thread echo residue into the **Julia** schema (OCaml `EchoClosed` node landed) | ECHO-TANGLEIR-THREADING.md | -| `echoClose` in WASM backend | tangle-wasm (not yet implemented) | diff --git a/docs/spec/DECISIONS-LOCKED.adoc b/docs/spec/DECISIONS-LOCKED.adoc new file mode 100644 index 0000000..994e087 --- /dev/null +++ b/docs/spec/DECISIONS-LOCKED.adoc @@ -0,0 +1,1395 @@ +== TANGLE & TANGLE-JTV Design Decisions (LOCKED 2026-02-12) + +This document records all locked design decisions for: 1. *TANGLE* - The +base topological programming language 2. *TANGLE-JTV* - TANGLE extended +with Julia-the-Viper injection blocks + +''''' + +== PART 1: TANGLE (Base Language) + +=== Core Type System + +==== D1.1: Word vs Tangle Split + +*Decision*: Braid literals construct `+Word[n]+` (data), tangles are +morphisms. + +*Type Rules*: + +.... +braid[σ₁,...,σₖ] : Word[n] where n = max strand index + 1 + +Coercion (implicit): + If w : Word[n] appears where Tangle[𝐀,𝐁] expected, + insert realize_𝐀(w) : Tangle[𝐀, π_w(𝐀)] +.... + +*Rationale*: - Pattern matching requires data values (Words) - +Equational reasoning requires morphisms (Tangles) - Separation prevents +matching breaking extensional equality + +*Example*: + +[source,tangle] +---- +def w = braid[s1, s2, s1] # w : Word[2] + +match w with # Pattern match on Word (intensional) + | s1 . rest => ... +end + +weave strands a, b into w yield a, b # w coerced to Tangle (extensional) +---- + +''''' + +==== D1.2: Two Equality Operators + +*Decision*: `+~+` for isotopy, `+==+` for definitional equality. + +*Semantics*: + +.... +~ : Tangle[𝐀,𝐁] × Tangle[𝐀,𝐁] → Bool (isotopy in FR(T)) +== : Word[n] × Word[n] → Bool (structural) +== : Num × Num → Bool (numeric) +== : Str × Str → Bool (string) +.... + +*Critical*: `+~+` has *fixed mathematical meaning* (equality in strict +ribbon category FR(T)). - Backends provide checking procedures +(strict/lax) - MVP may only support syntactic equality - Do NOT redefine +`+~+` as AST equality + +*Example*: + +[source,tangle] +---- +assert trefoil ~ mirror(trefoil) # Isotopy check (mathematical truth) +assert braid[s1] == braid[s1] # Definitional equality (structural) +---- + +''''' + +==== D1.3: Recursion on Words + +*Decision*: TANGLE definitions CAN recurse via pattern matching on +Words. + +*Semantics*: Call-by-value for non-Tangle values. + +*Example*: + +[source,tangle] +---- +def length(w) = match w with + | identity => 0 + | s1 . rest => 1 + length(rest) # Recursive - legal +end +---- + +*Rationale*: This enables Turing-completeness. Words behave like lists +(identity/cons), match provides branching, recursion gives unbounded +iteration. + +''''' + +==== D1.3.5: Pattern Variable Scoping (NEW) + +*Decision*: Pattern variables are lexically scoped to their match arm. + +*Scoping Rules*: + +.... +Scope: Pattern variables visible ONLY in the arm body (RHS of =>) +Shadowing: YES - pattern variables shadow outer definitions +Namespace: Unified with global definitions (per D1.15.3) +.... + +*Example*: + +[source,tangle] +---- +def rest = braid[s2] # Global definition + +def f(w) = match w with + | s1 . rest => rest . rest # Pattern 'rest' shadows global (warning emitted) + # Uses matched tail, not global braid[s2] +end +---- + +*Rationale*: Lexical scoping prevents accidental capture. Shadowing is +natural for pattern matching (matches functional language conventions). + +''''' + +==== D1.4: Match Exhaustiveness + +*Decision*: Runtime error if no arm matches (MVP). Width-aware warnings. + +*Semantics*: - Match evaluates arms in order - If no pattern matches, +halt with `+MatchFailure(span)+` (per D1.15) - *Width-aware warning*: +When width is statically known, compiler warns about missing generator +arms - Wildcard `+_+` or variable pattern silences the warning + +*Example*: + +[source,tangle] +---- +def process(w : Word[3]) = match w with + | identity => 0 + | s1 . rest => 1 + | s2 . rest => 2 + # Warning: match on Word[3] missing arm for s3 +end + +def safe(w : Word[3]) = match w with + | identity => 0 + | s1 . rest => 1 + | _ => 2 # No warning - wildcard catches s2, s3 +end +---- + +*Rules*: - Known-width types: warn about missing generators up to width +- Unknown-width types: no warning (programmer takes responsibility) - +Warning only, not error — compilation proceeds + +''''' + +==== D1.4.5: Let Binding Scoping (NEW) + +*Decision*: Let bindings are lexically scoped to the `+in+` clause. + +*Syntax*: `+let identifier = expr in expr+` + +*Scoping Rules*: + +.... +Scope: Binding visible ONLY in the 'in' clause +Shadowing: YES - let bindings can shadow outer definitions +Nesting: Nested lets allowed (inner shadows outer) +.... + +*Type Rule*: + +.... +Γ ⊢ e₁ : S₁ +Γ, x : S₁ ⊢ e₂ : S₂ +──────────────────────── +Γ ⊢ let x = e₁ in e₂ : S₂ +.... + +*Example*: + +[source,tangle] +---- +def x = braid[s1] # Global + +def f(y) = + let x = braid[s2] in # Shadows global + let z = x . y in # x refers to braid[s2] + z . z # Result uses shadowed x + +# After f completes, global x still braid[s1] +---- + +*Rationale*: Lexical scoping prevents variable leakage. Shadowing allows +temporary rebinding without name conflicts. + +''''' + +==== D1.5: TANGLE Literals + +*Decision*: Direct `+Num+` and `+Str+` literals (no wrapping needed). + +*Grammar*: `+literal = number | string+` + +*Types*: `+Num+`, `+Str+` are first-class TANGLE sorts (alongside +`+Word[n]+`, `+Tangle[𝐀,𝐁]+`). + +*Example*: + +[source,tangle] +---- +def copies = 5 # Num literal +def name = "trefoil" # Str literal +---- + +''''' + +==== D1.6: Numeric Arithmetic in TANGLE + +*Decision*: TANGLE has `+++`, `+-+`, `+*+`, `+/+` for `+Num+`, with +*`+++` overloaded by sort*. + +*Overloading Rule*: + +.... ++ : Num × Num → Num (numeric addition) ++ : Tangle[I,I] × Tangle[I,I] → Tangle[I,I] (disjoint union) +(mixed types) → TYPE ERROR +.... + +*Examples*: + +[source,tangle] +---- +def length(w) = match w with + | identity => 0 + | s1 . rest => 1 + length(rest) # + is Num addition +end + +def knots = close(trefoil) + close(unknot) # + is tangle union +def bad = 5 + close(trefoil) # TYPE ERROR +---- + +*Rationale*: Makes Word recursion practical while preserving +mathematical `+++` on closed tangles. + +''''' + +==== D1.6.5: Numeric Encoding of Braids (NEW) + +*Decision*: Braids do NOT represent numbers; `+Num+` is a separate type. + +*Turing Completeness*: - *Achieved via*: Recursion + pattern matching + +Num arithmetic (D1.3, D1.6) - *NOT via*: Encoding naturals as braid +words + +*Three Distinct Equalities*: + +.... +Word equality (==): braid[s1, s1] == braid[s1, s1] ✓ + braid[s1, s1] == braid[s2, s2] ✗ (different generators) + +Topological equality (~): braid[s1, s1^-1] ~ identity ✓ (isotopy) + +Numeric equality (==): 5 == 5 ✓ (separate Num type) +.... + +*No Automatic Encoding*: + +[source,tangle] +---- +# These are DIFFERENT types: +def word = braid[s1, s1] # Word[2] +def num = 2 # Num + +# NO automatic conversion: +assert word == num # TYPE ERROR + +# To count generators, use explicit length function: +def length(w) = match w with + | identity => 0 + | s1 . rest => 1 + length(rest) +end + +assert length(braid[s1, s1]) == 2 ✓ (Word → Num via function) +---- + +*Rationale*: - Avoids three-way ambiguity (word/topological/numeric +equality) - Braids retain topological meaning (not numeric encoding) - +Turing-completeness via Num + recursion (cleaner proof) + +''''' + +==== D1.7: Tangle `+++` Type Restriction + +*Decision*: Hard error - `+++` on tangles ONLY for `+Tangle[I,I]+`. + +*Rule*: + +[source,tangle] +---- +def valid = close(t1) + close(t2) ✓ Both Tangle[I,I] +def invalid = tangle1 + tangle2 ✗ ERROR if not closed +---- + +*Rationale*: Mathematical correctness (disjoint union defined only for +closed diagrams). + +''''' + +==== D1.8: Operator Disambiguation + +*`+.+` operator*: Context-sensitive parsing. + +.... +Pattern: s1 . rest (cons operator) +Expression: f . g (vertical composition) +.... + +*`+identity+`*: Type-directed disambiguation. + +.... +As pattern: identity (matches empty Word) +As expression: identity : Word[n] (polymorphic empty word) +As expression: identity : Tangle[𝐀,𝐀] (identity morphism) +.... + +''''' + +==== D1.8.5: Word/Tangle Composition with Different Indices (NEW) + +*Decision*: Auto-widen Words to maximum index on composition (MVP). + +*Index Inference*: + +.... +braid[s1] : Word[2] (strands 1,2 needed) +braid[s3] : Word[4] (strands 1,2,3,4 needed) +braid[s1, s5] : Word[6] (strands 1,2,3,4,5,6 needed) +.... + +*Composition Rule*: + +.... +Word[n] . Word[m] : Word[max(n,m)] (auto-widen to larger width) + +Example: + braid[s1] . braid[s3] : Word[max(2,4)] = Word[4] +.... + +*Coercion to Tangle*: + +.... +realize_𝐀(w : Word[n]) : Tangle[𝐀, π_w(𝐀)] + where |𝐀| = n (boundary length must match word width) + +If |𝐀| > n, implicit widening: + realize_𝐀(w) treats w as if w | identity^(|𝐀|-n) + (word w on first n strands, identity on remaining strands) +.... + +*Example*: + +[source,tangle] +---- +def a = braid[s1] # Word[2] +def b = braid[s3] # Word[4] +def c = a . b # Word[4] (auto-widen a to 4 strands) + +weave strands p:Q, q:Q, r:Q, s:Q into + a # realize_[Q,Q,Q,Q](braid[s1]) + # Treats as: (s1 crossing) | (identity on r,s) +yield strands p, q, r, s +---- + +*Rationale*: - Matches mathematical convention (n-strand braid embeds in +m-strand for m≥n) - Flexible (no explicit widening annotations needed) - +Sound (topologically correct widening) + +*Alternative (rejected for MVP)*: Explicit index type error (require +manual widening) + +''''' + +=== Weave Blocks + +==== D1.9: Weave Expression Restrictions + +*Decision*: Any TANGLE expression that typechecks to `+Tangle[𝐀,𝐁]+`. + +*Rules*: + +[source,tangle] +---- +weave strands a:A, b:B, c:C into + # ✓ Allowed +yield strands ... +---- + +*Allowed*: - Crossings, compositions, tensors - Calls to TANGLE +functions - Pattern matching (if yields Tangle) - Let bindings - Any +combinators + +*Not allowed* (type error): - Harvard blocks (statement-level, not +expressions) - add\{…} if it returns Num/Str (not Tangle) + +*Rationale*: Maximizes expressiveness, allows factoring and combinators. + +''''' + +==== D1.10: Heterogeneous Typed Boundaries + +*Decision*: Boundaries can have *different types* (NO "`all strands same +type`" restriction). + +*Rules*: + +[source,tangle] +---- +weave strands a:A, b:B, c:C into # 𝐀 = [A,B,C] + (a > b) # Tangle[[A,B,C], [B,A,C]] +yield strands b:B, a:A, c:C +---- + +*Crossing Typing*: - `+(x > y)+` where x:Tx, y:Ty denotes β_\{Tx,Ty} - +Swaps positions in boundary: `+[A,B]+` → `+[B,A]+` - Types are +reordered, not changed + +*Missing Type Annotations*: Default to `+Strand+` or `+Any+` (MVP). + +''''' + +==== D1.11: Yield Boundary Matching + +*Decision*: Yield must *exactly match* final boundary order (MVP). + +*Rule*: + +[source,tangle] +---- +weave strands a:A, b:B into + (a > b) # Final boundary: [B,A] +yield strands b:B, a:A # ✓ Exact match required + +yield strands a:A, b:B # ✗ ERROR - order mismatch +---- + +*Future v2*: Allow arbitrary yield order, insert permutation braid. + +''''' + +=== Computation + +==== D1.12: Invariant Computation + +*Decision*: Built-in reserved names + FFI/plugin registry. + +*Reserved Invariants*: `+jones+`, `+alexander+`, `+homfly+`, +`+kauffman+`, `+writhe+`, `+linking+` + +*Semantics*: + +[source,tangle] +---- +compute jones(trefoil) # Statement with effect (print/return value) +---- + +*Type Requirement*: Expression must typecheck to invariant’s domain +(usually `+Tangle[I,I]+`). + +*Extensibility*: User can register custom invariants via FFI/plugin +system. + +''''' + +=== Program Structure + +==== D1.13: Top-Level Definition Order + +*Decision*: Two-pass for TANGLE definitions (forward references +allowed). + +*Pass 1*: Collect all `+def+` names into Γ *Pass 2*: Execute +`+compute+`, `+assert+` in source order + +*Example*: + +[source,tangle] +---- +compute jones(trefoil) # ✓ OK - trefoil in Γ from pass 1 +def trefoil = braid[s1,s1,s1] +assert trefoil ~ trefoil # ✓ OK - forward refs allowed +---- + +*Rationale*: Good UX, matches functional language conventions. + +''''' + +==== D1.13.5: Termination and Evaluation Strategy (NEW) + +*Decision*: Non-termination allowed (Turing-complete); call-by-value +evaluation. + +*Non-Termination*: + +[source,tangle] +---- +def loop(x) = loop(x) # Legal (non-terminating) + +def collatz(n) = match n with + | identity => identity + | s1 . rest => collatz(computed_value(rest)) # Non-structural recursion allowed +end +---- + +*Allowed*: Recursion on *computed values* (not just sub-terms). + +*Consequence for Assertions*: + +[source,tangle] +---- +assert simplify(some_program) ~ identity +---- + +* If `+some_program+` doesn’t terminate, assertion checking *may +diverge* +* `+assert+` is *undecidable in general* (halting problem) +* MVP: Runtime check only (no static verification) + +*Evaluation Strategy*: *Call-by-value* (strict evaluation) + +.... +Arguments evaluated before function call +Matches are evaluated strictly (no lazy patterns) +Let bindings are strict: let x = e in ... evaluates e before binding +.... + +*Rationale*: - *Turing-completeness*: Requires unrestricted recursion +(D1.3) - *Simplicity*: Call-by-value is simpler to reason about and +implement - *Trade-off*: Accept undecidable assertions for computational +power + +*Note*: This creates a deliberate tension with decidable topological +verification. The language prioritizes expressiveness over complete +static checking. + +''''' + +=== Error Handling + +==== D1.14: Identity Width + +*Decision*: `+identity+` is `+Word[0]+` (the empty braid word, +equivalent to `+braid[]+`). + +*Semantics*: - `+identity+` alone has type `+Word[0]+` - Auto-widening +(D1.8.5) handles composition: `+identity . braid[s3]+` → `+Word[4]+` - +The empty braid word IS the identity element in every braid group B_n +after stabilization - Pattern matching: `+identity+` pattern matches the +empty word + +*Type Rule*: + +.... +identity : Word[0] +identity . w : Word[max(0, n)] = Word[n] (via D1.8.5) +.... + +*Implication*: No polymorphism needed in the type system for MVP. Width +inference suffices. + +''''' + +==== D1.15: Error Handling Philosophy + +*Decision*: Halt/panic for MVP. Future review for richer error model. + +*Error Classification*: + +.... +Parse errors → Compile time (never reach runtime) +Type errors → Compile time (never reach runtime) +MatchFailure → Runtime halt with diagnostic +Assertion failure → Runtime halt with diagnostic +Non-termination → Programmer's responsibility (no timeout/detection) +.... + +*Runtime Error Format*: + +.... +MatchFailure at line N: no pattern matched value +Assertion failed at line N: ~ +.... + +*Rationale*: Keeps TANGLE pure and simple. Error recovery belongs in +`+harvard{...}+` blocks where `+if/else+` can guard calls. Fail-fast is +correct for quantum circuit verification. + +*Future review*: Exceptions, Result types, or `+try/catch+` may be +considered post-MVP. + +''''' + +==== D1.15.1: Assertion Decidability + +*Decision*: Assertions are runtime-only expressions (MVP). + +*Semantics*: - `+assert P+` evaluates `+P+`; if true, continues; if +false, halts (per D1.15) - If `+P+` diverges (calls non-terminating +function), assertion check diverges - No static verification, no theorem +prover for MVP + +*Consistency*: Follows from D1.13.5 (non-termination allowed) and D1.15 +(halt on error). + +*Future review*: Split into `+assert+` (runtime) vs `+prove+` (static +verification). `+prove+` would require a static verifier — significant +implementation effort but valuable for quantum circuit verification. + +''''' + +==== D1.15.2: Error Messages — Name-Based + +*Decision*: Error messages reference strand names with positional hints. + +*Format*: + +.... +Error at line 3: yield boundary mismatch + Expected: strands a:Q, b:R + Got: strands b:R, a:Q + (strand 'a' is in position 2, expected position 1) +.... + +*Rationale*: Users write strand names, not type lists. Messages should +speak the user’s language. Compiler tracks strand names through weave +body. + +''''' + +==== D1.15.3: Name Conflict Resolution + +*Decision*: Unified namespace, innermost binding wins, shadowing emits +warning. + +*Binding Priority* (innermost wins): + +.... +pattern variable > strand name > let binding > global def +.... + +*Warning*: + +.... +Warning: strand name 'a' shadows global definition 'a' at line N +.... + +*Consistency*: Same rule as D1.3.5 (pattern variables) and D1.4.5 (let +bindings). All three binding forms follow standard lexical scoping. + +''''' + +=== Operations + +==== D1.16: Primitives and Library Tiering + +*Decision*: Three-tier split for TANGLE operations. + +*Tier 1 — Language Primitives* (in compiler, have typing rules): - +`+identity+` — Word[0], type-directed (D1.14) - `+braid[...]+` literals +— fundamental data constructor - `+(a > b)+`, `+(a < b)+` crossings — +strand interaction - `+(~x)+` twist — topological operation (D1.18) - +`+.+` `+|+` `+++` `+>>+` — composition operators - `+close+` — +Tangle[A,A] → Tangle[I,I] (D1.17) - `+cap+`, `+cup+` — create/destroy +strand pairs - `+mirror+`, `+reverse+` — structural transforms - +`+simplify+` — applies Reidemeister moves (needs internal representation +access) + +*Tier 2 — Built-in Invariants* (compiler knows names, delegates to +backends): - `+jones+`, `+alexander+`, `+homfly+`, `+kauffman+`, +`+writhe+`, `+linking+` - Reserved names (D1.12) with FFI/plugin +backends - Compiler type-checks, runtime dispatches to invariant engine + +*Tier 3 — Standard Library* (pure TANGLE definitions, shipped with +language): - `+length+`, `+concat+`, `+braid_repeat+`, and similar +utilities - Defined via pattern matching + recursion - Shipped as +`+.tangle+` files alongside the compiler + +''''' + +==== D1.17: Close Operation Validation + +*Decision*: `+close+` works on any matching-boundary tangle. No +permutation check. + +*Type Rule*: + +.... +close : Tangle[A,A] → Tangle[I,I] +.... + +*Semantics*: Connects output strand i to input strand i regardless of +permutation. Closing a braid that permutes strands gives a *link* +(possibly multi-component), not necessarily a knot. + +*Example*: + +[source,tangle] +---- +def c = braid[s1] . braid[s3] # Permutation (1 2)(3 4), NOT identity +def link = close(c) # ✓ Legal — produces a 2-component link +---- + +*Rationale*: Standard knot theory (Alexander’s theorem). Any braid +closure is a well-defined link. `+close+` always succeeds on any +`+Word[n]+` since input and output both have n strands. + +''''' + +==== D1.18: Twist Operator Types + +*Decision*: Context-dependent granularity. + +*Standalone* `+(~t)+` — all-strand twist (categorical θ_A): + +.... +(~t) ≜ t . twist_n where n = width of t +Type: Word[n] → Word[n] or Tangle[A,B] → Tangle[A,B] +.... + +Composes expression with the all-strand twist tangle. No new semantics — +just sugar for composition with a Tier 1 primitive. + +*Weave context* `+(~a)+` — single named strand: + +.... +Γ; strands ⊢ a : T +──────────────────── +Γ; strands ⊢ (~a) : Tangle[[T], [T]] +.... + +Twists only the named strand. + +*Resolution*: Compiler checks "`am I inside a weave block with a strand +named `+x+`?`" If yes, single-strand twist. If no, treat `+x+` as +expression and apply all-strand twist. + +''''' + +==== D1.19: Self-Crossings in Weave + +*Decision*: Allow but warn, desugar to `+(~a)+`. + +*Semantics*: + +[source,tangle] +---- +weave strands a:Q into + (a > a) # ✓ Legal — equivalent to (~a) + # Warning: self-crossing (a > a) is equivalent to (~a) +yield strands a:Q +---- + +*Compiler*: Desugars `+(a > a)+` to `+(~a)+` during lowering. Warning +suggests canonical form. + +''''' + +==== D1.20: Pipeline `+>>+` Precedence + +*Decision*: `+>>+` is sugar for `+.+` semantically, but has LOWER +precedence. + +*Precedence* (lowest to highest): + +.... +>> pipeline (lowest) ++ addition / disjoint union +. vertical composition +| horizontal tensor (highest) +.... + +*Example*: + +[source,tangle] +---- +# Without >>: parentheses needed +(braid[s1] . braid[s2]) . (braid[s3] . braid[s1]) + +# With >>: pipeline stages visually clear +braid[s1] . braid[s2] >> braid[s3] . braid[s1] +---- + +Both evaluate identically — `+.+` is associative. Different precedence +is purely for *human readability*. + +*Status*: Grammar already implements this correctly. + +''''' + +=== Polymorphism and Width + +==== D1.21: No Full Polymorphism (MVP) + +*Decision*: Width inference instead of Hindley-Milner polymorphism. + +*Rules*: - `+identity+` is concretely `+Word[0]+` with auto-widening +(D1.14) - User-defined function widths inferred from usage - If +ambiguous, compiler asks for annotation + +*Example*: + +[source,tangle] +---- +def f(x) = x . braid[s1] # x must be at least Word[2], result is Word[2] +---- + +*No* `+∀+` quantifiers. Width inference is simpler than full +polymorphism — just track maximum generator index through expressions. + +*Future*: Full polymorphic boundaries (∀A. Tangle[A,A]) can be added +post-MVP. + +''''' + +=== Module System + +==== D1.22: TANGLE Module System + +*Decision*: Flat namespace for MVP (no in-language modules). + +*Rules*: - All `+def+`s go into one global Γ - Multiple `+.tangle+` +files loaded in order - Harvard modules (already in grammar) available +for namespacing via JTV + +*Rationale*: TANGLE programs are mathematical objects. Mathematical +papers have definitions, not modules. Module system can be added +post-MVP if name collisions become a problem. + +''''' + +=== Standard Library + +==== D1.23: Standard Library Functions + +*Decision*: Utility functions shipped as pure TANGLE definitions (Tier +3). + +*Included*: + +[source,tangle] +---- +# length : Word[n] → Num +def length(w) = match w with + | identity => 0 + | _ . rest => add{ 1 + length(rest) } +end + +# Also: concat, braid_repeat, reverse_word, etc. +---- + +*Rationale*: These are trivially definable with pattern matching + +recursion. No reason to bake into the compiler. Also serve as idiomatic +TANGLE code examples. + +''''' + +=== Theoretical Foundations + +==== D1.24: Turing Completeness Proof Strategy + +*Decision*: Via pattern matching + recursion on Word structure. + +*Proof Sketch*: - `+identity+` = nil - `+s_i . rest+` = cons(s_i, rest) +- Pattern matching = list destructuring - Recursion = general recursion + +Pattern matching + recursion on an inductively-defined structure with +infinitely many constructors (s1, s2, s3, …) is Turing complete +(standard result). + +*Implication*: Pure TANGLE (without JTV) is Turing complete on its own. +Num is a convenience, not a necessity. No braid-as-number encoding +needed (D1.6.5). + +''''' + +==== D1.25: Data Encoding Philosophy + +*Decision*: Pure TANGLE handles topology only. Complex data structures +live in JTV. + +*Scope*: - TANGLE: `+Word[n]+`, `+Tangle[A,B]+`, `+Num+`, `+Str+` — +that’s it - Pairs, lists, trees → require `+add{...}+` / +`+harvard{...}+` blocks - No braid encoding of data structures +(Coherence Problem #5 resolved by design) + +*Rationale*: "`Everything topological is a braid, everything else is +Harvard.`" Encoding lists as braids would overload topological meaning +with data semantics. The two-world design exists precisely so TANGLE +doesn’t have to solve this. + +*Implication*: Generator index partitioning (using high indices as type +tags) is unnecessary. + +''''' + +== PART 2: TANGLE-JTV (Julia-the-Viper Extension) + +=== Overview + +TANGLE-JTV extends TANGLE with two delimited syntactic islands: 1. +*`+add{...}+`* - Data-only computations (total, guaranteed terminating) +2. *`+harvard{...}+`* - Full imperative programs (control + data) + +''''' + +=== The Three Worlds + +==== D2.1: Semantic Stratification + +*TANGLE World* (from Part 1): - Values: `+Word[n]+`, `+Tangle[𝐀,𝐁]+`, +`+Num+`, `+Str+`, `+Bool+` - Control: Pattern matching on Words only - +Environment: Γ (TANGLE definitions) + +*Harvard DATA World* (`+add{...}+`): - Values: Total data expressions +(numbers, bools, strings) - Grammar: `+hv_data_expr+` only (NO +if/while/for/assignments) - Calls: Only @pure/@total functions from Π - +*Guarantee*: Always terminates + +*Harvard CONTROL World* (`+harvard{...}+`): - Full imperative language: +if/while/for/return/assignments - Functions with purity markers +(@pure/@total) - Modules, imports - Environment: Δ (full Harvard), Π ⊆ Δ +(pure subset) + +''''' + +=== Visibility & Environments + +==== D2.2: Three Environments + +*Decision*: Separate namespaces with one-way bridge. + +.... +Γ : TangleEnv - TANGLE definitions (def, weave) +Δ : HarvardEnv - All Harvard functions, modules +Π ⊆ Δ : PureEnv - Pure/total Harvard functions only +.... + +*Visibility Rules*: + +.... +Inside TANGLE expr: calls resolve in Γ only +Inside harvard{...}: calls resolve in Δ +Inside add{...}: calls resolve in Π only +.... + +*Bridge Flow*: + +.... +harvard{...} defines functions + ↓ +@pure/@total functions → Π + ↓ +add{...} calls Π functions + ↓ +Results embed via Embed(τ) + ↓ +TANGLE uses embedded values +.... + +*Rationale*: Clean separation prevents effect leakage, maintains +totality guarantees. + +''''' + +==== D2.3: Π Visibility Model (Sequential) + +*Decision*: Sequential visibility (MVP). + +*Meaning*: @pure/@total function visible in `+add{...}+` ONLY AFTER its +`+harvard{...}+` block. + +*Example*: + +[source,tangle] +---- +add{ bar() } ✗ ERROR - bar not in Π yet + +harvard{ fn bar() @pure { ... } } + +add{ bar() } ✓ OK - bar now in Π +---- + +*Two-Pass Reconciliation*: - TANGLE defs collected in pass 1 (forward +refs OK) - Harvard blocks processed sequentially in pass 2 (Π grows) - +add\{…} sees current Π at point of use + +*Future*: Two-pass Π in v2 (non-breaking, accepts more programs). + +''''' + +=== Embedding Bridge + +==== D2.4: Embed(τ) Type Bridge + +*Decision*: Minimal scalar embedding only (MVP). + +.... +Embed : HarvardType → TangleType + +Embed(Int) = Num +Embed(Float) = Num +Embed(Rational) = Num +Embed(Hex) = Num (convert to numeric) +Embed(Binary) = Num (convert to numeric) +Embed(Bool) = Bool +Embed(String) = Str +Embed(Symbolic) = Str (serialized) + +Embed(Complex) = ERROR ("Complex not yet supported") +Embed(List) = ERROR ("Lists not embeddable") +Embed(Tuple) = ERROR ("Tuples not embeddable") +Embed(Fn ...) = ERROR ("Functions not embeddable") +.... + +*Example*: + +[source,tangle] +---- +harvard{ + fn factorial(n: Int) @pure { ... } +} + +def copies = add{ factorial(5) } # Embed(Int) = Num +---- + +*Future Extensions*: - Phase 2: Complex, structured data (List, Tuple) - +Phase 3: Semantic mappings (List ≈ Word[n]?) + +''''' + +=== Harvard Semantics + +==== D2.5: Harvard Store Persistence + +*Decision*: Module-scoped (explicit imports). + +*Semantics*: + +[source,tangle] +---- +harvard{ module Math { let x = 5 } } + +harvard{ + import Math + print(Math.x) # ✓ OK - explicit import +} + +harvard{ + print(x) # ✗ ERROR - x not in scope +} +---- + +*Rationale*: Modularity, no accidental global state. + +''''' + +==== D2.6: Harvard Module Imports + +*Decision*: Explicit imports with sequential visibility. + +*Rules*: - `+module M { ... }+` registers M in Δ - `+import M+` or +`+import M as Alias+` brings M into scope - *Sequential constraint*: Can +only import modules from earlier `+harvard{...}+` blocks + +*Example*: + +[source,tangle] +---- +harvard{ + module Math { + fn sqrt(x: Float) @pure { ... } + } +} + +harvard{ + import Math + fn hypotenuse(a, b) @pure { + Math.sqrt(a*a + b*b) + } +} +---- + +*Rationale*: Consistent with sequential Π visibility (D2.3). + +''''' + +=== Future Extensions + +==== D2.7: Reverse Blocks + +*Decision*: Document interface, defer implementation. + +*Status*: - Parse `+reverse{...}+` syntax - Typecheck reversible +statements - Full Bennett semantics: post-MVP + +''''' + +=== Cross-World Interaction + +==== D2.8: Weave Block Visibility + +*Decision*: Weave blocks can reference all definitions in Γ (outer +scope). + +*Rules*: + +[source,tangle] +---- +def helper = braid[s1, s2] + +weave strands a:Q, b:Q into + helper # ✓ Can reference global def +yield strands b:Q, a:Q +---- + +*Rationale*: Weave blocks are TANGLE expressions. They naturally see all +of Γ, consistent with D1.9 (any TANGLE expression that typechecks). + +''''' + +==== D2.9: Harvard Calling TANGLE + +*Decision*: Harvard CAN call TANGLE functions, with purity restriction. + +*Rules*: + +.... +Unmarked Harvard functions → can call ANY TANGLE function +@pure/@total Harvard functions → can ONLY call non-recursive TANGLE functions +.... + +*Recursion Check*: Syntactic (conservative) — if a TANGLE function’s +body contains self-reference, it’s marked as potentially +non-terminating. @pure/@total Harvard code cannot call it. + +*Example*: + +[source,tangle] +---- +def simplify_once(w) = ... # Non-recursive — @pure can call ✓ +def loop(w) = loop(w) # Recursive — @pure CANNOT call ✗ + +harvard{ + fn verify(w) @pure { + simplify_once(w) # ✓ OK + # loop(w) # ✗ ERROR: @pure cannot call recursive TANGLE + } + fn debug(w) { + loop(w) # ✓ OK (no purity marker) + } +} +---- + +*Rationale*: Sound (conservative check, never wrong), simple +(syntactic), practical (Tier 1 primitives like `+simplify+`, `+jones+`, +`+close+` are non-recursive, so @pure Harvard code can call them +freely). + +''''' + +==== D2.10: Reverse Embedding (Unembed) + +*Decision*: Implicit scalar Unembed — TANGLE scalars convert to Harvard +types automatically. + +*Unembed Rules*: + +.... +Unembed(Num) = Int or Float (context-dependent) +Unembed(Str) = String +Unembed(Word[n]) = ERROR ("braids don't cross into Harvard") +Unembed(Tangle[A,B]) = ERROR ("tangles don't cross into Harvard") +.... + +*Bidirectional Scalar Bridge*: + +.... +Harvard → TANGLE: Embed(Int) = Num, Embed(String) = Str +TANGLE → Harvard: Unembed(Num) = Int, Unembed(Str) = String +.... + +*Example*: + +[source,tangle] +---- +def copies = 5 # TANGLE Num + +harvard{ + fn process(n: Int) @pure { n * 2 } +} + +add{ process(copies) } # ✓ copies (Num) → Int automatically +add{ process(braid[s1]) } # ✗ TYPE ERROR: Word can't cross +---- + +*Rationale*: Symmetric with D2.4 (Embed). Scalars cross both ways, +topological types stay in TANGLE. + +''''' + +==== D2.11: Harvard Module Re-exports + +*Decision*: Imports are private to the module (MVP). + +*Rules*: + +[source,tangle] +---- +harvard{ + module Utils { + import Math # Private — Utils uses Math internally + fn helper() @pure { Math.sqrt(2) } + } +} + +harvard{ + import Utils + # Utils.helper() ✓ OK + # Math.sqrt(2) ✗ ERROR — must import Math directly +} +---- + +*Rationale*: Keeps dependency chains explicit — you always know where a +function comes from. + +*Future review*: Re-exports (like Rust `+pub use+`) may be added +post-MVP if module hierarchies get deep. + +''''' + +=== Decision Cross-Reference + +==== TANGLE-Only Decisions (Part 1): + +* D1.1–D1.8.5: Core type system (Word/Tangle split, equality, recursion, +scoping, literals, arithmetic, encoding, operators, widening) +* D1.9–D1.11: Weave blocks (expression restrictions, heterogeneous +boundaries, yield matching) +* D1.12: Computation (invariants) +* D1.13–D1.13.5: Program structure (definition order, termination, +evaluation) +* D1.14–D1.15.3: Error handling (identity width, halt/panic, assertions, +error messages, name conflicts) +* D1.16–D1.20: Operations (tiering, close, twist, self-crossings, +pipeline) +* D1.21: Polymorphism (width inference, no HM for MVP) +* D1.22: Module system (flat for MVP) +* D1.23: Standard library (Tier 3 definitions) +* D1.24–D1.25: Theoretical foundations (Turing completeness, data +encoding) + +==== TANGLE-JTV Decisions (Part 2): + +* D2.1–D2.3: Three worlds, environments, Π visibility +* D2.4: Embed(τ) type bridge +* D2.5–D2.6: Harvard store persistence, module imports +* D2.7: Reverse blocks (deferred) +* D2.8: Weave block visibility (sees all Γ) +* D2.9: Harvard calling TANGLE (@pure restriction) +* D2.10: Reverse embedding (scalar Unembed) +* D2.11: Module re-exports (private for MVP) + +==== Decisions Affecting Both: + +* D1.3 (Recursion) — affects D2.9 (Harvard purity check) +* D1.6 (Arithmetic) — add\{…} can call Π functions that use arithmetic +* D1.13 (Order) — two-pass for TANGLE, sequential for harvard\{…} +* D1.15 (Errors) — Harvard blocks provide error recovery TANGLE lacks +* D1.25 (Data encoding) — TANGLE topology only, complex data via JTV + +''''' + +=== Implementation Priorities + +*MVP (Minimum Viable Product)*: - All TANGLE decisions (D1.1–D1.25) - +add\{…} blocks with Embed(τ) and Unembed (D2.4, D2.10) - harvard\{…} +blocks with @pure functions (D2.2, D2.3, D2.9) - Sequential Π visibility +(D2.3) - Halt/panic error model (D1.15) - Width inference (D1.21) - Flat +namespace (D1.22) - Standard library (D1.23) - Three-tier operations +(D1.16) + +*v2 (Enhanced)*: - Two-pass Π visibility - Exhaustiveness checking +promoted from warning to error - Rich Embed(τ) (Complex, List, Tuple) - +Module re-exports (D2.11 future) - Richer error model (D1.15 future +review) - `+assert+` vs `+prove+` split (D1.15.1 future review) + +*v3 (Advanced)*: - Reverse blocks (Bennett semantics, D2.7) - Arbitrary +yield order permutations - Full polymorphic boundaries (∀A. Tangle[A,A]) +- Advanced isotopy checkers (Reidemeister, model-based) - TANGLE module +system + +''''' + +=== Future Review Items + +Items explicitly noted for post-MVP review: 1. *Error handling model* +(D1.15) — exceptions, Result types, try/catch 2. *Assert vs Prove split* +(D1.15.1) — static verification for quantum circuit proofs 3. *Module +re-exports* (D2.11) — Rust-style `+pub use+` for facade modules + +''''' + +=== Meta + +* *Specification Version*: 1.0.0-draft +* *Decisions Locked*: 2026-02-12 +* *Total Decisions*: 37 (25 TANGLE + 11 TANGLE-JTV + 1 deferred) +* *Authors*: Jonathan D.A. Jewell, Claude (Sonnet 4.5, Opus 4.6) +* *License*: MPL-2.0 +* *Status*: Ready for formal specification writing + +''''' + +=== Change Policy + +These decisions are *locked* for the MVP specification. Changes require: +1. Documented rationale 2. Impact analysis (which decisions are +affected?) 3. Version bump: - *Major*: Breaking changes to TANGLE or +TANGLE-JTV semantics - *Minor*: Additive features (e.g., two-pass Π) - +*Patch*: Clarifications, typo fixes + +''''' + +=== Quick Reference + +*TANGLE* = Part 1 (D1.1–D1.25) *TANGLE-JTV* = Part 1 + Part 2 +(D1.1–D1.25 + D2.1–D2.11) + +*Can I use TANGLE without JTV?* Yes! Part 1 is self-contained. *Can I +use JTV without TANGLE?* No — JTV extends TANGLE. + +==== Decision Index + +[cols=",,",options="header",] +|=== +|ID |Topic |Section +|D1.1 |Word vs Tangle split |Core Type System +|D1.2 |Two equality operators (~ and ==) |Core Type System +|D1.3 |Recursion on Words |Core Type System +|D1.3.5 |Pattern variable scoping |Core Type System +|D1.4 |Match exhaustiveness (runtime + warning) |Core Type System +|D1.4.5 |Let binding scoping |Core Type System +|D1.5 |TANGLE literals (Num, Str) |Core Type System +|D1.6 |Numeric arithmetic (+ overloaded) |Core Type System +|D1.6.5 |Numeric encoding (Num ≠ Word) |Core Type System +|D1.7 |Tangle + restriction (closed only) |Core Type System +|D1.8 |Operator disambiguation (. and identity) |Core Type System +|D1.8.5 |Auto-widening on composition |Core Type System +|D1.9 |Weave expression restrictions |Weave Blocks +|D1.10 |Heterogeneous typed boundaries |Weave Blocks +|D1.11 |Yield boundary matching (exact) |Weave Blocks +|D1.12 |Invariant computation (built-in + FFI) |Computation +|D1.13 |Top-level definition order (two-pass) |Program Structure +|D1.13.5 |Termination and evaluation (CBV) |Program Structure +|D1.14 |Identity width (Word[0]) |Error Handling +|D1.15 |Error handling (halt/panic) |Error Handling +|D1.15.1 |Assertion decidability (runtime only) |Error Handling +|D1.15.2 |Error messages (name-based) |Error Handling +|D1.15.3 |Name conflict resolution (unified, warn) |Error Handling +|D1.16 |Primitives tiering (3 tiers) |Operations +|D1.17 |Close operation (no permutation check) |Operations +|D1.18 |Twist operator (context-dependent) |Operations +|D1.19 |Self-crossings (allow, warn, desugar) |Operations +|D1.20 |Pipeline >> precedence |Operations +|D1.21 |No full polymorphism (width inference) |Polymorphism +|D1.22 |Flat module system |Module System +|D1.23 |Standard library (Tier 3) |Standard Library +|D1.24 |Turing completeness proof |Theoretical +|D1.25 |Data encoding (topology only) |Theoretical +|D2.1 |Semantic stratification (3 worlds) |Three Worlds +|D2.2 |Three environments (Γ, Δ, Π) |Visibility +|D2.3 |Π sequential visibility |Visibility +|D2.4 |Embed(τ) scalar bridge |Embedding +|D2.5 |Harvard store persistence |Harvard Semantics +|D2.6 |Harvard module imports |Harvard Semantics +|D2.7 |Reverse blocks (deferred) |Future +|D2.8 |Weave block visibility (all Γ) |Cross-World +|D2.9 |Harvard calling TANGLE (@pure restriction) |Cross-World +|D2.10 |Reverse embedding (scalar Unembed) |Cross-World +|D2.11 |Module re-exports (private MVP) |Cross-World +|=== diff --git a/docs/spec/DECISIONS-LOCKED.md b/docs/spec/DECISIONS-LOCKED.md deleted file mode 100644 index cb25f28..0000000 --- a/docs/spec/DECISIONS-LOCKED.md +++ /dev/null @@ -1,1217 +0,0 @@ - -# TANGLE & TANGLE-JTV Design Decisions (LOCKED 2026-02-12) - -This document records all locked design decisions for: -1. **TANGLE** - The base topological programming language -2. **TANGLE-JTV** - TANGLE extended with Julia-the-Viper injection blocks - ---- - -# PART 1: TANGLE (Base Language) - -## Core Type System - -### D1.1: Word vs Tangle Split -**Decision**: Braid literals construct `Word[n]` (data), tangles are morphisms. - -**Type Rules**: -``` -braid[σ₁,...,σₖ] : Word[n] where n = max strand index + 1 - -Coercion (implicit): - If w : Word[n] appears where Tangle[𝐀,𝐁] expected, - insert realize_𝐀(w) : Tangle[𝐀, π_w(𝐀)] -``` - -**Rationale**: -- Pattern matching requires data values (Words) -- Equational reasoning requires morphisms (Tangles) -- Separation prevents matching breaking extensional equality - -**Example**: -```tangle -def w = braid[s1, s2, s1] # w : Word[2] - -match w with # Pattern match on Word (intensional) - | s1 . rest => ... -end - -weave strands a, b into w yield a, b # w coerced to Tangle (extensional) -``` - ---- - -### D1.2: Two Equality Operators -**Decision**: `~` for isotopy, `==` for definitional equality. - -**Semantics**: -``` -~ : Tangle[𝐀,𝐁] × Tangle[𝐀,𝐁] → Bool (isotopy in FR(T)) -== : Word[n] × Word[n] → Bool (structural) -== : Num × Num → Bool (numeric) -== : Str × Str → Bool (string) -``` - -**Critical**: `~` has **fixed mathematical meaning** (equality in strict ribbon category FR(T)). -- Backends provide checking procedures (strict/lax) -- MVP may only support syntactic equality -- Do NOT redefine `~` as AST equality - -**Example**: -```tangle -assert trefoil ~ mirror(trefoil) # Isotopy check (mathematical truth) -assert braid[s1] == braid[s1] # Definitional equality (structural) -``` - ---- - -### D1.3: Recursion on Words -**Decision**: TANGLE definitions CAN recurse via pattern matching on Words. - -**Semantics**: Call-by-value for non-Tangle values. - -**Example**: -```tangle -def length(w) = match w with - | identity => 0 - | s1 . rest => 1 + length(rest) # Recursive - legal -end -``` - -**Rationale**: This enables Turing-completeness. Words behave like lists (identity/cons), match provides branching, recursion gives unbounded iteration. - ---- - -### D1.3.5: Pattern Variable Scoping (NEW) -**Decision**: Pattern variables are lexically scoped to their match arm. - -**Scoping Rules**: -``` -Scope: Pattern variables visible ONLY in the arm body (RHS of =>) -Shadowing: YES - pattern variables shadow outer definitions -Namespace: Unified with global definitions (per D1.15.3) -``` - -**Example**: -```tangle -def rest = braid[s2] # Global definition - -def f(w) = match w with - | s1 . rest => rest . rest # Pattern 'rest' shadows global (warning emitted) - # Uses matched tail, not global braid[s2] -end -``` - -**Rationale**: Lexical scoping prevents accidental capture. Shadowing is natural for pattern matching (matches functional language conventions). - ---- - -### D1.4: Match Exhaustiveness -**Decision**: Runtime error if no arm matches (MVP). Width-aware warnings. - -**Semantics**: -- Match evaluates arms in order -- If no pattern matches, halt with `MatchFailure(span)` (per D1.15) -- **Width-aware warning**: When width is statically known, compiler warns about missing generator arms -- Wildcard `_` or variable pattern silences the warning - -**Example**: -```tangle -def process(w : Word[3]) = match w with - | identity => 0 - | s1 . rest => 1 - | s2 . rest => 2 - # Warning: match on Word[3] missing arm for s3 -end - -def safe(w : Word[3]) = match w with - | identity => 0 - | s1 . rest => 1 - | _ => 2 # No warning - wildcard catches s2, s3 -end -``` - -**Rules**: -- Known-width types: warn about missing generators up to width -- Unknown-width types: no warning (programmer takes responsibility) -- Warning only, not error — compilation proceeds - ---- - -### D1.4.5: Let Binding Scoping (NEW) -**Decision**: Let bindings are lexically scoped to the `in` clause. - -**Syntax**: `let identifier = expr in expr` - -**Scoping Rules**: -``` -Scope: Binding visible ONLY in the 'in' clause -Shadowing: YES - let bindings can shadow outer definitions -Nesting: Nested lets allowed (inner shadows outer) -``` - -**Type Rule**: -``` -Γ ⊢ e₁ : S₁ -Γ, x : S₁ ⊢ e₂ : S₂ -──────────────────────── -Γ ⊢ let x = e₁ in e₂ : S₂ -``` - -**Example**: -```tangle -def x = braid[s1] # Global - -def f(y) = - let x = braid[s2] in # Shadows global - let z = x . y in # x refers to braid[s2] - z . z # Result uses shadowed x - -# After f completes, global x still braid[s1] -``` - -**Rationale**: Lexical scoping prevents variable leakage. Shadowing allows temporary rebinding without name conflicts. - ---- - -### D1.5: TANGLE Literals -**Decision**: Direct `Num` and `Str` literals (no wrapping needed). - -**Grammar**: `literal = number | string` - -**Types**: `Num`, `Str` are first-class TANGLE sorts (alongside `Word[n]`, `Tangle[𝐀,𝐁]`). - -**Example**: -```tangle -def copies = 5 # Num literal -def name = "trefoil" # Str literal -``` - ---- - -### D1.6: Numeric Arithmetic in TANGLE -**Decision**: TANGLE has `+`, `-`, `*`, `/` for `Num`, with **`+` overloaded by sort**. - -**Overloading Rule**: -``` -+ : Num × Num → Num (numeric addition) -+ : Tangle[I,I] × Tangle[I,I] → Tangle[I,I] (disjoint union) -(mixed types) → TYPE ERROR -``` - -**Examples**: -```tangle -def length(w) = match w with - | identity => 0 - | s1 . rest => 1 + length(rest) # + is Num addition -end - -def knots = close(trefoil) + close(unknot) # + is tangle union -def bad = 5 + close(trefoil) # TYPE ERROR -``` - -**Rationale**: Makes Word recursion practical while preserving mathematical `+` on closed tangles. - ---- - -### D1.6.5: Numeric Encoding of Braids (NEW) -**Decision**: Braids do NOT represent numbers; `Num` is a separate type. - -**Turing Completeness**: -- **Achieved via**: Recursion + pattern matching + Num arithmetic (D1.3, D1.6) -- **NOT via**: Encoding naturals as braid words - -**Three Distinct Equalities**: -``` -Word equality (==): braid[s1, s1] == braid[s1, s1] ✓ - braid[s1, s1] == braid[s2, s2] ✗ (different generators) - -Topological equality (~): braid[s1, s1^-1] ~ identity ✓ (isotopy) - -Numeric equality (==): 5 == 5 ✓ (separate Num type) -``` - -**No Automatic Encoding**: -```tangle -# These are DIFFERENT types: -def word = braid[s1, s1] # Word[2] -def num = 2 # Num - -# NO automatic conversion: -assert word == num # TYPE ERROR - -# To count generators, use explicit length function: -def length(w) = match w with - | identity => 0 - | s1 . rest => 1 + length(rest) -end - -assert length(braid[s1, s1]) == 2 ✓ (Word → Num via function) -``` - -**Rationale**: -- Avoids three-way ambiguity (word/topological/numeric equality) -- Braids retain topological meaning (not numeric encoding) -- Turing-completeness via Num + recursion (cleaner proof) - ---- - -### D1.7: Tangle `+` Type Restriction -**Decision**: Hard error - `+` on tangles ONLY for `Tangle[I,I]`. - -**Rule**: -```tangle -def valid = close(t1) + close(t2) ✓ Both Tangle[I,I] -def invalid = tangle1 + tangle2 ✗ ERROR if not closed -``` - -**Rationale**: Mathematical correctness (disjoint union defined only for closed diagrams). - ---- - -### D1.8: Operator Disambiguation - -**`.` operator**: Context-sensitive parsing. -``` -Pattern: s1 . rest (cons operator) -Expression: f . g (vertical composition) -``` - -**`identity`**: Type-directed disambiguation. -``` -As pattern: identity (matches empty Word) -As expression: identity : Word[n] (polymorphic empty word) -As expression: identity : Tangle[𝐀,𝐀] (identity morphism) -``` - ---- - -### D1.8.5: Word/Tangle Composition with Different Indices (NEW) -**Decision**: Auto-widen Words to maximum index on composition (MVP). - -**Index Inference**: -``` -braid[s1] : Word[2] (strands 1,2 needed) -braid[s3] : Word[4] (strands 1,2,3,4 needed) -braid[s1, s5] : Word[6] (strands 1,2,3,4,5,6 needed) -``` - -**Composition Rule**: -``` -Word[n] . Word[m] : Word[max(n,m)] (auto-widen to larger width) - -Example: - braid[s1] . braid[s3] : Word[max(2,4)] = Word[4] -``` - -**Coercion to Tangle**: -``` -realize_𝐀(w : Word[n]) : Tangle[𝐀, π_w(𝐀)] - where |𝐀| = n (boundary length must match word width) - -If |𝐀| > n, implicit widening: - realize_𝐀(w) treats w as if w | identity^(|𝐀|-n) - (word w on first n strands, identity on remaining strands) -``` - -**Example**: -```tangle -def a = braid[s1] # Word[2] -def b = braid[s3] # Word[4] -def c = a . b # Word[4] (auto-widen a to 4 strands) - -weave strands p:Q, q:Q, r:Q, s:Q into - a # realize_[Q,Q,Q,Q](braid[s1]) - # Treats as: (s1 crossing) | (identity on r,s) -yield strands p, q, r, s -``` - -**Rationale**: -- Matches mathematical convention (n-strand braid embeds in m-strand for m≥n) -- Flexible (no explicit widening annotations needed) -- Sound (topologically correct widening) - -**Alternative (rejected for MVP)**: Explicit index type error (require manual widening) - ---- - -## Weave Blocks - -### D1.9: Weave Expression Restrictions -**Decision**: Any TANGLE expression that typechecks to `Tangle[𝐀,𝐁]`. - -**Rules**: -```tangle -weave strands a:A, b:B, c:C into - # ✓ Allowed -yield strands ... -``` - -**Allowed**: -- Crossings, compositions, tensors -- Calls to TANGLE functions -- Pattern matching (if yields Tangle) -- Let bindings -- Any combinators - -**Not allowed** (type error): -- Harvard blocks (statement-level, not expressions) -- add{...} if it returns Num/Str (not Tangle) - -**Rationale**: Maximizes expressiveness, allows factoring and combinators. - ---- - -### D1.10: Heterogeneous Typed Boundaries -**Decision**: Boundaries can have **different types** (NO "all strands same type" restriction). - -**Rules**: -```tangle -weave strands a:A, b:B, c:C into # 𝐀 = [A,B,C] - (a > b) # Tangle[[A,B,C], [B,A,C]] -yield strands b:B, a:A, c:C -``` - -**Crossing Typing**: -- `(x > y)` where x:Tx, y:Ty denotes β_{Tx,Ty} -- Swaps positions in boundary: `[A,B]` → `[B,A]` -- Types are reordered, not changed - -**Missing Type Annotations**: Default to `Strand` or `Any` (MVP). - ---- - -### D1.11: Yield Boundary Matching -**Decision**: Yield must **exactly match** final boundary order (MVP). - -**Rule**: -```tangle -weave strands a:A, b:B into - (a > b) # Final boundary: [B,A] -yield strands b:B, a:A # ✓ Exact match required - -yield strands a:A, b:B # ✗ ERROR - order mismatch -``` - -**Future v2**: Allow arbitrary yield order, insert permutation braid. - ---- - -## Computation - -### D1.12: Invariant Computation -**Decision**: Built-in reserved names + FFI/plugin registry. - -**Reserved Invariants**: `jones`, `alexander`, `homfly`, `kauffman`, `writhe`, `linking` - -**Semantics**: -```tangle -compute jones(trefoil) # Statement with effect (print/return value) -``` - -**Type Requirement**: Expression must typecheck to invariant's domain (usually `Tangle[I,I]`). - -**Extensibility**: User can register custom invariants via FFI/plugin system. - ---- - -## Program Structure - -### D1.13: Top-Level Definition Order -**Decision**: Two-pass for TANGLE definitions (forward references allowed). - -**Pass 1**: Collect all `def` names into Γ -**Pass 2**: Execute `compute`, `assert` in source order - -**Example**: -```tangle -compute jones(trefoil) # ✓ OK - trefoil in Γ from pass 1 -def trefoil = braid[s1,s1,s1] -assert trefoil ~ trefoil # ✓ OK - forward refs allowed -``` - -**Rationale**: Good UX, matches functional language conventions. - ---- - -### D1.13.5: Termination and Evaluation Strategy (NEW) -**Decision**: Non-termination allowed (Turing-complete); call-by-value evaluation. - -**Non-Termination**: -```tangle -def loop(x) = loop(x) # Legal (non-terminating) - -def collatz(n) = match n with - | identity => identity - | s1 . rest => collatz(computed_value(rest)) # Non-structural recursion allowed -end -``` - -**Allowed**: Recursion on **computed values** (not just sub-terms). - -**Consequence for Assertions**: -```tangle -assert simplify(some_program) ~ identity -``` - -- If `some_program` doesn't terminate, assertion checking **may diverge** -- `assert` is **undecidable in general** (halting problem) -- MVP: Runtime check only (no static verification) - -**Evaluation Strategy**: **Call-by-value** (strict evaluation) -``` -Arguments evaluated before function call -Matches are evaluated strictly (no lazy patterns) -Let bindings are strict: let x = e in ... evaluates e before binding -``` - -**Rationale**: -- **Turing-completeness**: Requires unrestricted recursion (D1.3) -- **Simplicity**: Call-by-value is simpler to reason about and implement -- **Trade-off**: Accept undecidable assertions for computational power - -**Note**: This creates a deliberate tension with decidable topological verification. The language prioritizes expressiveness over complete static checking. - ---- - -## Error Handling - -### D1.14: Identity Width -**Decision**: `identity` is `Word[0]` (the empty braid word, equivalent to `braid[]`). - -**Semantics**: -- `identity` alone has type `Word[0]` -- Auto-widening (D1.8.5) handles composition: `identity . braid[s3]` → `Word[4]` -- The empty braid word IS the identity element in every braid group B_n after stabilization -- Pattern matching: `identity` pattern matches the empty word - -**Type Rule**: -``` -identity : Word[0] -identity . w : Word[max(0, n)] = Word[n] (via D1.8.5) -``` - -**Implication**: No polymorphism needed in the type system for MVP. Width inference suffices. - ---- - -### D1.15: Error Handling Philosophy -**Decision**: Halt/panic for MVP. Future review for richer error model. - -**Error Classification**: -``` -Parse errors → Compile time (never reach runtime) -Type errors → Compile time (never reach runtime) -MatchFailure → Runtime halt with diagnostic -Assertion failure → Runtime halt with diagnostic -Non-termination → Programmer's responsibility (no timeout/detection) -``` - -**Runtime Error Format**: -``` -MatchFailure at line N: no pattern matched value -Assertion failed at line N: ~ -``` - -**Rationale**: Keeps TANGLE pure and simple. Error recovery belongs in `harvard{...}` blocks where `if/else` can guard calls. Fail-fast is correct for quantum circuit verification. - -**Future review**: Exceptions, Result types, or `try/catch` may be considered post-MVP. - ---- - -### D1.15.1: Assertion Decidability -**Decision**: Assertions are runtime-only expressions (MVP). - -**Semantics**: -- `assert P` evaluates `P`; if true, continues; if false, halts (per D1.15) -- If `P` diverges (calls non-terminating function), assertion check diverges -- No static verification, no theorem prover for MVP - -**Consistency**: Follows from D1.13.5 (non-termination allowed) and D1.15 (halt on error). - -**Future review**: Split into `assert` (runtime) vs `prove` (static verification). `prove` would require a static verifier — significant implementation effort but valuable for quantum circuit verification. - ---- - -### D1.15.2: Error Messages — Name-Based -**Decision**: Error messages reference strand names with positional hints. - -**Format**: -``` -Error at line 3: yield boundary mismatch - Expected: strands a:Q, b:R - Got: strands b:R, a:Q - (strand 'a' is in position 2, expected position 1) -``` - -**Rationale**: Users write strand names, not type lists. Messages should speak the user's language. Compiler tracks strand names through weave body. - ---- - -### D1.15.3: Name Conflict Resolution -**Decision**: Unified namespace, innermost binding wins, shadowing emits warning. - -**Binding Priority** (innermost wins): -``` -pattern variable > strand name > let binding > global def -``` - -**Warning**: -``` -Warning: strand name 'a' shadows global definition 'a' at line N -``` - -**Consistency**: Same rule as D1.3.5 (pattern variables) and D1.4.5 (let bindings). All three binding forms follow standard lexical scoping. - ---- - -## Operations - -### D1.16: Primitives and Library Tiering -**Decision**: Three-tier split for TANGLE operations. - -**Tier 1 — Language Primitives** (in compiler, have typing rules): -- `identity` — Word[0], type-directed (D1.14) -- `braid[...]` literals — fundamental data constructor -- `(a > b)`, `(a < b)` crossings — strand interaction -- `(~x)` twist — topological operation (D1.18) -- `.` `|` `+` `>>` — composition operators -- `close` — Tangle[A,A] → Tangle[I,I] (D1.17) -- `cap`, `cup` — create/destroy strand pairs -- `mirror`, `reverse` — structural transforms -- `simplify` — applies Reidemeister moves (needs internal representation access) - -**Tier 2 — Built-in Invariants** (compiler knows names, delegates to backends): -- `jones`, `alexander`, `homfly`, `kauffman`, `writhe`, `linking` -- Reserved names (D1.12) with FFI/plugin backends -- Compiler type-checks, runtime dispatches to invariant engine - -**Tier 3 — Standard Library** (pure TANGLE definitions, shipped with language): -- `length`, `concat`, `braid_repeat`, and similar utilities -- Defined via pattern matching + recursion -- Shipped as `.tangle` files alongside the compiler - ---- - -### D1.17: Close Operation Validation -**Decision**: `close` works on any matching-boundary tangle. No permutation check. - -**Type Rule**: -``` -close : Tangle[A,A] → Tangle[I,I] -``` - -**Semantics**: Connects output strand i to input strand i regardless of permutation. Closing a braid that permutes strands gives a **link** (possibly multi-component), not necessarily a knot. - -**Example**: -```tangle -def c = braid[s1] . braid[s3] # Permutation (1 2)(3 4), NOT identity -def link = close(c) # ✓ Legal — produces a 2-component link -``` - -**Rationale**: Standard knot theory (Alexander's theorem). Any braid closure is a well-defined link. `close` always succeeds on any `Word[n]` since input and output both have n strands. - ---- - -### D1.18: Twist Operator Types -**Decision**: Context-dependent granularity. - -**Standalone** `(~t)` — all-strand twist (categorical θ_A): -``` -(~t) ≜ t . twist_n where n = width of t -Type: Word[n] → Word[n] or Tangle[A,B] → Tangle[A,B] -``` -Composes expression with the all-strand twist tangle. No new semantics — just sugar for composition with a Tier 1 primitive. - -**Weave context** `(~a)` — single named strand: -``` -Γ; strands ⊢ a : T -──────────────────── -Γ; strands ⊢ (~a) : Tangle[[T], [T]] -``` -Twists only the named strand. - -**Resolution**: Compiler checks "am I inside a weave block with a strand named `x`?" If yes, single-strand twist. If no, treat `x` as expression and apply all-strand twist. - ---- - -### D1.19: Self-Crossings in Weave -**Decision**: Allow but warn, desugar to `(~a)`. - -**Semantics**: -```tangle -weave strands a:Q into - (a > a) # ✓ Legal — equivalent to (~a) - # Warning: self-crossing (a > a) is equivalent to (~a) -yield strands a:Q -``` - -**Compiler**: Desugars `(a > a)` to `(~a)` during lowering. Warning suggests canonical form. - ---- - -### D1.20: Pipeline `>>` Precedence -**Decision**: `>>` is sugar for `.` semantically, but has LOWER precedence. - -**Precedence** (lowest to highest): -``` ->> pipeline (lowest) -+ addition / disjoint union -. vertical composition -| horizontal tensor (highest) -``` - -**Example**: -```tangle -# Without >>: parentheses needed -(braid[s1] . braid[s2]) . (braid[s3] . braid[s1]) - -# With >>: pipeline stages visually clear -braid[s1] . braid[s2] >> braid[s3] . braid[s1] -``` - -Both evaluate identically — `.` is associative. Different precedence is purely for **human readability**. - -**Status**: Grammar already implements this correctly. - ---- - -## Polymorphism and Width - -### D1.21: No Full Polymorphism (MVP) -**Decision**: Width inference instead of Hindley-Milner polymorphism. - -**Rules**: -- `identity` is concretely `Word[0]` with auto-widening (D1.14) -- User-defined function widths inferred from usage -- If ambiguous, compiler asks for annotation - -**Example**: -```tangle -def f(x) = x . braid[s1] # x must be at least Word[2], result is Word[2] -``` - -**No** `∀` quantifiers. Width inference is simpler than full polymorphism — just track maximum generator index through expressions. - -**Future**: Full polymorphic boundaries (∀A. Tangle[A,A]) can be added post-MVP. - ---- - -## Module System - -### D1.22: TANGLE Module System -**Decision**: Flat namespace for MVP (no in-language modules). - -**Rules**: -- All `def`s go into one global Γ -- Multiple `.tangle` files loaded in order -- Harvard modules (already in grammar) available for namespacing via JTV - -**Rationale**: TANGLE programs are mathematical objects. Mathematical papers have definitions, not modules. Module system can be added post-MVP if name collisions become a problem. - ---- - -## Standard Library - -### D1.23: Standard Library Functions -**Decision**: Utility functions shipped as pure TANGLE definitions (Tier 3). - -**Included**: -```tangle -# length : Word[n] → Num -def length(w) = match w with - | identity => 0 - | _ . rest => add{ 1 + length(rest) } -end - -# Also: concat, braid_repeat, reverse_word, etc. -``` - -**Rationale**: These are trivially definable with pattern matching + recursion. No reason to bake into the compiler. Also serve as idiomatic TANGLE code examples. - ---- - -## Theoretical Foundations - -### D1.24: Turing Completeness Proof Strategy -**Decision**: Via pattern matching + recursion on Word structure. - -**Proof Sketch**: -- `identity` = nil -- `s_i . rest` = cons(s_i, rest) -- Pattern matching = list destructuring -- Recursion = general recursion - -Pattern matching + recursion on an inductively-defined structure with infinitely many constructors (s1, s2, s3, ...) is Turing complete (standard result). - -**Implication**: Pure TANGLE (without JTV) is Turing complete on its own. Num is a convenience, not a necessity. No braid-as-number encoding needed (D1.6.5). - ---- - -### D1.25: Data Encoding Philosophy -**Decision**: Pure TANGLE handles topology only. Complex data structures live in JTV. - -**Scope**: -- TANGLE: `Word[n]`, `Tangle[A,B]`, `Num`, `Str` — that's it -- Pairs, lists, trees → require `add{...}` / `harvard{...}` blocks -- No braid encoding of data structures (Coherence Problem #5 resolved by design) - -**Rationale**: "Everything topological is a braid, everything else is Harvard." Encoding lists as braids would overload topological meaning with data semantics. The two-world design exists precisely so TANGLE doesn't have to solve this. - -**Implication**: Generator index partitioning (using high indices as type tags) is unnecessary. - ---- - -# PART 2: TANGLE-JTV (Julia-the-Viper Extension) - -## Overview - -TANGLE-JTV extends TANGLE with two delimited syntactic islands: -1. **`add{...}`** - Data-only computations (total, guaranteed terminating) -2. **`harvard{...}`** - Full imperative programs (control + data) - ---- - -## The Three Worlds - -### D2.1: Semantic Stratification - -**TANGLE World** (from Part 1): -- Values: `Word[n]`, `Tangle[𝐀,𝐁]`, `Num`, `Str`, `Bool` -- Control: Pattern matching on Words only -- Environment: Γ (TANGLE definitions) - -**Harvard DATA World** (`add{...}`): -- Values: Total data expressions (numbers, bools, strings) -- Grammar: `hv_data_expr` only (NO if/while/for/assignments) -- Calls: Only @pure/@total functions from Π -- **Guarantee**: Always terminates - -**Harvard CONTROL World** (`harvard{...}`): -- Full imperative language: if/while/for/return/assignments -- Functions with purity markers (@pure/@total) -- Modules, imports -- Environment: Δ (full Harvard), Π ⊆ Δ (pure subset) - ---- - -## Visibility & Environments - -### D2.2: Three Environments -**Decision**: Separate namespaces with one-way bridge. - -``` -Γ : TangleEnv - TANGLE definitions (def, weave) -Δ : HarvardEnv - All Harvard functions, modules -Π ⊆ Δ : PureEnv - Pure/total Harvard functions only -``` - -**Visibility Rules**: -``` -Inside TANGLE expr: calls resolve in Γ only -Inside harvard{...}: calls resolve in Δ -Inside add{...}: calls resolve in Π only -``` - -**Bridge Flow**: -``` -harvard{...} defines functions - ↓ -@pure/@total functions → Π - ↓ -add{...} calls Π functions - ↓ -Results embed via Embed(τ) - ↓ -TANGLE uses embedded values -``` - -**Rationale**: Clean separation prevents effect leakage, maintains totality guarantees. - ---- - -### D2.3: Π Visibility Model (Sequential) -**Decision**: Sequential visibility (MVP). - -**Meaning**: @pure/@total function visible in `add{...}` ONLY AFTER its `harvard{...}` block. - -**Example**: -```tangle -add{ bar() } ✗ ERROR - bar not in Π yet - -harvard{ fn bar() @pure { ... } } - -add{ bar() } ✓ OK - bar now in Π -``` - -**Two-Pass Reconciliation**: -- TANGLE defs collected in pass 1 (forward refs OK) -- Harvard blocks processed sequentially in pass 2 (Π grows) -- add{...} sees current Π at point of use - -**Future**: Two-pass Π in v2 (non-breaking, accepts more programs). - ---- - -## Embedding Bridge - -### D2.4: Embed(τ) Type Bridge -**Decision**: Minimal scalar embedding only (MVP). - -``` -Embed : HarvardType → TangleType - -Embed(Int) = Num -Embed(Float) = Num -Embed(Rational) = Num -Embed(Hex) = Num (convert to numeric) -Embed(Binary) = Num (convert to numeric) -Embed(Bool) = Bool -Embed(String) = Str -Embed(Symbolic) = Str (serialized) - -Embed(Complex) = ERROR ("Complex not yet supported") -Embed(List) = ERROR ("Lists not embeddable") -Embed(Tuple) = ERROR ("Tuples not embeddable") -Embed(Fn ...) = ERROR ("Functions not embeddable") -``` - -**Example**: -```tangle -harvard{ - fn factorial(n: Int) @pure { ... } -} - -def copies = add{ factorial(5) } # Embed(Int) = Num -``` - -**Future Extensions**: -- Phase 2: Complex, structured data (List, Tuple) -- Phase 3: Semantic mappings (List ≈ Word[n]?) - ---- - -## Harvard Semantics - -### D2.5: Harvard Store Persistence -**Decision**: Module-scoped (explicit imports). - -**Semantics**: -```tangle -harvard{ module Math { let x = 5 } } - -harvard{ - import Math - print(Math.x) # ✓ OK - explicit import -} - -harvard{ - print(x) # ✗ ERROR - x not in scope -} -``` - -**Rationale**: Modularity, no accidental global state. - ---- - -### D2.6: Harvard Module Imports -**Decision**: Explicit imports with sequential visibility. - -**Rules**: -- `module M { ... }` registers M in Δ -- `import M` or `import M as Alias` brings M into scope -- **Sequential constraint**: Can only import modules from earlier `harvard{...}` blocks - -**Example**: -```tangle -harvard{ - module Math { - fn sqrt(x: Float) @pure { ... } - } -} - -harvard{ - import Math - fn hypotenuse(a, b) @pure { - Math.sqrt(a*a + b*b) - } -} -``` - -**Rationale**: Consistent with sequential Π visibility (D2.3). - ---- - -## Future Extensions - -### D2.7: Reverse Blocks -**Decision**: Document interface, defer implementation. - -**Status**: -- Parse `reverse{...}` syntax -- Typecheck reversible statements -- Full Bennett semantics: post-MVP - ---- - -## Cross-World Interaction - -### D2.8: Weave Block Visibility -**Decision**: Weave blocks can reference all definitions in Γ (outer scope). - -**Rules**: -```tangle -def helper = braid[s1, s2] - -weave strands a:Q, b:Q into - helper # ✓ Can reference global def -yield strands b:Q, a:Q -``` - -**Rationale**: Weave blocks are TANGLE expressions. They naturally see all of Γ, consistent with D1.9 (any TANGLE expression that typechecks). - ---- - -### D2.9: Harvard Calling TANGLE -**Decision**: Harvard CAN call TANGLE functions, with purity restriction. - -**Rules**: -``` -Unmarked Harvard functions → can call ANY TANGLE function -@pure/@total Harvard functions → can ONLY call non-recursive TANGLE functions -``` - -**Recursion Check**: Syntactic (conservative) — if a TANGLE function's body contains self-reference, it's marked as potentially non-terminating. @pure/@total Harvard code cannot call it. - -**Example**: -```tangle -def simplify_once(w) = ... # Non-recursive — @pure can call ✓ -def loop(w) = loop(w) # Recursive — @pure CANNOT call ✗ - -harvard{ - fn verify(w) @pure { - simplify_once(w) # ✓ OK - # loop(w) # ✗ ERROR: @pure cannot call recursive TANGLE - } - fn debug(w) { - loop(w) # ✓ OK (no purity marker) - } -} -``` - -**Rationale**: Sound (conservative check, never wrong), simple (syntactic), practical (Tier 1 primitives like `simplify`, `jones`, `close` are non-recursive, so @pure Harvard code can call them freely). - ---- - -### D2.10: Reverse Embedding (Unembed) -**Decision**: Implicit scalar Unembed — TANGLE scalars convert to Harvard types automatically. - -**Unembed Rules**: -``` -Unembed(Num) = Int or Float (context-dependent) -Unembed(Str) = String -Unembed(Word[n]) = ERROR ("braids don't cross into Harvard") -Unembed(Tangle[A,B]) = ERROR ("tangles don't cross into Harvard") -``` - -**Bidirectional Scalar Bridge**: -``` -Harvard → TANGLE: Embed(Int) = Num, Embed(String) = Str -TANGLE → Harvard: Unembed(Num) = Int, Unembed(Str) = String -``` - -**Example**: -```tangle -def copies = 5 # TANGLE Num - -harvard{ - fn process(n: Int) @pure { n * 2 } -} - -add{ process(copies) } # ✓ copies (Num) → Int automatically -add{ process(braid[s1]) } # ✗ TYPE ERROR: Word can't cross -``` - -**Rationale**: Symmetric with D2.4 (Embed). Scalars cross both ways, topological types stay in TANGLE. - ---- - -### D2.11: Harvard Module Re-exports -**Decision**: Imports are private to the module (MVP). - -**Rules**: -```tangle -harvard{ - module Utils { - import Math # Private — Utils uses Math internally - fn helper() @pure { Math.sqrt(2) } - } -} - -harvard{ - import Utils - # Utils.helper() ✓ OK - # Math.sqrt(2) ✗ ERROR — must import Math directly -} -``` - -**Rationale**: Keeps dependency chains explicit — you always know where a function comes from. - -**Future review**: Re-exports (like Rust `pub use`) may be added post-MVP if module hierarchies get deep. - ---- - -## Decision Cross-Reference - -### TANGLE-Only Decisions (Part 1): -- D1.1–D1.8.5: Core type system (Word/Tangle split, equality, recursion, scoping, literals, arithmetic, encoding, operators, widening) -- D1.9–D1.11: Weave blocks (expression restrictions, heterogeneous boundaries, yield matching) -- D1.12: Computation (invariants) -- D1.13–D1.13.5: Program structure (definition order, termination, evaluation) -- D1.14–D1.15.3: Error handling (identity width, halt/panic, assertions, error messages, name conflicts) -- D1.16–D1.20: Operations (tiering, close, twist, self-crossings, pipeline) -- D1.21: Polymorphism (width inference, no HM for MVP) -- D1.22: Module system (flat for MVP) -- D1.23: Standard library (Tier 3 definitions) -- D1.24–D1.25: Theoretical foundations (Turing completeness, data encoding) - -### TANGLE-JTV Decisions (Part 2): -- D2.1–D2.3: Three worlds, environments, Π visibility -- D2.4: Embed(τ) type bridge -- D2.5–D2.6: Harvard store persistence, module imports -- D2.7: Reverse blocks (deferred) -- D2.8: Weave block visibility (sees all Γ) -- D2.9: Harvard calling TANGLE (@pure restriction) -- D2.10: Reverse embedding (scalar Unembed) -- D2.11: Module re-exports (private for MVP) - -### Decisions Affecting Both: -- D1.3 (Recursion) — affects D2.9 (Harvard purity check) -- D1.6 (Arithmetic) — add{...} can call Π functions that use arithmetic -- D1.13 (Order) — two-pass for TANGLE, sequential for harvard{...} -- D1.15 (Errors) — Harvard blocks provide error recovery TANGLE lacks -- D1.25 (Data encoding) — TANGLE topology only, complex data via JTV - ---- - -## Implementation Priorities - -**MVP (Minimum Viable Product)**: -- All TANGLE decisions (D1.1–D1.25) -- add{...} blocks with Embed(τ) and Unembed (D2.4, D2.10) -- harvard{...} blocks with @pure functions (D2.2, D2.3, D2.9) -- Sequential Π visibility (D2.3) -- Halt/panic error model (D1.15) -- Width inference (D1.21) -- Flat namespace (D1.22) -- Standard library (D1.23) -- Three-tier operations (D1.16) - -**v2 (Enhanced)**: -- Two-pass Π visibility -- Exhaustiveness checking promoted from warning to error -- Rich Embed(τ) (Complex, List, Tuple) -- Module re-exports (D2.11 future) -- Richer error model (D1.15 future review) -- `assert` vs `prove` split (D1.15.1 future review) - -**v3 (Advanced)**: -- Reverse blocks (Bennett semantics, D2.7) -- Arbitrary yield order permutations -- Full polymorphic boundaries (∀A. Tangle[A,A]) -- Advanced isotopy checkers (Reidemeister, model-based) -- TANGLE module system - ---- - -## Future Review Items - -Items explicitly noted for post-MVP review: -1. **Error handling model** (D1.15) — exceptions, Result types, try/catch -2. **Assert vs Prove split** (D1.15.1) — static verification for quantum circuit proofs -3. **Module re-exports** (D2.11) — Rust-style `pub use` for facade modules - ---- - -## Meta - -- **Specification Version**: 1.0.0-draft -- **Decisions Locked**: 2026-02-12 -- **Total Decisions**: 37 (25 TANGLE + 11 TANGLE-JTV + 1 deferred) -- **Authors**: Jonathan D.A. Jewell, Claude (Sonnet 4.5, Opus 4.6) -- **License**: MPL-2.0 -- **Status**: Ready for formal specification writing - ---- - -## Change Policy - -These decisions are **locked** for the MVP specification. Changes require: -1. Documented rationale -2. Impact analysis (which decisions are affected?) -3. Version bump: - - **Major**: Breaking changes to TANGLE or TANGLE-JTV semantics - - **Minor**: Additive features (e.g., two-pass Π) - - **Patch**: Clarifications, typo fixes - ---- - -## Quick Reference - -**TANGLE** = Part 1 (D1.1–D1.25) -**TANGLE-JTV** = Part 1 + Part 2 (D1.1–D1.25 + D2.1–D2.11) - -**Can I use TANGLE without JTV?** Yes! Part 1 is self-contained. -**Can I use JTV without TANGLE?** No — JTV extends TANGLE. - -### Decision Index - -| ID | Topic | Section | -|----|-------|---------| -| D1.1 | Word vs Tangle split | Core Type System | -| D1.2 | Two equality operators (~ and ==) | Core Type System | -| D1.3 | Recursion on Words | Core Type System | -| D1.3.5 | Pattern variable scoping | Core Type System | -| D1.4 | Match exhaustiveness (runtime + warning) | Core Type System | -| D1.4.5 | Let binding scoping | Core Type System | -| D1.5 | TANGLE literals (Num, Str) | Core Type System | -| D1.6 | Numeric arithmetic (+ overloaded) | Core Type System | -| D1.6.5 | Numeric encoding (Num ≠ Word) | Core Type System | -| D1.7 | Tangle + restriction (closed only) | Core Type System | -| D1.8 | Operator disambiguation (. and identity) | Core Type System | -| D1.8.5 | Auto-widening on composition | Core Type System | -| D1.9 | Weave expression restrictions | Weave Blocks | -| D1.10 | Heterogeneous typed boundaries | Weave Blocks | -| D1.11 | Yield boundary matching (exact) | Weave Blocks | -| D1.12 | Invariant computation (built-in + FFI) | Computation | -| D1.13 | Top-level definition order (two-pass) | Program Structure | -| D1.13.5 | Termination and evaluation (CBV) | Program Structure | -| D1.14 | Identity width (Word[0]) | Error Handling | -| D1.15 | Error handling (halt/panic) | Error Handling | -| D1.15.1 | Assertion decidability (runtime only) | Error Handling | -| D1.15.2 | Error messages (name-based) | Error Handling | -| D1.15.3 | Name conflict resolution (unified, warn) | Error Handling | -| D1.16 | Primitives tiering (3 tiers) | Operations | -| D1.17 | Close operation (no permutation check) | Operations | -| D1.18 | Twist operator (context-dependent) | Operations | -| D1.19 | Self-crossings (allow, warn, desugar) | Operations | -| D1.20 | Pipeline >> precedence | Operations | -| D1.21 | No full polymorphism (width inference) | Polymorphism | -| D1.22 | Flat module system | Module System | -| D1.23 | Standard library (Tier 3) | Standard Library | -| D1.24 | Turing completeness proof | Theoretical | -| D1.25 | Data encoding (topology only) | Theoretical | -| D2.1 | Semantic stratification (3 worlds) | Three Worlds | -| D2.2 | Three environments (Γ, Δ, Π) | Visibility | -| D2.3 | Π sequential visibility | Visibility | -| D2.4 | Embed(τ) scalar bridge | Embedding | -| D2.5 | Harvard store persistence | Harvard Semantics | -| D2.6 | Harvard module imports | Harvard Semantics | -| D2.7 | Reverse blocks (deferred) | Future | -| D2.8 | Weave block visibility (all Γ) | Cross-World | -| D2.9 | Harvard calling TANGLE (@pure restriction) | Cross-World | -| D2.10 | Reverse embedding (scalar Unembed) | Cross-World | -| D2.11 | Module re-exports (private MVP) | Cross-World | diff --git a/docs/spec/ECHO-TANGLEIR-THREADING.adoc b/docs/spec/ECHO-TANGLEIR-THREADING.adoc new file mode 100644 index 0000000..b50c240 --- /dev/null +++ b/docs/spec/ECHO-TANGLEIR-THREADING.adoc @@ -0,0 +1,143 @@ +== Echo residue threading into TangleIR — cross-repo contract + +*Status:* design / coordination contract (2026-06-14). Authored in +`+tangle+` (the semantics owner). The TangleIR type change and the +QuandleDB consumer change live in *`+KRLAdapter.jl+`* (TangleIR +definition + adapters) and *`+quandledb+`* — both Julia, outside this +session’s scope — so this file is the _contract_ those repos implement, +not the implementation. + +=== 1. Why threading the residue matters + +Tangle’s `+close : Word[n] → Word[0]+` is the canonical *lossy* map: it +collapses a braid to the identity, discarding the word. Echo types +(`+proofs/Tangle.lean+` §ECHO-TYPES; `+compiler/lib/typecheck.ml+`) make +that loss recoverable — `+echoClose b+` retains the braid as a +*residue*, and `+residue (echoClose b) ⟶ b+` +(`+echo_residue_recovers+`). + +The seam with QuandleDB is exact, not incidental: + +____ +A *quandle presentation is an invariant of the knot*, and the knot is +the *closure of the braid*. `+close+` is precisely the braid→knot step. +So the residue retained by `+echoClose+` — the _pre-closure braid_ — is +exactly the object +`+quandle_presentation(ir::TangleIR)::QuandlePresentation+` derives the +quandle from. +____ + +`+echo_distinguishes_collapsed+` (Lean) says distinct braids can close +to the same diagram while keeping distinct residues. Threading the +residue therefore gives QuandleDB *provenance*: which braid produced a +given closed diagram, disambiguating cases that plain `+close+` would +conflate. *A note on what the Lean model proves.* The mechanized +`+close+`/`+lower+` (`+proofs/Tangle.lean+`) is a _type-level_ collapse: +every braid reduces to the single `+Word[0]+` value `+.identity+` (a +collapse to one point), *not* to a knot diagram. So +`+echo_distinguishes_collapsed+` proves only that distinct braids share +that identity result while their residues stay distinct — it is *not* +the knot-theoretic statement "`distinct braids close to the same knot +diagram.`" That geometric closure is a separate notion, modelled by the +compositional PD compiler (`+compositional.ml+`) and +`+FORMAL-SEMANTICS.md+` (`+close : Tangle[I,I]+`), and is *not* +mechanized here. What the proofs _do_ establish — residue recovery +(`+echo_residue_recovers+`) and type-safe round-trip +(`+echo_roundtrip_typed+`) — is sufficient to justify threading the +residue braid to QuandleDB for *provenance* (which braid produced a +given closed diagram), even though the knot-level conflation itself is +an external knot-theory fact. + +=== 2. The contract per layer + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|Layer |Repo |Responsibility +|Semantics |`+tangle+` (this repo) |Defines echo types + residue +semantics. `+residue (echoClose b) = b+`; +`+lower (echoClose b) = identity+`. Mechanised in +`+proofs/Tangle.lean+`; checked in `+typecheck.ml+` +(`+TEcho+`/`+TProd+`, rules +`+[T-Echo-Close]+`/`+[T-Lower]+`/`+[T-Residue]+`). + +|Interchange |`+KRLAdapter.jl+` |TangleIR represents an echo-closed term +*carrying the residue braid alongside the closed result* (see §3). A +plain `+close+` node is unchanged (no residue). + +|Consumer |`+quandledb+` |`+quandle_presentation+` reads the residue +braid of an echo-closed node to compute the quandle (the pre-closure +braid determines the knot). Plain-`+close+` behaviour unchanged. +|=== + +=== 3. Proposed TangleIR representation (for KRLAdapter.jl) + +Mirror the Lean `+echoVal (residue, result)+` shape. Two equivalent +options; recommend (a): + +* *(a) Residue-carrying closure node.* Add an IR node +`+EchoClosed(residue::BraidWord, result::ClosedDiagram)+` — the closed +diagram plus the braid it came from. `+lower+`/`+residue+` IR +projections read `+.result+` / `+.residue+`. This keeps the closed +diagram identical to the plain-`+close+` output (so existing consumers +are unaffected) while exposing the braid. +* *(b) Residue as closure metadata.* Keep the existing closure node and +attach the pre-closure braid as an optional metadata field +(`+residue::Union{BraidWord,Nothing}+`). Lighter, but makes the residue +optional rather than type-guaranteed — weaker than the Lean guarantee. + +Products (`+Ty.prod+` / `+pair+`/`+fst+`/`+snd+`) are the residue +carrier for the binary lossy ops (`+echoAdd+`/`+echoEq+`): their residue +is the *pair of operands*. If TangleIR needs to represent those, add a +`+Pair(a, b)+` IR node with `+fst+`/`+snd+` projections. (For QuandleDB +specifically, only the `+echoClose+` residue is knot-relevant; +`+echoAdd+`/`+echoEq+` residues are scalar provenance.) + +=== 4. Consumer contract (for quandledb) + +.... +quandle_presentation(ir::TangleIR) = + case ir of + EchoClosed(residue, _result) -> quandle_of_braid(residue) # use the braid + Close(diagram) -> quandle_of_diagram(diagram) # unchanged + ... +.... + +The invariant to preserve: for any braid `+b+`, +`+quandle_presentation(EchoClosed(b, close(b)))+` ≡ +`+quandle_presentation(Close(close(b)))+` whenever the closed diagram +alone suffices — the residue path must agree with the diagram path on +the quandle, and additionally retains `+b+` for provenance. This mirrors +`+echo_roundtrip_typed+` (the residue/result projections are well-typed) +and the `+lower+`/`+residue+` agreement in the Lean model. and +additionally retains `+b+` for provenance. + +*This quandle invariant is an unproven knot-theoretic obligation* that +QuandleDB must establish itself: it is _not_ mechanized in Lean nor +checked in OCaml (the word `+quandle+` appears in neither). The Lean +theorem `+echo_roundtrip_typed+` only guarantees that the residue/result +projections are *well-typed* (`+residue : Word[n]+`, +`+lower : Word[0]+`); it says nothing about quandle equality, and +`+lower+`/`+residue+` project _different_ components (they diverge by +design — `+echo_distinguishes_collapsed+` — they do not "`agree`"). The +mechanized backing for threading is narrower than quandle agreement: +residue recovery plus type-safe round-trip. + +=== 5. Scope / coordination + +* *No TangleIR or QuandleDB code is changed by this document.* Those are +KRLAdapter.jl/quandledb (Julia) changes, to be made by the quandle +session. +* *An OCaml-side `+EchoClosed+` node now exists* in tangle’s own +compositional PD compiler (`+compiler/lib/compositional.ml+`), reachable +via `+tanglec --compile-pd+`. It mirrors option (a) and emits the +residue braid, but it is a _different_ IR from the Julia TangleIR this +contract specifies — it is the producer-side reference, not the +interchange schema. The Julia TangleIR / QuandleDB consumer work remains +pending. +* This contract is additive and conservative: plain `+close+` is +untouched, so existing TangleIR producers/consumers keep working; +echo-closed nodes are new. +* Cross-reference: `+proofs/Tangle.lean+` (`+echo_residue_recovers+`, +`+echo_distinguishes_collapsed+`, `+echo_roundtrip_typed+`), +`+.machine_readable/6a2/ECOSYSTEM.a2ml+` (the echo↔quandle seam), and +`+quandledb+`’s `+quandle_presentation+`. diff --git a/docs/spec/ECHO-TANGLEIR-THREADING.md b/docs/spec/ECHO-TANGLEIR-THREADING.md deleted file mode 100644 index f7cb057..0000000 --- a/docs/spec/ECHO-TANGLEIR-THREADING.md +++ /dev/null @@ -1,121 +0,0 @@ - -# Echo residue threading into TangleIR — cross-repo contract - -**Status:** design / coordination contract (2026-06-14). Authored in `tangle` -(the semantics owner). The TangleIR type change and the QuandleDB consumer -change live in **`KRLAdapter.jl`** (TangleIR definition + adapters) and -**`quandledb`** — both Julia, outside this session's scope — so this file is -the *contract* those repos implement, not the implementation. - -## 1. Why threading the residue matters - -Tangle's `close : Word[n] → Word[0]` is the canonical **lossy** map: it -collapses a braid to the identity, discarding the word. Echo types -(`proofs/Tangle.lean` §ECHO-TYPES; `compiler/lib/typecheck.ml`) make that loss -recoverable — `echoClose b` retains the braid as a **residue**, and -`residue (echoClose b) ⟶ b` (`echo_residue_recovers`). - -The seam with QuandleDB is exact, not incidental: - -> A **quandle presentation is an invariant of the knot**, and the knot is the -> **closure of the braid**. `close` is precisely the braid→knot step. So the -> residue retained by `echoClose` — the *pre-closure braid* — is exactly the -> object `quandle_presentation(ir::TangleIR)::QuandlePresentation` derives the -> quandle from. - -`echo_distinguishes_collapsed` (Lean) says distinct braids can close to the -same diagram while keeping distinct residues. Threading the residue therefore -gives QuandleDB **provenance**: which braid produced a given closed diagram, -disambiguating cases that plain `close` would conflate. -**A note on what the Lean model proves.** The mechanized `close`/`lower` -(`proofs/Tangle.lean`) is a *type-level* collapse: every braid reduces to the -single `Word[0]` value `.identity` (a collapse to one point), **not** to a knot -diagram. So `echo_distinguishes_collapsed` proves only that distinct braids -share that identity result while their residues stay distinct — it is **not** -the knot-theoretic statement "distinct braids close to the same knot diagram." -That geometric closure is a separate notion, modelled by the compositional PD -compiler (`compositional.ml`) and `FORMAL-SEMANTICS.md` (`close : Tangle[I,I]`), -and is **not** mechanized here. What the proofs *do* establish — residue -recovery (`echo_residue_recovers`) and type-safe round-trip -(`echo_roundtrip_typed`) — is sufficient to justify threading the residue braid -to QuandleDB for **provenance** (which braid produced a given closed diagram), -even though the knot-level conflation itself is an external knot-theory fact. - -## 2. The contract per layer - -| Layer | Repo | Responsibility | -|---|---|---| -| Semantics | `tangle` (this repo) | Defines echo types + residue semantics. `residue (echoClose b) = b`; `lower (echoClose b) = identity`. Mechanised in `proofs/Tangle.lean`; checked in `typecheck.ml` (`TEcho`/`TProd`, rules `[T-Echo-Close]`/`[T-Lower]`/`[T-Residue]`). | -| Interchange | `KRLAdapter.jl` | TangleIR represents an echo-closed term **carrying the residue braid alongside the closed result** (see §3). A plain `close` node is unchanged (no residue). | -| Consumer | `quandledb` | `quandle_presentation` reads the residue braid of an echo-closed node to compute the quandle (the pre-closure braid determines the knot). Plain-`close` behaviour unchanged. | - -## 3. Proposed TangleIR representation (for KRLAdapter.jl) - -Mirror the Lean `echoVal (residue, result)` shape. Two equivalent options; -recommend (a): - -* **(a) Residue-carrying closure node.** Add an IR node - `EchoClosed(residue::BraidWord, result::ClosedDiagram)` — the closed diagram - plus the braid it came from. `lower`/`residue` IR projections read `.result` - / `.residue`. This keeps the closed diagram identical to the plain-`close` - output (so existing consumers are unaffected) while exposing the braid. -* **(b) Residue as closure metadata.** Keep the existing closure node and attach - the pre-closure braid as an optional metadata field - (`residue::Union{BraidWord,Nothing}`). Lighter, but makes the residue - optional rather than type-guaranteed — weaker than the Lean guarantee. - -Products (`Ty.prod` / `pair`/`fst`/`snd`) are the residue carrier for the -binary lossy ops (`echoAdd`/`echoEq`): their residue is the **pair of operands**. -If TangleIR needs to represent those, add a `Pair(a, b)` IR node with `fst`/`snd` -projections. (For QuandleDB specifically, only the `echoClose` residue is -knot-relevant; `echoAdd`/`echoEq` residues are scalar provenance.) - -## 4. Consumer contract (for quandledb) - -``` -quandle_presentation(ir::TangleIR) = - case ir of - EchoClosed(residue, _result) -> quandle_of_braid(residue) # use the braid - Close(diagram) -> quandle_of_diagram(diagram) # unchanged - ... -``` - -The invariant to preserve: for any braid `b`, -`quandle_presentation(EchoClosed(b, close(b)))` ≡ -`quandle_presentation(Close(close(b)))` whenever the closed diagram alone -suffices — the residue path must agree with the diagram path on the quandle, -and additionally retains `b` for provenance. This mirrors -`echo_roundtrip_typed` (the residue/result projections are well-typed) and the -`lower`/`residue` agreement in the Lean model. -and additionally retains `b` for provenance. - -**This quandle invariant is an unproven knot-theoretic obligation** that -QuandleDB must establish itself: it is *not* mechanized in Lean nor checked in -OCaml (the word `quandle` appears in neither). The Lean theorem -`echo_roundtrip_typed` only guarantees that the residue/result projections are -**well-typed** (`residue : Word[n]`, `lower : Word[0]`); it says nothing about -quandle equality, and `lower`/`residue` project *different* components (they -diverge by design — `echo_distinguishes_collapsed` — they do not "agree"). The -mechanized backing for threading is narrower than quandle agreement: residue -recovery plus type-safe round-trip. - -## 5. Scope / coordination - -- **No TangleIR or QuandleDB code is changed by this document.** Those are - KRLAdapter.jl/quandledb (Julia) changes, to be made by the quandle session. -- **An OCaml-side `EchoClosed` node now exists** in tangle's own compositional - PD compiler (`compiler/lib/compositional.ml`), reachable via `tanglec - --compile-pd`. It mirrors option (a) and emits the residue braid, but it is a - *different* IR from the Julia TangleIR this contract specifies — it is the - producer-side reference, not the interchange schema. The Julia TangleIR / - QuandleDB consumer work remains pending. -- This contract is additive and conservative: plain `close` is untouched, so - existing TangleIR producers/consumers keep working; echo-closed nodes are new. -- Cross-reference: `proofs/Tangle.lean` (`echo_residue_recovers`, - `echo_distinguishes_collapsed`, `echo_roundtrip_typed`), - `.machine_readable/6a2/ECOSYSTEM.a2ml` (the echo↔quandle seam), - and `quandledb`'s `quandle_presentation`. diff --git a/docs/spec/FEATURE-COVERAGE.adoc b/docs/spec/FEATURE-COVERAGE.adoc new file mode 100644 index 0000000..c5b3486 --- /dev/null +++ b/docs/spec/FEATURE-COVERAGE.adoc @@ -0,0 +1,151 @@ +== TANGLE & TANGLE-JTV Feature Coverage + +SPDX-License-Identifier: CC-BY-SA-4.0 + +Last updated: 2026-06-14 + +This document maps language features to design decisions and formal +rules. + +''''' + +=== TANGLE Core Features + +[width="100%",cols="19%,20%,24%,22%,15%",options="header",] +|=== +|Feature |Decisions |Typing Rules |Eval Rules |Status +|Named definitions with parameters |D1.3, D1.13 |T-Def-Fun, T-Def-Val +|E-App |Complete + +|Braid literals (Word[n]) |D1.1, D1.14 |T-Braid, T-Braid-Empty, +T-Identity |E-Braid, E-Identity |Complete + +|Vertical composition (`+.+`) |D1.8, D1.8.5 |T-Compose-Word, +T-Compose-Tangle |E-Compose-Word, E-Compose-Tangle |Complete + +|Horizontal tensor (`+\|+`) |D1.8 |T-Tensor-Word, T-Tensor-Tangle +|E-Tensor-Word |Complete + +|Pipeline (`+>>+`) |D1.20 |T-Pipeline |E-Pipeline |Complete + +|Addition (`+++`) |D1.6, D1.7 |T-Add-Num, T-Add-Tangle |E-Add-Num, +E-Add-Tangle |Complete + +|Arithmetic (`+-+`, `+*+`, `+/+`) |D1.6 |T-Arith |E-Arith, E-Div-Zero +|Complete + +|Structural equality (`+==+`) |D1.2 |T-Eq-Word, T-Eq-Num, T-Eq-Str +|E-Eq-Word, E-Eq-Num, E-Eq-Str |Complete + +|Isotopy equivalence (`+~+`) |D1.2 |T-Isotopy |E-Isotopy |Complete + +|Crossings (`+>+`, `+<+`) |D1.10 |T-Cross-Over, T-Cross-Under |E-Cross +|Complete + +|Twist (`+~+`) |D1.18, D1.19 |T-Twist-Word, T-Twist-Tangle, +T-Twist-Strand, T-Self-Cross |E-Twist-Standalone |Complete + +|close() |D1.17 |T-Close-Tangle, T-Close-Word |E-Close-Word, +E-Close-Tangle |Complete + +|mirror() |D1.16 |T-Mirror-Tangle, T-Mirror-Word |E-Mirror-Word +|Complete + +|reverse() |D1.16 |T-Reverse |E-Reverse |Complete + +|simplify() |D1.16 |T-Simplify-Word, T-Simplify-Tangle |E-Simplify +|Complete + +|cap/cup |D1.16 |T-Cap, T-Cup, T-Cap-Typed, T-Cup-Typed |— |Complete + +|Pattern matching |D1.3, D1.4 |T-Match, P-Identity, P-Cons, P-Var, +P-Wildcard |E-Match-Hit, E-Match-Fail, M-* |Complete + +|Let binding |D1.4.5 |T-Let |E-Let |Complete + +|Weave blocks |D1.9-D1.11, D2.8 |T-Weave |E-Cross, E-Yield-Mismatch +|Complete + +|Assertions |D1.15, D1.15.1 |T-Assert |E-Assert-Pass, E-Assert-Fail +|Complete + +|Invariant computation |D1.12, D1.16 |T-Compute |E-Compute |Complete + +|Auto-widening |D1.8.5, D1.14 |T-Compose-Word |E-Compose-Word |Complete + +|Word→Tangle coercion |D1.1 |T-Realize, T-Realize-Default |— |Complete + +|Width inference |D1.21 |§3.14 |— |Complete + +|Two-pass program typing |D1.13 |T-Program |§4.16 |Complete + +|Boolean literals |— |T-True, T-False |E-True, E-False |Complete + +|Error propagation |D1.15 |— |E-Halt-Left, E-Halt-Right |Complete + +|Echo type former (`+TEcho ρ τ+`) |— |T-Echo-Close, T-Lower, T-Residue, +T-Echo-Val |— |Complete + +|Product type (`+TProd α β+`) |— |T-Pair, T-Fst, T-Snd |E-Pair-L/R, +E-Fst-Pair, E-Snd-Pair |Complete + +|`+echoClose(e)+` |— |T-Echo-Close |E-Echo-Close-Word, E-Echo-Close-Id +|Complete + +|`+lower(e)+` |— |T-Lower |E-Lower-Val |Complete + +|`+residue(e)+` |— |T-Residue |E-Residue-Val |Complete + +|`+pair(a, b)+` |— |T-Pair |E-Pair-L, E-Pair-R |Complete + +|`+fst(e)+` / `+snd(e)+` |— |T-Fst, T-Snd |E-Fst-Step, E-Fst-Pair, +E-Snd-Step, E-Snd-Pair |Complete + +|`+echoAdd(a, b)+` |— |T-Echo-Add |E-EchoAdd-L/R, E-EchoAdd-Nums +|Complete + +|`+echoEq(a, b)+` |— |T-Echo-Eq-Word/Num/Str |E-EchoEq-L/R, +E-EchoEq-\{Nums,Strs,Braids,IdId,IdBraid,BraidId} |Complete +|=== + +=== TANGLE-JTV Extension Features + +[width="100%",cols="19%,20%,24%,22%,15%",options="header",] +|=== +|Feature |Decisions |Typing Rules |Eval Rules |Status +|add\{} blocks |D2.1, D2.4 |T-Add, HD-* |E-Add, EHD-* |Complete + +|harvard\{} blocks |D2.1 |T-Harvard |E-Harvard |Complete + +|Three environments (Γ, Δ, Π) |D2.2, D2.3 |§8 |§10 |Complete + +|Embed/Unembed |D2.4, D2.10 |T-Unembed, §7.2 |E-Unembed-* |Complete + +|Harvard data expr |D2.1 |HD-Num, HD-Str, HD-Bool, HD-Var, HD-App, +HD-Arith, HD-Compare, HD-And, HD-Or, HD-Not, HD-Neg, HD-If |EHD-Num, +EHD-App, EHD-If-* |Complete + +|Harvard control stmts |D2.1 |§6.3 |§10.4 |Complete + +|Harvard calling TANGLE |D2.9 |HC-Call-Tangle-Pure, +HC-Call-Tangle-Impure |— |Complete + +|Purity markers |D2.3, D2.9 |§9.5 |— |Complete + +|Module system |D2.6, D2.11 |HC-Import, HC-Import-Alias |— |Complete + +|Reversible blocks |D2.1 |§6.3 |— |Specified in grammar +|=== + +''''' + +=== Coverage Summary + +*TANGLE Core*: 36/36 features fully specified (100%) *TANGLE-JTV*: 10/10 +features fully specified (100%) *Total decisions referenced*: 44 +(D1.1-D1.25, D2.1-D2.11) *Total typing rules*: 26 HasType rules (Lean); +37+ spec rules *Total evaluation rules*: 55 Step rules (Lean); 26+ spec +rules + +All features have corresponding grammar productions in EBNF, typing +rules in FORMAL-SEMANTICS.md, and evaluation rules where applicable. diff --git a/docs/spec/FEATURE-COVERAGE.md b/docs/spec/FEATURE-COVERAGE.md deleted file mode 100644 index 80252cd..0000000 --- a/docs/spec/FEATURE-COVERAGE.md +++ /dev/null @@ -1,82 +0,0 @@ - -# TANGLE & TANGLE-JTV Feature Coverage - -SPDX-License-Identifier: CC-BY-SA-4.0 - -Last updated: 2026-06-14 - -This document maps language features to design decisions and formal rules. - ---- - -## TANGLE Core Features - -| Feature | Decisions | Typing Rules | Eval Rules | Status | -|---------|-----------|-------------|------------|--------| -| Named definitions with parameters | D1.3, D1.13 | T-Def-Fun, T-Def-Val | E-App | Complete | -| Braid literals (Word[n]) | D1.1, D1.14 | T-Braid, T-Braid-Empty, T-Identity | E-Braid, E-Identity | Complete | -| Vertical composition (`.`) | D1.8, D1.8.5 | T-Compose-Word, T-Compose-Tangle | E-Compose-Word, E-Compose-Tangle | Complete | -| Horizontal tensor (`\|`) | D1.8 | T-Tensor-Word, T-Tensor-Tangle | E-Tensor-Word | Complete | -| Pipeline (`>>`) | D1.20 | T-Pipeline | E-Pipeline | Complete | -| Addition (`+`) | D1.6, D1.7 | T-Add-Num, T-Add-Tangle | E-Add-Num, E-Add-Tangle | Complete | -| Arithmetic (`-`, `*`, `/`) | D1.6 | T-Arith | E-Arith, E-Div-Zero | Complete | -| Structural equality (`==`) | D1.2 | T-Eq-Word, T-Eq-Num, T-Eq-Str | E-Eq-Word, E-Eq-Num, E-Eq-Str | Complete | -| Isotopy equivalence (`~`) | D1.2 | T-Isotopy | E-Isotopy | Complete | -| Crossings (`>`, `<`) | D1.10 | T-Cross-Over, T-Cross-Under | E-Cross | Complete | -| Twist (`~`) | D1.18, D1.19 | T-Twist-Word, T-Twist-Tangle, T-Twist-Strand, T-Self-Cross | E-Twist-Standalone | Complete | -| close() | D1.17 | T-Close-Tangle, T-Close-Word | E-Close-Word, E-Close-Tangle | Complete | -| mirror() | D1.16 | T-Mirror-Tangle, T-Mirror-Word | E-Mirror-Word | Complete | -| reverse() | D1.16 | T-Reverse | E-Reverse | Complete | -| simplify() | D1.16 | T-Simplify-Word, T-Simplify-Tangle | E-Simplify | Complete | -| cap/cup | D1.16 | T-Cap, T-Cup, T-Cap-Typed, T-Cup-Typed | — | Complete | -| Pattern matching | D1.3, D1.4 | T-Match, P-Identity, P-Cons, P-Var, P-Wildcard | E-Match-Hit, E-Match-Fail, M-* | Complete | -| Let binding | D1.4.5 | T-Let | E-Let | Complete | -| Weave blocks | D1.9-D1.11, D2.8 | T-Weave | E-Cross, E-Yield-Mismatch | Complete | -| Assertions | D1.15, D1.15.1 | T-Assert | E-Assert-Pass, E-Assert-Fail | Complete | -| Invariant computation | D1.12, D1.16 | T-Compute | E-Compute | Complete | -| Auto-widening | D1.8.5, D1.14 | T-Compose-Word | E-Compose-Word | Complete | -| Word→Tangle coercion | D1.1 | T-Realize, T-Realize-Default | — | Complete | -| Width inference | D1.21 | §3.14 | — | Complete | -| Two-pass program typing | D1.13 | T-Program | §4.16 | Complete | -| Boolean literals | — | T-True, T-False | E-True, E-False | Complete | -| Error propagation | D1.15 | — | E-Halt-Left, E-Halt-Right | Complete | -| Echo type former (`TEcho ρ τ`) | — | T-Echo-Close, T-Lower, T-Residue, T-Echo-Val | — | Complete | -| Product type (`TProd α β`) | — | T-Pair, T-Fst, T-Snd | E-Pair-L/R, E-Fst-Pair, E-Snd-Pair | Complete | -| `echoClose(e)` | — | T-Echo-Close | E-Echo-Close-Word, E-Echo-Close-Id | Complete | -| `lower(e)` | — | T-Lower | E-Lower-Val | Complete | -| `residue(e)` | — | T-Residue | E-Residue-Val | Complete | -| `pair(a, b)` | — | T-Pair | E-Pair-L, E-Pair-R | Complete | -| `fst(e)` / `snd(e)` | — | T-Fst, T-Snd | E-Fst-Step, E-Fst-Pair, E-Snd-Step, E-Snd-Pair | Complete | -| `echoAdd(a, b)` | — | T-Echo-Add | E-EchoAdd-L/R, E-EchoAdd-Nums | Complete | -| `echoEq(a, b)` | — | T-Echo-Eq-Word/Num/Str | E-EchoEq-L/R, E-EchoEq-{Nums,Strs,Braids,IdId,IdBraid,BraidId} | Complete | - -## TANGLE-JTV Extension Features - -| Feature | Decisions | Typing Rules | Eval Rules | Status | -|---------|-----------|-------------|------------|--------| -| add{} blocks | D2.1, D2.4 | T-Add, HD-* | E-Add, EHD-* | Complete | -| harvard{} blocks | D2.1 | T-Harvard | E-Harvard | Complete | -| Three environments (Γ, Δ, Π) | D2.2, D2.3 | §8 | §10 | Complete | -| Embed/Unembed | D2.4, D2.10 | T-Unembed, §7.2 | E-Unembed-* | Complete | -| Harvard data expr | D2.1 | HD-Num, HD-Str, HD-Bool, HD-Var, HD-App, HD-Arith, HD-Compare, HD-And, HD-Or, HD-Not, HD-Neg, HD-If | EHD-Num, EHD-App, EHD-If-* | Complete | -| Harvard control stmts | D2.1 | §6.3 | §10.4 | Complete | -| Harvard calling TANGLE | D2.9 | HC-Call-Tangle-Pure, HC-Call-Tangle-Impure | — | Complete | -| Purity markers | D2.3, D2.9 | §9.5 | — | Complete | -| Module system | D2.6, D2.11 | HC-Import, HC-Import-Alias | — | Complete | -| Reversible blocks | D2.1 | §6.3 | — | Specified in grammar | - ---- - -## Coverage Summary - -**TANGLE Core**: 36/36 features fully specified (100%) -**TANGLE-JTV**: 10/10 features fully specified (100%) -**Total decisions referenced**: 44 (D1.1-D1.25, D2.1-D2.11) -**Total typing rules**: 26 HasType rules (Lean); 37+ spec rules -**Total evaluation rules**: 55 Step rules (Lean); 26+ spec rules - -All features have corresponding grammar productions in EBNF, typing rules in -FORMAL-SEMANTICS.md, and evaluation rules where applicable. diff --git a/docs/spec/FORMAL-SEMANTICS.md b/docs/spec/FORMAL-SEMANTICS.adoc similarity index 73% rename from docs/spec/FORMAL-SEMANTICS.md rename to docs/spec/FORMAL-SEMANTICS.adoc index 5578281..70318f2 100644 --- a/docs/spec/FORMAL-SEMANTICS.md +++ b/docs/spec/FORMAL-SEMANTICS.adoc @@ -1,27 +1,21 @@ - -# TANGLE & TANGLE-JTV Formal Semantics +== TANGLE & TANGLE-JTV Formal Semantics -Specification Version: 1.0.0-draft -Date: 2026-02-12 -Authors: Jonathan D.A. Jewell, Claude (Opus 4.6) -License: MPL-2.0 +Specification Version: 1.0.0-draft Date: 2026-02-12 Authors: Jonathan +D.A. Jewell, Claude (Opus 4.6) License: MPL-2.0 -This document defines the formal typing rules and operational semantics for -TANGLE (Part 1) and TANGLE-JTV (Part 2). All rules reference locked decisions -in DECISIONS-LOCKED.md. +This document defines the formal typing rules and operational semantics +for TANGLE (Part 1) and TANGLE-JTV (Part 2). All rules reference locked +decisions in DECISIONS-LOCKED.md. ---- +''''' -# Part 1: TANGLE +== Part 1: TANGLE -## 1. Abstract Syntax +=== 1. Abstract Syntax -### 1.1 Programs +==== 1.1 Programs -``` +.... prog ::= stmt₁ ; ... ; stmtₙ stmt ::= def x = e -- value definition @@ -29,11 +23,11 @@ stmt ::= def x = e -- value defin | weave strands S_in into e yield strands S_out -- weave block | compute inv(e) -- invariant computation | assert e -- assertion (e : Bool) -``` +.... -### 1.2 Expressions +==== 1.2 Expressions -``` +.... e ::= x -- variable reference | n -- numeric literal (integer or float) | "s" -- string literal @@ -70,128 +64,133 @@ e ::= x -- variable reference | snd(e) -- second projection | echoAdd(e₁, e₂) -- addition with summand residue | echoEq(e₁, e₂) -- equality with operand residue -``` +.... -### 1.3 Generators +==== 1.3 Generators -``` +.... g ::= sᵢ -- positive generator (strand i over strand i+1) | sᵢ⁻¹ -- inverse generator (strand i+1 over strand i) index(sᵢ) = i index(sᵢ⁻¹) = i -``` +.... -### 1.4 Patterns +==== 1.4 Patterns -``` +.... p ::= identity -- matches empty word | g . p -- matches generator g followed by pattern p | x -- variable pattern (binds x to matched value) | _ -- wildcard (matches anything, binds nothing) -``` +.... -### 1.5 Types (Extended) +==== 1.5 Types (Extended) The type language is extended with two new type formers: -``` +.... τ ::= ... -- (all prior types) | Echo ρ τ -- echo type: result τ carrying witness ρ | ρ × σ -- product type (residue carrier for binary lossy ops) -``` +.... -`Echo ρ τ` is introduced by `echoClose`, `echoAdd`, `echoEq` and eliminated by `lower` (project result) and `residue` (recover witness). `ρ × σ` is the residue carrier type for binary operations: `echoAdd` has residue type `Num × Num`; `echoEq` has residue type `ρ × ρ`. +`+Echo ρ τ+` is introduced by `+echoClose+`, `+echoAdd+`, `+echoEq+` and +eliminated by `+lower+` (project result) and `+residue+` (recover +witness). `+ρ × σ+` is the residue carrier type for binary operations: +`+echoAdd+` has residue type `+Num × Num+`; `+echoEq+` has residue type +`+ρ × ρ+`. -### 1.6 Strand Declarations +==== 1.6 Strand Declarations -``` +.... S ::= a₁:T₁, ..., aₙ:Tₙ -- named typed strand list -``` +.... ---- +''''' -## 2. Types +=== 2. Types -### 2.1 Type Syntax +==== 2.1 Type Syntax -``` +.... τ ::= Word[n] -- braid word on n strands (n ≥ 0) | Tangle[A, B] -- tangle morphism from boundary A to boundary B | Num -- numbers (integers and floats) | Str -- strings | Bool -- booleans -``` +.... -### 2.2 Boundaries +==== 2.2 Boundaries -``` +.... A, B ::= [T₁, ..., Tₖ] -- ordered list of strand types (k ≥ 0) | I -- empty boundary (alias for []) |A| = length of boundary A A ++ B = concatenation of boundaries -``` +.... -### 2.3 Strand Types +==== 2.3 Strand Types -``` +.... T ::= Q | R | S | ... -- named strand types (from weave declarations) | Strand -- default strand type (when unannoted) -``` +.... -### 2.4 Function Signatures +==== 2.4 Function Signatures -Functions are not first-class. Their signatures are recorded in the environment. +Functions are not first-class. Their signatures are recorded in the +environment. -``` +.... sig ::= (τ₁, ..., τₖ) → τ -- k-argument function type -``` +.... -### 2.5 Width Function +==== 2.5 Width Function -``` +.... width(identity) = 0 width(braid[g₁, ..., gₖ]) = max(index(gⱼ) + 1 for j = 1..k), or 0 if k = 0 width(e₁ . e₂) = max(width(e₁), width(e₂)) width(e₁ | e₂) = width(e₁) + width(e₂) -``` +.... -### 2.6 Permutation Function +==== 2.6 Permutation Function -Each braid word w : Word[n] induces a permutation πw on {1, ..., n}. +Each braid word w : Word[n] induces a permutation πw on \{1, …, n}. -``` +.... π_identity = id π_{sᵢ} = transposition (i, i+1) π_{sᵢ⁻¹} = transposition (i, i+1) π_{w₁ · w₂} = π_{w₂} ∘ π_{w₁} -``` +.... -For boundary application: πw([T₁, ..., Tₙ]) = [T_{πw(1)}, ..., T_{πw(n)}] +For boundary application: πw([T₁, …, Tₙ]) = [T_\{πw(1)}, …, T_\{πw(n)}] ---- +''''' -## 3. Typing Rules +=== 3. Typing Rules -### Environments +==== Environments -``` +.... Γ ::= · -- empty environment | Γ, x : τ -- value binding | Γ, f : (τ₁,...,τₖ) → τ -- function binding Σ ::= · -- empty strand context | Σ, a : (i, T) -- strand name a at position i with type T -``` +.... -Typing judgments: -- `Γ ⊢ e : τ` — expression e has type τ under environment Γ -- `Γ; Σ ⊢ e : τ` — expression e has type τ under Γ and strand context Σ +Typing judgments: - `+Γ ⊢ e : τ+` — expression e has type τ under +environment Γ - `+Γ; Σ ⊢ e : τ+` — expression e has type τ under Γ and +strand context Σ -### 3.1 Literals +==== 3.1 Literals -``` +.... ─────────────────── [T-Num] Γ ⊢ n : Num @@ -206,11 +205,11 @@ Typing judgments: ─────────────────────────── [T-Identity] (D1.14) Γ ⊢ identity : Word[0] -``` +.... -### 3.2 Braid Literals +==== 3.2 Braid Literals -``` +.... g₁, ..., gₖ are generators n = max(index(gⱼ) + 1 for j = 1..k) (n ≥ 1 when k ≥ 1) ──────────────────────────────────────────── [T-Braid] @@ -219,21 +218,21 @@ n = max(index(gⱼ) + 1 for j = 1..k) (n ≥ 1 when k ≥ 1) ──────────────────────────── [T-Braid-Empty] Γ ⊢ braid[] : Word[0] -``` +.... -### 3.3 Variables +==== 3.3 Variables -``` +.... (x : τ) ∈ Γ ────────────── [T-Var] Γ ⊢ x : τ -``` +.... -### 3.4 Composition Operators +==== 3.4 Composition Operators -**Vertical composition** (`.`) — sequential application (D1.8, D1.8.5): +*Vertical composition* (`+.+`) — sequential application (D1.8, D1.8.5): -``` +.... Γ ⊢ e₁ : Word[n] Γ ⊢ e₂ : Word[m] ──────────────────────────────────────────── [T-Compose-Word] Γ ⊢ e₁ . e₂ : Word[max(n, m)] @@ -242,11 +241,11 @@ n = max(index(gⱼ) + 1 for j = 1..k) (n ≥ 1 when k ≥ 1) Γ ⊢ e₁ : Tangle[A, B] Γ ⊢ e₂ : Tangle[B, C] ──────────────────────────────────────────────────── [T-Compose-Tangle] Γ ⊢ e₁ . e₂ : Tangle[A, C] -``` +.... -**Horizontal tensor** (`|`) — parallel juxtaposition: +*Horizontal tensor* (`+|+`) — parallel juxtaposition: -``` +.... Γ ⊢ e₁ : Word[n] Γ ⊢ e₂ : Word[m] ──────────────────────────────────────────── [T-Tensor-Word] Γ ⊢ e₁ | e₂ : Word[n + m] @@ -255,21 +254,21 @@ n = max(index(gⱼ) + 1 for j = 1..k) (n ≥ 1 when k ≥ 1) Γ ⊢ e₁ : Tangle[A₁, B₁] Γ ⊢ e₂ : Tangle[A₂, B₂] ──────────────────────────────────────────────────────── [T-Tensor-Tangle] Γ ⊢ e₁ | e₂ : Tangle[A₁ ++ A₂, B₁ ++ B₂] -``` +.... -**Pipeline** (`>>`) — sugar for vertical composition (D1.20): +*Pipeline* (`+>>+`) — sugar for vertical composition (D1.20): -``` +.... Γ ⊢ e₁ . e₂ : τ ─────────────────── [T-Pipeline] Γ ⊢ e₁ >> e₂ : τ -``` +.... -### 3.5 Arithmetic Operators +==== 3.5 Arithmetic Operators -**Addition** — overloaded by sort (D1.6): +*Addition* — overloaded by sort (D1.6): -``` +.... Γ ⊢ e₁ : Num Γ ⊢ e₂ : Num ──────────────────────────────────── [T-Add-Num] Γ ⊢ e₁ + e₂ : Num @@ -278,23 +277,23 @@ n = max(index(gⱼ) + 1 for j = 1..k) (n ≥ 1 when k ≥ 1) Γ ⊢ e₁ : Tangle[I, I] Γ ⊢ e₂ : Tangle[I, I] ──────────────────────────────────────────────────── [T-Add-Tangle] (D1.7) Γ ⊢ e₁ + e₂ : Tangle[I, I] -``` +.... -If operand types don't match either rule: TYPE ERROR. +If operand types don’t match either rule: TYPE ERROR. -**Other arithmetic** (D1.6): +*Other arithmetic* (D1.6): -``` +.... Γ ⊢ e₁ : Num Γ ⊢ e₂ : Num op ∈ {-, *, /} ───────────────────────────────────────────────────────── [T-Arith] Γ ⊢ e₁ op e₂ : Num -``` +.... -### 3.6 Equality Operators +==== 3.6 Equality Operators -**Structural equality** (`==`) — defined for Word, Num, Str (D1.2): +*Structural equality* (`+==+`) — defined for Word, Num, Str (D1.2): -``` +.... Γ ⊢ e₁ : Word[n] Γ ⊢ e₂ : Word[n] ──────────────────────────────────────────── [T-Eq-Word] Γ ⊢ e₁ == e₂ : Bool @@ -308,23 +307,23 @@ If operand types don't match either rule: TYPE ERROR. Γ ⊢ e₁ : Str Γ ⊢ e₂ : Str ──────────────────────────────────── [T-Eq-Str] Γ ⊢ e₁ == e₂ : Bool -``` +.... -**Isotopy equivalence** (`~`) — defined for Tangles (D1.2): +*Isotopy equivalence* (`+~+`) — defined for Tangles (D1.2): -``` +.... Γ ⊢ e₁ : Tangle[A, B] Γ ⊢ e₂ : Tangle[A, B] ──────────────────────────────────────────────────── [T-Isotopy] Γ ⊢ e₁ ~ e₂ : Bool -``` +.... -`~` also works on Words via implicit coercion (see §3.12). +`+~+` also works on Words via implicit coercion (see §3.12). -### 3.7 Tier 1 Primitives +==== 3.7 Tier 1 Primitives -**Close** (D1.17): +*Close* (D1.17): -``` +.... Γ ⊢ e : Tangle[A, B] |A| = |B| ───────────────────────────────────────── [T-Close-Tangle] Γ ⊢ close(e) : Tangle[I, I] @@ -333,35 +332,36 @@ If operand types don't match either rule: TYPE ERROR. Γ ⊢ e : Word[n] ────────────────────────────── [T-Close-Word] Γ ⊢ close(e) : Tangle[I, I] -``` +.... -No permutation check. Closing a non-identity permutation produces a link. +No permutation check. Closing a non-identity permutation produces a +link. -**Cap and Cup**: +*Cap and Cup*: -``` +.... ──────────────────────────────────── [T-Cap] Γ ⊢ cap : Tangle[[T, T], I] ──────────────────────────────────── [T-Cup] Γ ⊢ cup : Tangle[I, [T, T]] -``` +.... With explicit strand types (in weave context): -``` +.... ──────────────────────────────────────────── [T-Cap-Typed] Γ ⊢ cap(T₁, T₂) : Tangle[[T₁, T₂], I] ──────────────────────────────────────────── [T-Cup-Typed] Γ ⊢ cup(T₁, T₂) : Tangle[I, [T₁, T₂]] -``` +.... -**Mirror** — reverses morphism direction: +*Mirror* — reverses morphism direction: -``` +.... Γ ⊢ e : Tangle[A, B] ──────────────────────────── [T-Mirror-Tangle] Γ ⊢ mirror(e) : Tangle[B, A] @@ -370,34 +370,35 @@ With explicit strand types (in weave context): Γ ⊢ e : Word[n] ────────────────────────── [T-Mirror-Word] Γ ⊢ mirror(e) : Word[n] -``` +.... -**Reverse** — the INVERSE braid. It reverses the word **and** negates every +*Reverse* — the INVERSE braid. It reverses the word *and* negates every exponent: -``` +.... reverse(g₁ g₂ … gₙ) = gₙ⁻¹ … g₂⁻¹ g₁⁻¹ i.e. reverse(w) = w⁻¹ -``` +.... -So `reverse(braid[s1, s2]) = braid[s2^-1, s1^-1]` — NOT `braid[s2, s1]`. +So `+reverse(braid[s1, s2]) = braid[s2^-1, s1^-1]+` — NOT +`+braid[s2, s1]+`. -This is easy to get wrong, and was: both `examples/trefoil.tangle` and -`conformance/valid/v16_close_mirror_reverse.tangle` asserted that `reverse` -merely reverses order, which is false. `writhe` disproves it — writhe is the -exponent sum and is invariant under the braid relations, so `w` and `w⁻¹` -differ in writhe by twice the writhe of `w` and cannot be equal unless the -writhe is 0. Contrast **mirror**, which negates exponents *in place* and -leaves the order alone. +This is easy to get wrong, and was: both `+examples/trefoil.tangle+` and +`+conformance/valid/v16_close_mirror_reverse.tangle+` asserted that +`+reverse+` merely reverses order, which is false. `+writhe+` disproves +it — writhe is the exponent sum and is invariant under the braid +relations, so `+w+` and `+w⁻¹+` differ in writhe by twice the writhe of +`+w+` and cannot be equal unless the writhe is 0. Contrast *mirror*, +which negates exponents _in place_ and leaves the order alone. -``` +.... Γ ⊢ e : Word[n] ──────────────────────── [T-Reverse] Γ ⊢ reverse(e) : Word[n] -``` +.... -**Simplify** — applies Reidemeister moves: +*Simplify* — applies Reidemeister moves: -``` +.... Γ ⊢ e : Word[n] ────────────────────────── [T-Simplify-Word] Γ ⊢ simplify(e) : Word[n] @@ -406,13 +407,13 @@ leaves the order alone. Γ ⊢ e : Tangle[A, B] ──────────────────────────────── [T-Simplify-Tangle] Γ ⊢ simplify(e) : Tangle[A, B] -``` +.... -### 3.8 Twist Operator (D1.18) +==== 3.8 Twist Operator (D1.18) -**Standalone twist** — composes with all-strand twist tangle (θ_A): +*Standalone twist* — composes with all-strand twist tangle (θ_A): -``` +.... Γ ⊢ e : Word[n] ──────────────────── [T-Twist-Word] Γ ⊢ (~e) : Word[n] @@ -421,26 +422,27 @@ leaves the order alone. Γ ⊢ e : Tangle[A, B] ──────────────────────────── [T-Twist-Tangle] Γ ⊢ (~e) : Tangle[A, B] -``` +.... -Desugaring: `(~e) ≡ e . twist_n` where `twist_n` is the n-strand full twist. +Desugaring: `+(~e) ≡ e . twist_n+` where `+twist_n+` is the n-strand +full twist. -**Weave twist** — single strand (see §3.10). +*Weave twist* — single strand (see §3.10). -### 3.9 Pattern Matching (D1.3, D1.4) +==== 3.9 Pattern Matching (D1.3, D1.4) -``` +.... Γ ⊢ e : τ_scrutinee ∀i. Γ ⊢ pᵢ ◁ τ_scrutinee ⊣ Γᵢ -- pattern pᵢ checks against τ, binds Γᵢ ∀i. Γ, Γᵢ ⊢ eᵢ : τ_result -- each arm body has same result type ──────────────────────────────────────── [T-Match] Γ ⊢ match e with p₁ => e₁ | ... | pₖ => eₖ end : τ_result -``` +.... -**Pattern typing** — `Γ ⊢ p ◁ τ ⊣ Γ'` means pattern p checks against type τ, -producing bindings Γ': +*Pattern typing* — `+Γ ⊢ p ◁ τ ⊣ Γ'+` means pattern p checks against +type τ, producing bindings Γ’: -``` +.... ──────────────────────────────── [P-Identity] Γ ⊢ identity ◁ Word[n] ⊣ · @@ -456,15 +458,15 @@ index(g) + 1 ≤ n Γ ⊢ p ◁ Word[n] ⊣ Γ' ──────────────────────────────── [P-Wildcard] Γ ⊢ _ ◁ τ ⊣ · -``` +.... -**Exhaustiveness**: Width-aware warning (D1.4). When scrutinee type is Word[n], -the compiler warns if not all generators s₁ through s_{n-1} are covered. -Warning only; does not affect well-typedness. +*Exhaustiveness*: Width-aware warning (D1.4). When scrutinee type is +Word[n], the compiler warns if not all generators s₁ through s_\{n-1} +are covered. Warning only; does not affect well-typedness. -### 3.10 Weave Blocks (D1.9, D1.10, D1.11, D2.8) +==== 3.10 Weave Blocks (D1.9, D1.10, D1.11, D2.8) -``` +.... Σ = {a₁ : (1, T₁), ..., aₙ : (n, Tₙ)} A = [T₁, ..., Tₙ] B = [U₁, ..., Uₘ] @@ -473,150 +475,170 @@ yield declarations match B ────────────────────────────────────────────────────────────── [T-Weave] Γ ⊢ weave strands a₁:T₁,...,aₙ:Tₙ into body yield strands b₁:U₁,...,bₘ:Uₘ : Tangle[A, B] -``` +.... Weave blocks can reference all definitions in Γ (D2.8). -#### 3.10.1 Strand quantities — the linear discipline +===== 3.10.1 Strand quantities — the linear discipline -The rule above has two side conditions that were, until the quantity semiring -landed, written down and never enforced: the `i ≠ j` on `[T-Cross-Over]` / -`[T-Cross-Under]` below, and "yield declarations match B". Both are instances -of one law, so both are now discharged by one check. +The rule above has two side conditions that were, until the quantity +semiring landed, written down and never enforced: the `+i ≠ j+` on +`+[T-Cross-Over]+` / `+[T-Cross-Under]+` below, and "`yield declarations +match B`". Both are instances of one law, so both are now discharged by +one check. -TANGLE annotates resources with a quantity from the QTT semiring -{0, 1, ω} (Atkey 2018), rather than committing the whole language to a single +TANGLE annotates resources with a quantity from the QTT semiring \{0, 1, +ω} (Atkey 2018), rather than committing the whole language to a single substructural discipline: -| quantity | reading | who carries it | -|---|---|---| -| `0` | erased — present for typing, absent at runtime | the claim in `Epi[κ, ρ, τ]` (see A-TG-11.1) | -| `1` | linear — used **exactly** once | **strands** inside a `weave` | -| `ω` | unrestricted — used freely | braid **words**, and every ordinary binding | +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|quantity |reading |who carries it +|`+0+` |erased — present for typing, absent at runtime |the claim in +`+Epi[κ, ρ, τ]+` (see A-TG-11.1) + +|`+1+` |linear — used *exactly* once |*strands* inside a `+weave+` + +|`+ω+` |unrestricted — used freely |braid *words*, and every ordinary +binding +|=== Why a semiring and not a choice: -- **Words are ω.** `x . x` is σ₁², a perfectly good braid. A blanket linear - discipline would reject a valid program. -- **Strands are 1, and linear rather than affine.** A strand is a physical - thread. A braid on *n* strands is a *permutation* of those *n* strands, so - strand count is a conservation law: a strand may be neither duplicated - (contraction) nor dropped (weakening). Affine permits the second, so affine - is specifically the wrong discipline here — this is the case that decides it. +* *Words are ω.* `+x . x+` is σ₁², a perfectly good braid. A blanket +linear discipline would reject a valid program. +* *Strands are 1, and linear rather than affine.* A strand is a physical +thread. A braid on _n_ strands is a _permutation_ of those _n_ strands, +so strand count is a conservation law: a strand may be neither +duplicated (contraction) nor dropped (weakening). Affine permits the +second, so affine is specifically the wrong discipline here — this is +the case that decides it. -Independent uses combine with semiring addition, so two uses of one strand give -`1 + 1 = ω`, and `ω` is not permitted where `1` was declared. +Independent uses combine with semiring addition, so two uses of one +strand give `+1 + 1 = ω+`, and `+ω+` is not permitted where `+1+` was +declared. -``` +.... Σ = {a₁ : (1, T₁), ..., aₙ : (n, Tₙ)} uses(body, aᵢ) = 1 for every i (no contraction, no unused strand) ⟦b₁, ..., bₘ⟧ is a permutation of ⟦a₁, ..., aₙ⟧ (m = n; conservation) ────────────────────────────────────────────────────────── [T-Weave-Linear] Σ ⊢ weave strands a₁,...,aₙ into body yield strands b₁,...,bₘ linear -``` +.... -`uses` is defined by structural recursion over the body, mapping into the -semiring: a strand occurrence contributes `1`, the two operands of a crossing -and the two sides of any binary form combine with `+`, and non-strand leaves -contribute `0`. +`+uses+` is defined by structural recursion over the body, mapping into +the semiring: a strand occurrence contributes `+1+`, the two operands of +a crossing and the two sides of any binary form combine with `+++`, and +non-strand leaves contribute `+0+`. Four programs this rejects, each previously accepted in silence: -| program | violated law | -|---|---| -| `weave strands a, b into (a > a) yield strands a, b` | contraction (also the spec's `i ≠ j`) | -| `weave strands a, b into (a > b) yield strands a, b, a` | contraction in the yield | -| `weave strands a, b into (a > b) yield strands a` | weakening — a strand vanished | -| `weave strands a, b into (a > b) yield strands a, c` | `c` is not in the input boundary | +[width="100%",cols="50%,50%",options="header",] +|=== +|program |violated law +|`+weave strands a, b into (a > a) yield strands a, b+` |contraction +(also the spec’s `+i ≠ j+`) + +|`+weave strands a, b into (a > b) yield strands a, b, a+` |contraction +in the yield + +|`+weave strands a, b into (a > b) yield strands a+` |weakening — a +strand vanished + +|`+weave strands a, b into (a > b) yield strands a, c+` |`+c+` is not in +the input boundary +|=== -**Scope.** This is the semiring applied *to strands*, which is where the -discipline bites and where the soundness gap was. TANGLE's core judgement is -still `Γ ⊢ e : τ` without quantities on ordinary bindings; a full QTT judgement -`Γ ⊢ e :^q τ` would change the judgement shape and require re-proving the -metatheory, and is tracked separately. +*Scope.* This is the semiring applied _to strands_, which is where the +discipline bites and where the soundness gap was. TANGLE’s core +judgement is still `+Γ ⊢ e : τ+` without quantities on ordinary +bindings; a full QTT judgement `+Γ ⊢ e :^q τ+` would change the +judgement shape and require re-proving the metatheory, and is tracked +separately. -**Crossing in weave context**: +*Crossing in weave context*: -``` +.... Σ(a) = (i, Tₐ) Σ(b) = (j, Tᵦ) i ≠ j A = current input boundary B = swap(A, i, j) ─────────────────────────────────────────────────── [T-Cross-Over] Γ; Σ ⊢ (a > b) : Tangle[A, B] -``` +.... -``` +.... Σ(a) = (i, Tₐ) Σ(b) = (j, Tᵦ) i ≠ j A = current input boundary B = swap(A, i, j) ─────────────────────────────────────────────────── [T-Cross-Under] Γ; Σ ⊢ (a < b) : Tangle[A, B] -``` +.... -Where `swap(A, i, j)` exchanges elements at positions i and j in A. +Where `+swap(A, i, j)+` exchanges elements at positions i and j in A. -**Twist in weave context** (D1.18): +*Twist in weave context* (D1.18): -``` +.... Σ(a) = (i, T) ─────────────────────────────────── [T-Twist-Strand] Γ; Σ ⊢ (~a) : Tangle[[T], [T]] -``` +.... -**Self-crossing** (D1.19): +*Self-crossing* (D1.19): -``` +.... Σ(a) = (i, T) ───────────────────────────────────── [T-Self-Cross] Γ; Σ ⊢ (a > a) : Tangle[[T], [T]] -``` +.... -Desugars to `(~a)`. Compiler emits warning. +Desugars to `+(~a)+`. Compiler emits warning. -### 3.11 Let Bindings (D1.4.5) +==== 3.11 Let Bindings (D1.4.5) -``` +.... Γ ⊢ e₁ : τ₁ Γ, x : τ₁ ⊢ e₂ : τ₂ ──────────────────────────────────────────── [T-Let] Γ ⊢ let x = e₁ in e₂ : τ₂ -``` +.... Shadowing: if x already exists in Γ, the inner binding shadows it. Compiler emits warning (D1.15.3). -### 3.12 Implicit Coercion: Word → Tangle (D1.1) +==== 3.12 Implicit Coercion: Word → Tangle (D1.1) -``` +.... Γ ⊢ e : Word[n] context expects Tangle[A, B] |A| = n' n' ≥ n B = πₑ(A) (permutation applied to A, identity on widened strands) ──────────────────────────────────────────── [T-Realize] Γ ⊢ e : Tangle[A, B] -``` +.... -Coercion inserts `realize_A(e)`: -- Embeds Word[n] into an n'-strand tangle (n' ≥ n) -- Extra strands (beyond n) act as identity -- Result boundary B = πₑ(A) where πₑ is the permutation of e, extended with identity on extra strands +Coercion inserts `+realize_A(e)+`: - Embeds Word[n] into an n’-strand +tangle (n’ ≥ n) - Extra strands (beyond n) act as identity - Result +boundary B = πₑ(A) where πₑ is the permutation of e, extended with +identity on extra strands With homogeneous default boundaries (all strands have type Strand): -``` +.... Γ ⊢ e : Word[n] A = [Strand, ..., Strand] (n copies) ──────────────────────────────────────── [T-Realize-Default] Γ ⊢ e : Tangle[A, A] -``` +.... -Note: With homogeneous boundaries, πₑ(A) = A always, since all strand types are identical. +Note: With homogeneous boundaries, πₑ(A) = A always, since all strand +types are identical. -### 3.13 Function Definitions and Application +==== 3.13 Function Definitions and Application -**Definition** (collected in pass 1 per D1.13): +*Definition* (collected in pass 1 per D1.13): -``` +.... Γ, f : (τ₁,...,τₖ) → τ, x₁ : τ₁, ..., xₖ : τₖ ⊢ body : τ ──────────────────────────────────────────────────────────────── [T-Def-Fun] Γ ⊢ def f(x₁, ..., xₖ) = body ⊣ Γ, f : (τ₁,...,τₖ) → τ @@ -625,79 +647,83 @@ Note: With homogeneous boundaries, πₑ(A) = A always, since all strand types a Γ ⊢ e : τ ──────────────────────────── [T-Def-Val] Γ ⊢ def x = e ⊣ Γ, x : τ -``` +.... -Note: f appears in its own environment (recursive definitions allowed, D1.3). +Note: f appears in its own environment (recursive definitions allowed, +D1.3). -**Application**: +*Application*: -``` +.... Γ(f) = (τ₁, ..., τₖ) → τ Γ ⊢ eᵢ : τᵢ for each i ──────────────────────────────────────────────────────────── [T-App] Γ ⊢ f(e₁, ..., eₖ) : τ -``` +.... -### 3.14 Width Inference (D1.21) +==== 3.14 Width Inference (D1.21) Types for function arguments are inferred from usage when not annotated. -The inference algorithm tracks the maximum generator index through expressions: +The inference algorithm tracks the maximum generator index through +expressions: -``` +.... infer_width(identity) = 0 infer_width(braid[g₁,...,gₖ]) = max(index(gⱼ) + 1) infer_width(e₁ . e₂) = max(infer_width(e₁), infer_width(e₂)) infer_width(e₁ | e₂) = infer_width(e₁) + infer_width(e₂) infer_width(f(e₁,...,eₖ)) = width from f's return type infer_width(x) = width from Γ(x) if Word[n], else unknown -``` +.... If width cannot be inferred, compiler requests annotation. -### 3.15 Statements +==== 3.15 Statements -**Assert** (D1.15, D1.15.1): +*Assert* (D1.15, D1.15.1): -The grammar has `assertion = "assert", expr`. The expression must evaluate -to Bool. Common patterns: `assert e₁ ~ e₂`, `assert e₁ == e₂`, `assert f(x)`. +The grammar has `+assertion = "assert", expr+`. The expression must +evaluate to Bool. Common patterns: `+assert e₁ ~ e₂+`, +`+assert e₁ == e₂+`, `+assert f(x)+`. -``` +.... Γ ⊢ e : Bool ────────────────────── [T-Assert] Γ ⊢ assert e : ok -``` +.... -This subsumes isotopy and equality assertions because `~` and `==` return Bool -(see §3.6). For example, `assert e₁ ~ e₂` typechecks because T-Isotopy gives -`e₁ ~ e₂ : Bool`, and T-Assert accepts any `Bool`. +This subsumes isotopy and equality assertions because `+~+` and `+==+` +return Bool (see §3.6). For example, `+assert e₁ ~ e₂+` typechecks +because T-Isotopy gives `+e₁ ~ e₂ : Bool+`, and T-Assert accepts any +`+Bool+`. -**Compute** (D1.12): +*Compute* (D1.12): -``` +.... inv ∈ {jones, alexander, homfly, kauffman, writhe, linking} Γ ⊢ e : Tangle[I, I] (or coercible to Tangle[I, I]) ──────────────────────────────────────────────────────────── [T-Compute] Γ ⊢ compute inv(e) : ok -``` +.... -**Invariant Result Types**: +*Invariant Result Types*: Each built-in invariant produces a specific type: -``` +.... result_type(jones) = Num -- Laurent polynomial in t^(1/2), evaluated numerically result_type(alexander) = Num -- Laurent polynomial in t, evaluated numerically result_type(homfly) = Num -- two-variable polynomial P(a,z), evaluated numerically result_type(kauffman) = Num -- Kauffman bracket polynomial, evaluated numerically result_type(writhe) = Num -- integer (sum of crossing signs) result_type(linking) = Num -- integer or half-integer (linking number) -``` +.... -MVP note: Polynomials are evaluated at fixed values, returning Num. Future versions -may return a Polynomial type for symbolic manipulation. +MVP note: Polynomials are evaluated at fixed values, returning Num. +Future versions may return a Polynomial type for symbolic manipulation. -### 3.16 Echo Types and Product Types +==== 3.16 Echo Types and Product Types -``` +.... Γ ⊢ e : Word[n] ───────────────────────────────────────────────── [T-Echo-Close] Γ ⊢ echoClose(e) : Echo (Word[n]) (Word[0]) @@ -744,72 +770,77 @@ may return a Polynomial type for symbolic manipulation. Γ ⊢ e₁ : Str Γ ⊢ e₂ : Str ────────────────────────────────────────────────────── [T-Echo-Eq-Str] Γ ⊢ echoEq(e₁, e₂) : Echo (Str × Str) Bool -``` +.... -(Note: `T-Echo-Val` is an internal rule for the `echoVal(r, v)` intermediate form produced during evaluation; it does not appear in surface typing.) +(Note: `+T-Echo-Val+` is an internal rule for the `+echoVal(r, v)+` +intermediate form produced during evaluation; it does not appear in +surface typing.) -### 3.17 Program Typing (D1.13) +==== 3.17 Program Typing (D1.13) -A program is well-typed if all statements typecheck under the accumulated Γ. +A program is well-typed if all statements typecheck under the +accumulated Γ. -**Pass 1**: Collect all `def` names and their types into Γ. +*Pass 1*: Collect all `+def+` names and their types into Γ. -``` +.... Γ₀ = · For each def in prog (in source order): Γᵢ₊₁ = Γᵢ, name : inferred_type Γ_complete = Γₙ -``` +.... -**Pass 2**: Typecheck all statements against Γ_complete. +*Pass 2*: Typecheck all statements against Γ_complete. -``` +.... ∀ stmt ∈ prog: Γ_complete ⊢ stmt : ok ──────────────────────────────────────── [T-Program] ⊢ prog : ok -``` +.... -Forward references are allowed because Γ_complete contains all definitions. +Forward references are allowed because Γ_complete contains all +definitions. ---- +''''' -## 4. Operational Semantics +=== 4. Operational Semantics Big-step natural semantics. Call-by-value evaluation (D1.13.5). -### 4.1 Values +==== 4.1 Values -``` +.... v ::= num(n) -- numeric value | str(s) -- string value | bool(b) -- boolean value (b ∈ {true, false}) | word(g₁, ..., gₖ) -- braid word value (sequence of generators) | tangle(t) -- tangle value (opaque internal representation) | halt(msg, span) -- error value (program halts) -``` +.... -`word()` (empty sequence) represents identity. +`+word()+` (empty sequence) represents identity. -### 4.2 Runtime Environments +==== 4.2 Runtime Environments -``` +.... ρ ::= · -- empty environment | ρ, x ↦ v -- value binding | ρ, f ↦ closure(x₁,...,xₖ, body) -- function binding -``` +.... -### 4.3 Judgment Form +==== 4.3 Judgment Form -``` +.... ρ ⊢ e ⇓ v -- under environment ρ, expression e evaluates to value v ρ ⊢ e ⇓ halt(m) -- under environment ρ, expression e halts with error message m -``` +.... -Non-termination: if no derivation exists, the evaluation diverges (D1.13.5). +Non-termination: if no derivation exists, the evaluation diverges +(D1.13.5). -### 4.4 Evaluation Rules — Literals +==== 4.4 Evaluation Rules — Literals -``` +.... ─────────────────── [E-Num] ρ ⊢ n ⇓ num(n) @@ -828,60 +859,61 @@ Non-termination: if no derivation exists, the evaluation diverges (D1.13.5). ─────────────────────────────────────── [E-Braid] ρ ⊢ braid[g₁,...,gₖ] ⇓ word(g₁,...,gₖ) -``` +.... -### 4.5 Evaluation Rules — Variables +==== 4.5 Evaluation Rules — Variables -``` +.... ρ(x) = v ────────────── [E-Var] ρ ⊢ x ⇓ v -``` +.... -### 4.6 Evaluation Rules — Composition +==== 4.6 Evaluation Rules — Composition -**Word composition** — concatenation with implicit widening (D1.8.5): +*Word composition* — concatenation with implicit widening (D1.8.5): -``` +.... ρ ⊢ e₁ ⇓ word(g₁, ..., gⱼ) ρ ⊢ e₂ ⇓ word(h₁, ..., hₖ) ──────────────────────────────────────────────────────────────── [E-Compose-Word] ρ ⊢ e₁ . e₂ ⇓ word(g₁, ..., gⱼ, h₁, ..., hₖ) -``` +.... -Widening is implicit: generators from both words coexist in the wider braid group. +Widening is implicit: generators from both words coexist in the wider +braid group. -**Tangle composition** — sequential application: +*Tangle composition* — sequential application: -``` +.... ρ ⊢ e₁ ⇓ tangle(t₁) ρ ⊢ e₂ ⇓ tangle(t₂) output boundary of t₁ = input boundary of t₂ ──────────────────────────────────────────────── [E-Compose-Tangle] ρ ⊢ e₁ . e₂ ⇓ tangle(compose(t₁, t₂)) -``` +.... -**Tensor** — parallel juxtaposition: +*Tensor* — parallel juxtaposition: -``` +.... ρ ⊢ e₁ ⇓ word(g₁, ..., gⱼ) ρ ⊢ e₂ ⇓ word(h₁, ..., hₖ) n₁ = width(word(g₁,...,gⱼ)) h'ᵢ = shift(hᵢ, n₁) for each i -- shift indices by n₁ ──────────────────────────────────────────────────────────────── [E-Tensor-Word] ρ ⊢ e₁ | e₂ ⇓ word(g₁, ..., gⱼ, h'₁, ..., h'ₖ) -``` +.... -Where `shift(sᵢ, k) = s_{i+k}` and `shift(sᵢ⁻¹, k) = s_{i+k}⁻¹`. +Where `+shift(sᵢ, k) = s_{i+k}+` and `+shift(sᵢ⁻¹, k) = s_{i+k}⁻¹+`. -**Pipeline** — desugars to composition: +*Pipeline* — desugars to composition: -``` +.... ρ ⊢ e₁ . e₂ ⇓ v ─────────────────── [E-Pipeline] ρ ⊢ e₁ >> e₂ ⇓ v -``` +.... -### 4.7 Evaluation Rules — Arithmetic +==== 4.7 Evaluation Rules — Arithmetic -``` +.... ρ ⊢ e₁ ⇓ num(n₁) ρ ⊢ e₂ ⇓ num(n₂) ─────────────────────────────────────────── [E-Add-Num] ρ ⊢ e₁ + e₂ ⇓ num(n₁ + n₂) @@ -896,27 +928,28 @@ t₁, t₂ both closed (boundary = I) ρ ⊢ e₁ ⇓ num(n₁) ρ ⊢ e₂ ⇓ num(n₂) op ∈ {-, *, /} ────────────────────────────────────────────────────────────────── [E-Arith] ρ ⊢ e₁ op e₂ ⇓ num(n₁ op n₂) -``` +.... Division by zero: -``` +.... ρ ⊢ e₁ ⇓ num(n₁) ρ ⊢ e₂ ⇓ num(0) ──────────────────────────────────────────── [E-Div-Zero] ρ ⊢ e₁ / e₂ ⇓ halt("division by zero") -``` +.... -### 4.8 Evaluation Rules — Equality +==== 4.8 Evaluation Rules — Equality -``` +.... ρ ⊢ e₁ ⇓ word(w₁) ρ ⊢ e₂ ⇓ word(w₂) ──────────────────────────────────────────── [E-Eq-Word] ρ ⊢ e₁ == e₂ ⇓ bool(w₁ = w₂) -``` +.... -Where `w₁ = w₂` iff the generator sequences are identical (structural equality). +Where `+w₁ = w₂+` iff the generator sequences are identical (structural +equality). -``` +.... ρ ⊢ e₁ ⇓ num(n₁) ρ ⊢ e₂ ⇓ num(n₂) ──────────────────────────────────────────── [E-Eq-Num] ρ ⊢ e₁ == e₂ ⇓ bool(n₁ = n₂) @@ -925,25 +958,25 @@ Where `w₁ = w₂` iff the generator sequences are identical (structural equali ρ ⊢ e₁ ⇓ str(s₁) ρ ⊢ e₂ ⇓ str(s₂) ──────────────────────────────────────────── [E-Eq-Str] ρ ⊢ e₁ == e₂ ⇓ bool(s₁ = s₂) -``` +.... -**Isotopy** (D1.2): +*Isotopy* (D1.2): -``` +.... ρ ⊢ e₁ ⇓ v₁ ρ ⊢ e₂ ⇓ v₂ ──────────────────────────────────── [E-Isotopy] ρ ⊢ e₁ ~ e₂ ⇓ bool(isotopy(v₁, v₂)) -``` +.... -Where `isotopy(v₁, v₂)` checks equality in the free ribbon category FR(T). -This is a semantic function provided by the backend (D1.12). -MVP: may only support syntactic equality after simplification. +Where `+isotopy(v₁, v₂)+` checks equality in the free ribbon category +FR(T). This is a semantic function provided by the backend (D1.12). MVP: +may only support syntactic equality after simplification. -### 4.9 Evaluation Rules — Primitives +==== 4.9 Evaluation Rules — Primitives -**Close**: +*Close*: -``` +.... ρ ⊢ e ⇓ word(g₁, ..., gₖ) ────────────────────────────────────────── [E-Close-Word] ρ ⊢ close(e) ⇓ tangle(close(word(g₁,...,gₖ))) @@ -952,60 +985,61 @@ MVP: may only support syntactic equality after simplification. ρ ⊢ e ⇓ tangle(t) ──────────────────────────── [E-Close-Tangle] ρ ⊢ close(e) ⇓ tangle(close(t)) -``` +.... -**Mirror**: +*Mirror*: -``` +.... ρ ⊢ e ⇓ word(g₁, ..., gₖ) mirror_gen(sᵢ) = sᵢ⁻¹ mirror_gen(sᵢ⁻¹) = sᵢ ───────────────────────────────────────────────────── [E-Mirror-Word] ρ ⊢ mirror(e) ⇓ word(mirror_gen(g₁), ..., mirror_gen(gₖ)) -``` +.... -**Reverse**: +*Reverse*: -``` +.... ρ ⊢ e ⇓ word(g₁, ..., gₖ) inv(sᵢ) = sᵢ⁻¹ inv(sᵢ⁻¹) = sᵢ ──────────────────────────────────────────────── [E-Reverse] ρ ⊢ reverse(e) ⇓ word(inv(gₖ), ..., inv(g₁)) -``` +.... -**Simplify**: +*Simplify*: -``` +.... ρ ⊢ e ⇓ word(w) w' = reidemeister_reduce(w) ───────────────────────────── [E-Simplify] ρ ⊢ simplify(e) ⇓ word(w') -``` +.... -Where `reidemeister_reduce` applies Reidemeister moves to normal form: -- R1: `sᵢ . sᵢ⁻¹ → ε` and `sᵢ⁻¹ . sᵢ → ε` (cancellation) -- R2: `sᵢ . sⱼ → sⱼ . sᵢ` when `|i - j| ≥ 2` (far commutativity) -- R3: `sᵢ . s_{i+1} . sᵢ → s_{i+1} . sᵢ . s_{i+1}` (braid relation) +Where `+reidemeister_reduce+` applies Reidemeister moves to normal form: +- R1: `+sᵢ . sᵢ⁻¹ → ε+` and `+sᵢ⁻¹ . sᵢ → ε+` (cancellation) - R2: +`+sᵢ . sⱼ → sⱼ . sᵢ+` when `+|i - j| ≥ 2+` (far commutativity) - R3: +`+sᵢ . s_{i+1} . sᵢ → s_{i+1} . sᵢ . s_{i+1}+` (braid relation) -Implementation may use any terminating strategy that produces a canonical representative. +Implementation may use any terminating strategy that produces a +canonical representative. -**Twist** (standalone, D1.18): +*Twist* (standalone, D1.18): -``` +.... ρ ⊢ e ⇓ word(w) n = width(word(w)) tw = twist_generators(n) -- full twist on n strands ──────────────────────────────── [E-Twist-Standalone] ρ ⊢ (~e) ⇓ word(w · tw) -``` +.... -Where `twist_generators(n)` produces the canonical full twist braid word -Δ² = (s₁ s₂ ... s_{n-1})ⁿ (the Garside element squared). +Where `+twist_generators(n)+` produces the canonical full twist braid +word Δ² = (s₁ s₂ … s_\{n-1})ⁿ (the Garside element squared). -### 4.10 Evaluation Rules — Echo Types and Product Types +==== 4.10 Evaluation Rules — Echo Types and Product Types -**Echo-close reduction:** +*Echo-close reduction:* -``` +.... e → e' ───────────────────────────────────── [E-Echo-Close-Step] echoClose(e) → echoClose(e') @@ -1015,11 +1049,11 @@ Where `twist_generators(n)` produces the canonical full twist braid word ───────────────────────────────────────────────────────── [E-Echo-Close-Id] echoClose(identity) → echoVal(identity, identity) -``` +.... -**Lower / residue projection:** +*Lower / residue projection:* -``` +.... e → e' ────────────────────────── [E-Lower-Step] lower(e) → lower(e') @@ -1035,11 +1069,11 @@ Where `twist_generators(n)` produces the canonical full twist braid word isValue(r) isValue(v) ───────────────────────────── [E-Residue-Val] residue(echoVal(r, v)) → r -``` +.... -**Product introduction and projection:** +*Product introduction and projection:* -``` +.... e₁ → e₁' ───────────────────────────────── [E-Pair-Left] pair(e₁, e₂) → pair(e₁', e₂) @@ -1063,11 +1097,11 @@ residue(echoVal(r, v)) → r isValue(v₁) isValue(v₂) ────────────────────────────── [E-Snd-Pair] snd(pair(v₁, v₂)) → v₂ -``` +.... -**Echo-preserving addition:** +*Echo-preserving addition:* -``` +.... e₁ → e₁' ────────────────────────────────────────────── [E-EchoAdd-Left] echoAdd(e₁, e₂) → echoAdd(e₁', e₂) @@ -1078,11 +1112,12 @@ residue(echoVal(r, v)) → r ────────────────────────────────────────────────────────────────────── [E-EchoAdd-Nums] echoAdd(n₁, n₂) → echoVal(pair(n₁, n₂), n₁ + n₂) -``` +.... -**Echo-preserving equality (shown for Num; analogous for Str, Word[n], identity):** +*Echo-preserving equality (shown for Num; analogous for Str, Word[n], +identity):* -``` +.... e₁ → e₁' ────────────────────────────────────────────── [E-EchoEq-Left] echoEq(e₁, e₂) → echoEq(e₁', e₂) @@ -1099,68 +1134,70 @@ residue(echoVal(r, v)) → r ────────────────────────────────────────────────────────────────────────────────────────────── [E-EchoEq-Braids] echoEq(braid[gs₁], braid[gs₂]) → echoVal(pair(braid[gs₁], braid[gs₂]), gs₁ == gs₂) -``` +.... -(Additional rules `E-EchoEq-IdId`, `E-EchoEq-IdBraid`, `E-EchoEq-BraidId` handle identity/braid combinations analogously.) +(Additional rules `+E-EchoEq-IdId+`, `+E-EchoEq-IdBraid+`, +`+E-EchoEq-BraidId+` handle identity/braid combinations analogously.) -### 4.11 Evaluation Rules — Pattern Matching +==== 4.11 Evaluation Rules — Pattern Matching -**Successful match** (D1.4): +*Successful match* (D1.4): -``` +.... ρ ⊢ e ⇓ v match(v, p₁) = fail ... match(v, p_{i-1}) = fail match(v, pᵢ) = θ -- first matching arm ρ ⊕ θ ⊢ eᵢ ⇓ v' ─────────────────────────────────────────────────────────────── [E-Match-Hit] ρ ⊢ match e with p₁ => e₁ | ... | pₖ => eₖ end ⇓ v' -``` +.... -**Match failure** (D1.15): +*Match failure* (D1.15): -``` +.... ρ ⊢ e ⇓ v ∀i. match(v, pᵢ) = fail ──────────────────────────────────────────────────────────── [E-Match-Fail] ρ ⊢ match e with p₁ => e₁ | ... | pₖ => eₖ end ⇓ halt("MatchFailure at ") -``` +.... -**Pattern matching function** `match(v, p) = θ | fail`: +*Pattern matching function* `+match(v, p) = θ | fail+`: -``` +.... match(word(), identity) = {} -- [M-Identity] match(word(g, g₂,...,gₖ), g . p) = match(word(g₂,...,gₖ), p) -- [M-Cons-Match] match(word(g, g₂,...,gₖ), g' . p) = fail when g ≠ g' -- [M-Cons-Fail] match(word(), g . p) = fail -- [M-Cons-Empty] match(v, x) = {x ↦ v} -- [M-Var] match(v, _) = {} -- [M-Wildcard] -``` +.... -### 4.12 Evaluation Rules — Let Bindings +==== 4.12 Evaluation Rules — Let Bindings -``` +.... ρ ⊢ e₁ ⇓ v₁ ρ, x ↦ v₁ ⊢ e₂ ⇓ v₂ ──────────────────────────────────────────── [E-Let] ρ ⊢ let x = e₁ in e₂ ⇓ v₂ -``` +.... -### 4.13 Evaluation Rules — Function Application +==== 4.13 Evaluation Rules — Function Application -``` +.... ρ(f) = closure(x₁, ..., xₖ, body) ρ ⊢ eᵢ ⇓ vᵢ for each i = 1..k -- call-by-value ρ, x₁ ↦ v₁, ..., xₖ ↦ vₖ ⊢ body ⇓ v ──────────────────────────────────────────── [E-App] ρ ⊢ f(e₁, ..., eₖ) ⇓ v -``` +.... -Note: f is in ρ (recursive calls resolve to the same closure), enabling recursion (D1.3). +Note: f is in ρ (recursive calls resolve to the same closure), enabling +recursion (D1.3). -### 4.14 Evaluation Rules — Assertions +==== 4.14 Evaluation Rules — Assertions Assertions evaluate the expression and check for truth: -``` +.... ρ ⊢ e ⇓ bool(true) ────────────────────── [E-Assert-Pass] ρ ⊢ assert e ⇓ ok @@ -1169,28 +1206,29 @@ Assertions evaluate the expression and check for truth: ρ ⊢ e ⇓ bool(false) ──────────────────────────────────────────────── [E-Assert-Fail] ρ ⊢ assert e ⇓ halt("assertion failed: at ") -``` +.... -For `assert e₁ ~ e₂`, evaluation first reduces `e₁ ~ e₂` via [E-Isotopy] -to `bool(b)`, then [E-Assert-Pass] or [E-Assert-Fail] applies. -Similarly for `assert e₁ == e₂` via [E-Eq-*]. +For `+assert e₁ ~ e₂+`, evaluation first reduces `+e₁ ~ e₂+` via +[E-Isotopy] to `+bool(b)+`, then [E-Assert-Pass] or [E-Assert-Fail] +applies. Similarly for `+assert e₁ == e₂+` via [E-Eq-*]. -### 4.15 Evaluation Rules — Invariant Computation +==== 4.15 Evaluation Rules — Invariant Computation -``` +.... ρ ⊢ e ⇓ v v is closed tangle or word result = compute_invariant(inv, v) ──────────────────────────────────────── [E-Compute] ρ ⊢ compute inv(e) ⇓ result -``` +.... -`compute_invariant` dispatches to the backend/plugin for the named invariant (D1.12). +`+compute_invariant+` dispatches to the backend/plugin for the named +invariant (D1.12). -### 4.16 Error Propagation +==== 4.16 Error Propagation Errors propagate strictly (halt short-circuits evaluation): -``` +.... ρ ⊢ e₁ ⇓ halt(m) ──────────────────────── [E-Halt-Left] ρ ⊢ e₁ op e₂ ⇓ halt(m) @@ -1199,13 +1237,13 @@ Errors propagate strictly (halt short-circuits evaluation): ρ ⊢ e₁ ⇓ v₁ ρ ⊢ e₂ ⇓ halt(m) ──────────────────────────────────────── [E-Halt-Right] ρ ⊢ e₁ op e₂ ⇓ halt(m) -``` +.... This applies uniformly to all binary operators and function arguments. -### 4.17 Program Evaluation (D1.13) +==== 4.17 Program Evaluation (D1.13) -``` +.... ρ₀ = · -- Pass 1: Collect definitions @@ -1220,67 +1258,67 @@ For each def f(x₁,...,xₖ) = body in prog: For each non-def stmt in prog (in source order): ρ ⊢ stmt ⇓ result if result = halt(m): terminate program with error message m -``` +.... ---- +''''' -## 5. Weave Block Semantics (Detailed) +=== 5. Weave Block Semantics (Detailed) Weave blocks have richer structure than simple expressions. This section specifies their evaluation in detail. -### 5.1 Weave Body Expressions +==== 5.1 Weave Body Expressions -The body of a weave block is an expression in strand context. Strand names -resolve in Σ. Other names resolve in ρ (D2.8). +The body of a weave block is an expression in strand context. Strand +names resolve in Σ. Other names resolve in ρ (D2.8). -**Crossing evaluation**: +*Crossing evaluation*: -``` +.... Σ(a) = (i, Tₐ) Σ(b) = (j, Tᵦ) ──────────────────────────────────────────── [E-Cross] ρ; Σ ⊢ (a > b) ⇓ tangle(crossing(i, j, over)) ρ; Σ ⊢ (a < b) ⇓ tangle(crossing(i, j, under)) -``` +.... -**Composition in weave** — body expressions compose sequentially: +*Composition in weave* — body expressions compose sequentially: -If the body contains multiple operations (e.g., `(a > b) . (b > c)`), +If the body contains multiple operations (e.g., `+(a > b) . (b > c)+`), they compose via [E-Compose-Tangle]. -### 5.2 Yield Validation (D1.11) +==== 5.2 Yield Validation (D1.11) -At runtime, the computed tangle's output boundary must exactly match the +At runtime, the computed tangle’s output boundary must exactly match the yield declaration. Error messages are name-based (D1.15.2): -``` +.... computed output boundary ≠ declared yield boundary ─────────────────────────────────────────────────── [E-Yield-Mismatch] result = halt("yield boundary mismatch at Expected: strands Got: strands (strand '' is in position , expected position )") -``` +.... ---- +''''' -# Part 2: TANGLE-JTV Extensions +== Part 2: TANGLE-JTV Extensions -## 6. Extended Syntax +=== 6. Extended Syntax -### 6.1 Additional Expressions +==== 6.1 Additional Expressions -``` +.... e ::= ... -- all TANGLE expressions from §1 | add{ he } -- Harvard data block | harvard{ hp } -- Harvard control block (statement-level) -``` +.... -### 6.2 Harvard Data Expressions (add{...}) +==== 6.2 Harvard Data Expressions (add\{…}) -``` +.... he ::= n | "s" | true | false -- literals | x -- variable (resolves in Π) | he₁ op he₂ -- arithmetic (op ∈ {+,-,*,/}) @@ -1289,13 +1327,14 @@ he ::= n | "s" | true | false -- literals | !he -- boolean negation | f(he₁, ..., heₖ) -- function call (f must be in Π) | if he₁ then he₂ else he₃ -- conditional (total: both branches required) -``` +.... -Note: NO side effects, NO loops, NO assignments. Guaranteed terminating (D2.1). +Note: NO side effects, NO loops, NO assignments. Guaranteed terminating +(D2.1). -### 6.3 Harvard Control Programs (harvard{...}) +==== 6.3 Harvard Control Programs (harvard\{…}) -``` +.... hp ::= hs₁ ; ... ; hsₙ -- statement sequence hs ::= let x = he -- variable binding @@ -1312,15 +1351,15 @@ hs ::= let x = he -- variable binding purity ::= @pure -- total and side-effect free | @total -- always terminates, may have effects | ε -- no purity guarantee -``` +.... ---- +''''' -## 7. Extended Types +=== 7. Extended Types -### 7.1 Harvard Types +==== 7.1 Harvard Types -``` +.... hτ ::= Int | Float | Rational -- numeric types | Bool -- boolean | String -- strings @@ -1330,13 +1369,14 @@ hτ ::= Int | Float | Rational -- numeric types | List -- lists (future) | Tuple -- tuples (future) | (hτ₁,...,hτₖ) → hτ -- function types -``` +.... -### 7.2 Embed and Unembed (D2.4, D2.10) +==== 7.2 Embed and Unembed (D2.4, D2.10) -**Embed**: Harvard type → TANGLE type (for `add{...}` results entering TANGLE): +*Embed*: Harvard type → TANGLE type (for `+add{...}+` results entering +TANGLE): -``` +.... Embed(Int) = Num Embed(Float) = Num Embed(Rational) = Num @@ -1350,41 +1390,42 @@ Embed(Complex) = ERROR("Complex not yet supported") Embed(List) = ERROR("Lists not embeddable") Embed(Tuple) = ERROR("Tuples not embeddable") Embed(T → U) = ERROR("Functions not embeddable") -``` +.... -**Unembed**: TANGLE type → Harvard type (for TANGLE values entering Harvard): +*Unembed*: TANGLE type → Harvard type (for TANGLE values entering +Harvard): -``` +.... Unembed(Num) = Int or Float (context-dependent) Unembed(Str) = String Unembed(Bool) = Bool Unembed(Word[n]) = ERROR("braids cannot cross into Harvard") Unembed(Tangle[A,B]) = ERROR("tangles cannot cross into Harvard") -``` +.... ---- +''''' -## 8. Extended Environments (D2.2) +=== 8. Extended Environments (D2.2) -``` +.... Γ : TangleEnv -- TANGLE definitions (def, weave) Δ : HarvardEnv -- ALL Harvard definitions (functions, modules, variables) Π ⊆ Δ : PureEnv -- @pure/@total Harvard functions only -``` +.... -### 8.1 Visibility Rules +==== 8.1 Visibility Rules -``` +.... Inside TANGLE expression: names resolve in Γ only Inside add{...}: names resolve in Π only Inside harvard{...}: names resolve in Δ -``` +.... -### 8.2 Π Construction (D2.3) +==== 8.2 Π Construction (D2.3) -Π grows sequentially as harvard{...} blocks are processed: +Π grows sequentially as harvard\{…} blocks are processed: -``` +.... Π₀ = · For each harvard{ ... fn f(args) @pure { body } ... } in source order: @@ -1392,42 +1433,43 @@ For each harvard{ ... fn f(args) @pure { body } ... } in source order: For each harvard{ ... fn f(args) @total { body } ... } in source order: Πᵢ₊₁ = Πᵢ, f : sig -``` +.... -An `add{...}` block at position j in the source sees Π = Πⱼ (all @pure/@total -functions defined in harvard{...} blocks that precede position j). +An `+add{...}+` block at position j in the source sees Π = Πⱼ (all +@pure/@total functions defined in harvard\{…} blocks that precede +position j). ---- +''''' -## 9. Extended Typing Rules +=== 9. Extended Typing Rules -### 9.1 Harvard Data Blocks (add{...}) +==== 9.1 Harvard Data Blocks (add\{…}) -``` +.... Π ⊢_hd he : hτ Embed(hτ) = τ Embed(hτ) ≠ ERROR ──────────────────────────────────────────────────────────── [T-Add] Γ ⊢ add{ he } : τ -``` +.... -Where `⊢_hd` is the Harvard data typing judgment (see §9.3). +Where `+⊢_hd+` is the Harvard data typing judgment (see §9.3). -### 9.2 Harvard Control Blocks (harvard{...}) +==== 9.2 Harvard Control Blocks (harvard\{…}) -``` +.... Δ ⊢_hc hp ⊣ Δ' -- hp typechecks, extending Δ to Δ' extract_pure(Δ' \ Δ) = Π' -- new @pure/@total bindings ──────────────────────────────────── [T-Harvard] Γ; Δ; Π ⊢ harvard{ hp } ⊣ Γ; Δ'; Π ∪ Π' -``` +.... -Harvard blocks are statement-level: they don't produce TANGLE values. +Harvard blocks are statement-level: they don’t produce TANGLE values. They extend Δ and Π for subsequent blocks. -### 9.3 Harvard Data Typing (⊢_hd) +==== 9.3 Harvard Data Typing (⊢_hd) -Typing judgment for expressions inside `add{...}`: +Typing judgment for expressions inside `+add{...}+`: -``` +.... ─────────────────── [HD-Num] Π ⊢_hd n : Int @@ -1489,23 +1531,23 @@ op ∈ {==, !=, <, <=, >, >=} Π ⊢_hd he : numeric ──────────────────── [HD-Neg] Π ⊢_hd -he : numeric -``` +.... -### 9.4 TANGLE Value Passing to Harvard (Unembed) +==== 9.4 TANGLE Value Passing to Harvard (Unembed) When a TANGLE value is passed as argument to a Harvard function: -``` +.... Γ ⊢ e : τ Unembed(τ) = hτ Unembed(τ) ≠ ERROR ──────────────────────────────────────────────────────────── [T-Unembed] Π ⊢_hd e : hτ (TANGLE expression in Harvard data context) -``` +.... -### 9.5 Harvard Calling TANGLE (D2.9) +==== 9.5 Harvard Calling TANGLE (D2.9) Harvard functions can call TANGLE functions with purity restriction: -``` +.... (f : (τ₁,...,τₖ) → τ) ∈ Γ f is non-recursive (syntactic check) Δ ⊢_hc eᵢ : τᵢ for each i (with Unembed) @@ -1518,30 +1560,32 @@ f may be recursive Δ ⊢_hc eᵢ : τᵢ for each i (with Unembed) ────────────────────────────────────────────── [HC-Call-Tangle-Impure] Δ ⊢_hc f(e₁,...,eₖ) : τ (legal ONLY in unmarked context, NOT in @pure/@total) -``` +.... -**Recursion check** (syntactic, conservative): +*Recursion check* (syntactic, conservative): -``` +.... is_recursive(def f(x₁,...,xₖ) = body) = f ∈ reachable_names(body, Γ) -``` +.... -Where `reachable_names(body, Γ)` is the transitive closure of free names: +Where `+reachable_names(body, Γ)+` is the transitive closure of free +names: -``` +.... reachable_names(body, Γ) = let direct = free_names(body) let indirect = ∪ { free_names(Γ(g).body) | g ∈ direct, g is a function in Γ } direct ∪ reachable_names(indirect \ direct, Γ) -- fixed-point iteration -``` +.... -This detects both direct recursion (`f` calls `f`) and mutual recursion -(`f` calls `g` which calls `f`). The check is conservative: if the call -graph cannot be statically determined, the function is marked recursive. +This detects both direct recursion (`+f+` calls `+f+`) and mutual +recursion (`+f+` calls `+g+` which calls `+f+`). The check is +conservative: if the call graph cannot be statically determined, the +function is marked recursive. -### 9.6 Module Imports (D2.6, D2.11) +==== 9.6 Module Imports (D2.6, D2.11) -``` +.... M ∈ Δ M defined in earlier harvard{...} block ──────────────────────────────────────────────────── [HC-Import] Δ ⊢_hc import M ⊣ Δ, (all bindings from M) @@ -1550,37 +1594,37 @@ M ∈ Δ M defined in earlier harvard{...} block M ∈ Δ M defined in earlier harvard{...} block ──────────────────────────────────────────────────── [HC-Import-Alias] Δ ⊢_hc import M as A ⊣ Δ, (all bindings from M under prefix A) -``` +.... -Imports are private: importing M in module N does not make M's bindings +Imports are private: importing M in module N does not make M’s bindings available to consumers of N (D2.11). ---- +''''' -## 10. Extended Operational Semantics +=== 10. Extended Operational Semantics -### 10.1 Harvard Data Block Evaluation +==== 10.1 Harvard Data Block Evaluation -``` +.... ρ_Π = extract_pure_values(ρ) -- runtime values for Π functions ρ_Π ⊢_hd he ⇓ hv -- evaluate Harvard data expression v = embed_value(hv) -- convert Harvard value to TANGLE value ────────────────────────────────── [E-Add] ρ ⊢ add{ he } ⇓ v -``` +.... -Where `embed_value`: +Where `+embed_value+`: -``` +.... embed_value(int(n)) = num(n) embed_value(float(f)) = num(f) embed_value(bool(b)) = bool(b) embed_value(string(s)) = str(s) -``` +.... -### 10.2 Harvard Data Expression Evaluation (⊢_hd) +==== 10.2 Harvard Data Expression Evaluation (⊢_hd) -``` +.... ────────────────────── [EHD-Num] ρ_Π ⊢_hd n ⇓ int(n) @@ -1600,11 +1644,11 @@ embed_value(string(s)) = str(s) ρ_Π ⊢_hd he₁ ⇓ bool(false) ρ_Π ⊢_hd he₃ ⇓ hv ──────────────────────────────────────────────────── [EHD-If-False] ρ_Π ⊢_hd if he₁ then he₂ else he₃ ⇓ hv -``` +.... -### 10.3 TANGLE Value in Harvard Context (Unembed) +==== 10.3 TANGLE Value in Harvard Context (Unembed) -``` +.... ρ ⊢ e ⇓ num(n) ──────────────────────── [E-Unembed-Num] ρ_Π ⊢_hd e ⇓ int(n) @@ -1618,101 +1662,98 @@ embed_value(string(s)) = str(s) ρ ⊢ e ⇓ bool(b) ──────────────────────── [E-Unembed-Bool] ρ_Π ⊢_hd e ⇓ bool(b) -``` +.... -### 10.4 Harvard Control Block Evaluation +==== 10.4 Harvard Control Block Evaluation -Harvard control blocks are evaluated for their side effects (defining functions, -modules). They do not produce TANGLE values. +Harvard control blocks are evaluated for their side effects (defining +functions, modules). They do not produce TANGLE values. -``` +.... ρ_Δ = current Harvard runtime environment ρ_Δ ⊢_hc hp ⇓ ρ_Δ' -- execute Harvard program, get new environment ρ' = ρ ∪ extract_pure(ρ_Δ' \ ρ_Δ) -- add new @pure functions to TANGLE env ──────────────────────────────────── [E-Harvard] ρ ⊢ harvard{ hp } ⇓ ok, ρ' -``` +.... -Detailed Harvard control evaluation rules (while loops, assignments, etc.) -follow standard imperative semantics and are not specified here. The key -constraint is the purity discipline: @pure functions must not access mutable -state or perform I/O. +Detailed Harvard control evaluation rules (while loops, assignments, +etc.) follow standard imperative semantics and are not specified here. +The key constraint is the purity discipline: @pure functions must not +access mutable state or perform I/O. ---- +''''' -## 11. Metatheory +=== 11. Metatheory -### 11.1 Type Safety (Conjecture) +==== 11.1 Type Safety (Conjecture) -**Progress**: If `Γ ⊢ e : τ` and e is not a value, then either: -- e can take a step (ρ ⊢ e ⇓ v for some v), or -- e halts with an error (ρ ⊢ e ⇓ halt(m)), or -- e diverges +*Progress*: If `+Γ ⊢ e : τ+` and e is not a value, then either: - e can +take a step (ρ ⊢ e ⇓ v for some v), or - e halts with an error (ρ ⊢ e ⇓ +halt(m)), or - e diverges -**Preservation**: If `Γ ⊢ e : τ` and `ρ ⊢ e ⇓ v`, then v has type τ. +*Preservation*: If `+Γ ⊢ e : τ+` and `+ρ ⊢ e ⇓ v+`, then v has type τ. Note: These are conjectures for the MVP. Formal proofs are future work. -### 11.2 Turing Completeness (D1.24) +==== 11.2 Turing Completeness (D1.24) -TANGLE is Turing complete via: -1. **Data**: Word values = inductively defined sequences (identity = nil, g . w = cons) -2. **Branching**: Pattern matching on Word structure -3. **Iteration**: General recursion on definitions (D1.3) +TANGLE is Turing complete via: 1. *Data*: Word values = inductively +defined sequences (identity = nil, g . w = cons) 2. *Branching*: Pattern +matching on Word structure 3. *Iteration*: General recursion on +definitions (D1.3) -**Proof sketch**: Encode a Turing machine as: -- Tape alphabet → generator indices (s₁ = symbol 1, s₂ = symbol 2, ...) -- Tape = Word value (generator sequence) -- Head position = Num value -- Transition function = pattern match + recursion -- Halting state = base case in match +*Proof sketch*: Encode a Turing machine as: - Tape alphabet → generator +indices (s₁ = symbol 1, s₂ = symbol 2, …) - Tape = Word value (generator +sequence) - Head position = Num value - Transition function = pattern +match + recursion - Halting state = base case in match -### 11.3 Totality of add{...} (D2.1) +==== 11.3 Totality of add\{…} (D2.1) -Harvard data expressions (inside `add{...}`) are total: -- No loops (while/for excluded from grammar) -- No recursion (functions in Π are checked by the @pure/@total discipline) -- Conditional requires both branches -- All operations on finite data +Harvard data expressions (inside `+add{...}+`) are total: - No loops +(while/for excluded from grammar) - No recursion (functions in Π are +checked by the @pure/@total discipline) - Conditional requires both +branches - All operations on finite data -Informal argument: The `⊢_hd` typing rules exclude all sources of non-termination. -A formal proof would show that `ρ_Π ⊢_hd he ⇓ hv` always holds (no divergence). +Informal argument: The `+⊢_hd+` typing rules exclude all sources of +non-termination. A formal proof would show that `+ρ_Π ⊢_hd he ⇓ hv+` +always holds (no divergence). -### 11.4 Soundness of Purity Restriction (D2.9) +==== 11.4 Soundness of Purity Restriction (D2.9) -If a Harvard function marked @pure calls only non-recursive TANGLE functions -(per HC-Call-Tangle-Pure), and the @pure function itself terminates, then: -- The combined call always terminates -- No side effects occur +If a Harvard function marked @pure calls only non-recursive TANGLE +functions (per HC-Call-Tangle-Pure), and the @pure function itself +terminates, then: - The combined call always terminates - No side +effects occur -This follows from: -1. Non-recursive TANGLE functions terminate on all inputs (no recursive calls) -2. @pure Harvard functions have no side effects by construction -3. Composition of terminating, effect-free computations terminates without effects +This follows from: 1. Non-recursive TANGLE functions terminate on all +inputs (no recursive calls) 2. @pure Harvard functions have no side +effects by construction 3. Composition of terminating, effect-free +computations terminates without effects -### 11.5 Coherence of Auto-Widening (D1.8.5) +==== 11.5 Coherence of Auto-Widening (D1.8.5) Auto-widening preserves braid group semantics: -If w₁ ∈ B_n and w₂ ∈ B_m, then w₁ . w₂ is computed in B_{max(n,m)} via -the standard stabilization embedding ι : B_n → B_{n+1} which adds an +If w₁ ∈ B_n and w₂ ∈ B_m, then w₁ . w₂ is computed in B_\{max(n,m)} via +the standard stabilization embedding ι : B_n → B_\{n+1} which adds an identity strand. This embedding is a group homomorphism: -``` +.... ι(sᵢ) = sᵢ (generators preserved) ι(w₁ · w₂) = ι(w₁) · ι(w₂) (homomorphism) -``` +.... Therefore, auto-widening is sound: the isotopy class of the widened word is the canonical image of the original word under stabilization. ---- +''''' -## 12. Precedence Table (Complete) +=== 12. Precedence Table (Complete) Operator precedence from lowest to highest binding: -``` +.... Precedence Operator Associativity Domain ────────── ──────── ───────────── ────── 1 (lowest) >> left Word, Tangle (sugar for .) @@ -1724,64 +1765,85 @@ Precedence Operator Associativity Domain Unary: ~e prefix Word, Tangle (twist) -e prefix Num (negation) -``` +.... + +In weave context, crossings `+(a > b)+` and `+(a < b)+` are atomic +expressions (fully parenthesized by syntax). + +''''' + +=== Appendix A: Summary of Semantic Functions + +[width="100%",cols="30%,32%,38%",options="header",] +|=== +|Function |Signature |Description +|`+width(e)+` |Expr → Nat |Maximum strand index + 1 + +|`+πw+` |Word → Permutation |Permutation induced by braid word + +|`+isotopy(v₁, v₂)+` |Value × Value → Bool |Equality in FR(T) + +|`+reidemeister_reduce(w)+` |Word → Word |Canonical form via +Reidemeister moves + +|`+match(v, p)+` |Value × Pattern → Subst ∪ \{fail} |Pattern matching + +|`+Embed(hτ)+` |HarvardType → TangleType |Type bridge Harvard → TANGLE + +|`+Unembed(τ)+` |TangleType → HarvardType |Type bridge TANGLE → Harvard + +|`+embed_value(hv)+` |HarvardValue → TangleValue |Value bridge Harvard → +TANGLE + +|`+is_recursive(def)+` |Definition → Bool |Syntactic recursion check + +|`+shift(g, k)+` |Generator × Nat → Generator |Index shift for tensor -In weave context, crossings `(a > b)` and `(a < b)` are atomic expressions -(fully parenthesized by syntax). +|`+swap(A, i, j)+` |Boundary × Nat × Nat → Boundary |Position swap in +boundary ---- +|`+twist_generators(n)+` |Nat → Word |Full twist braid on n strands -## Appendix A: Summary of Semantic Functions +|`+close(t)+` |Tangle → Tangle |Trace operation (close all strands) -| Function | Signature | Description | -|----------|-----------|-------------| -| `width(e)` | Expr → Nat | Maximum strand index + 1 | -| `πw` | Word → Permutation | Permutation induced by braid word | -| `isotopy(v₁, v₂)` | Value × Value → Bool | Equality in FR(T) | -| `reidemeister_reduce(w)` | Word → Word | Canonical form via Reidemeister moves | -| `match(v, p)` | Value × Pattern → Subst ∪ {fail} | Pattern matching | -| `Embed(hτ)` | HarvardType → TangleType | Type bridge Harvard → TANGLE | -| `Unembed(τ)` | TangleType → HarvardType | Type bridge TANGLE → Harvard | -| `embed_value(hv)` | HarvardValue → TangleValue | Value bridge Harvard → TANGLE | -| `is_recursive(def)` | Definition → Bool | Syntactic recursion check | -| `shift(g, k)` | Generator × Nat → Generator | Index shift for tensor | -| `swap(A, i, j)` | Boundary × Nat × Nat → Boundary | Position swap in boundary | -| `twist_generators(n)` | Nat → Word | Full twist braid on n strands | -| `close(t)` | Tangle → Tangle | Trace operation (close all strands) | -| `disjoint_union(t₁, t₂)` | Tangle × Tangle → Tangle | Disjoint union of closed tangles | +|`+disjoint_union(t₁, t₂)+` |Tangle × Tangle → Tangle |Disjoint union of +closed tangles +|=== ---- +''''' -## Appendix B: Decision Traceability +=== Appendix B: Decision Traceability Every rule in this document traces to a locked decision: -| Rule(s) | Decision | -|---------|----------| -| T-Identity, E-Identity | D1.14 (identity = Word[0]) | -| T-Braid, E-Braid | D1.1 (braid literals = Word[n]) | -| T-Compose-Word | D1.8.5 (auto-widening) | -| T-Add-Num, T-Add-Tangle | D1.6, D1.7 (+ overloaded, closed only) | -| T-Eq-*, T-Isotopy | D1.2 (two equalities) | -| T-Close-* | D1.17 (no permutation check) | -| T-Twist-* | D1.18 (context-dependent twist) | -| T-Match, P-*, E-Match-* | D1.3, D1.4 (recursion, exhaustiveness) | -| T-Let, E-Let | D1.4.5 (let scoping) | -| T-Weave | D1.9, D1.10, D1.11 (weave rules) | -| T-Add, E-Add | D2.1, D2.4 (three worlds, Embed) | -| HC-Call-Tangle-* | D2.9 (Harvard calling TANGLE) | -| T-Unembed, E-Unembed-* | D2.10 (reverse embedding) | -| T-Assert, E-Assert-* | D1.15, D1.15.1 (halt/panic, assert) | -| E-Simplify | D1.16 Tier 1 (simplify is primitive) | -| E-Pipeline | D1.20 (>> sugar for .) | -| T-Self-Cross | D1.19 (self-crossing = twist) | -| T-Program | D1.13 (two-pass) | -| E-App | D1.13.5 (call-by-value) | -| HD-*, EHD-* | D2.1, D2.3 (Harvard data, sequential Π) | -| HD-Compare, HD-And, HD-Or, HD-Not | D2.1 (total data grammar) | -| HD-Var, HD-Str, HD-Neg | D2.1 (data expression completeness) | -| T-Compute + result_type | D1.12, D1.16 (invariant computation) | - ---- - -*End of formal semantics.* +[cols=",",options="header",] +|=== +|Rule(s) |Decision +|T-Identity, E-Identity |D1.14 (identity = Word[0]) +|T-Braid, E-Braid |D1.1 (braid literals = Word[n]) +|T-Compose-Word |D1.8.5 (auto-widening) +|T-Add-Num, T-Add-Tangle |D1.6, D1.7 (+ overloaded, closed only) +|T-Eq-*, T-Isotopy |D1.2 (two equalities) +|T-Close-* |D1.17 (no permutation check) +|T-Twist-* |D1.18 (context-dependent twist) +|T-Match, P-_, E-Match-_ |D1.3, D1.4 (recursion, exhaustiveness) +|T-Let, E-Let |D1.4.5 (let scoping) +|T-Weave |D1.9, D1.10, D1.11 (weave rules) +|T-Add, E-Add |D2.1, D2.4 (three worlds, Embed) +|HC-Call-Tangle-* |D2.9 (Harvard calling TANGLE) +|T-Unembed, E-Unembed-* |D2.10 (reverse embedding) +|T-Assert, E-Assert-* |D1.15, D1.15.1 (halt/panic, assert) +|E-Simplify |D1.16 Tier 1 (simplify is primitive) +|E-Pipeline |D1.20 (>> sugar for .) +|T-Self-Cross |D1.19 (self-crossing = twist) +|T-Program |D1.13 (two-pass) +|E-App |D1.13.5 (call-by-value) +|HD-_, EHD-_ |D2.1, D2.3 (Harvard data, sequential Π) +|HD-Compare, HD-And, HD-Or, HD-Not |D2.1 (total data grammar) +|HD-Var, HD-Str, HD-Neg |D2.1 (data expression completeness) +|T-Compute + result_type |D1.12, D1.16 (invariant computation) +|=== + +''''' + +_End of formal semantics._ diff --git a/docs/spec/UNANSWERED-QUESTIONS.adoc b/docs/spec/UNANSWERED-QUESTIONS.adoc new file mode 100644 index 0000000..4772cae --- /dev/null +++ b/docs/spec/UNANSWERED-QUESTIONS.adoc @@ -0,0 +1,70 @@ +== TANGLE & TANGLE-JTV — Questions Status + +Last updated: 2026-02-12 + +''''' + +=== ALL QUESTIONS RESOLVED + +All 21 questions have been answered and locked into DECISIONS-LOCKED.md. + +==== Resolution Summary + +[width="100%",cols="10%,29%,29%,32%",options="header",] +|=== +|# |Question |Decision |Locked As +|A1.1 |Identity width |Word[0] + auto-widening |D1.14 + +|A1.2 |Close validation |No permutation check |D1.17 + +|A1.3 |Polymorphic boundaries |Width inference, no HM |D1.21 + +|A2.1 |Exhaustiveness scope |Width-aware warning |D1.4 (updated) + +|A2.2 |Self-crossings |Allow, warn, desugar to (~a) |D1.19 + +|A3.1 |Name conflicts |Unified namespace, warn on shadow |D1.15.3 + +|A3.2 |Weave visibility |Can see all of Γ |D2.8 + +|A3.3 |Module system |Flat for MVP |D1.22 + +|A4.1 |Length function |Standard library (Tier 3) |D1.23 + +|A4.2 |Pipeline precedence |Lower than `+.+`, readability sugar |D1.20 + +|A4.3 |Twist operator |Context-dependent (standalone vs weave) |D1.18 + +|A4.4 |Assertion decidability |Runtime only MVP; future: assert vs prove +|D1.15.1 + +|A5.1 |Error handling |Halt/panic MVP; noted for future review |D1.15 + +|A5.2 |Error messages |Name-based with positional hints |D1.15.2 + +|A6.1 |Primitives vs library |Three-tier split |D1.16 + +|B1.1 |Harvard calling TANGLE |Yes, @pure only non-recursive |D2.9 + +|B1.2 |Reverse embedding |Implicit scalar Unembed |D2.10 + +|B1.3 |Turing completeness |Via pattern matching + recursion |D1.24 + +|B2.1 |Data encoding |JTV for complex data, TANGLE = topology |D1.25 + +|B2.2 |Generator partitioning |N/A — resolved by B2.1 |D1.25 + +|B3.1 |Module re-exports |Private for MVP; noted for future review +|D2.11 +|=== + +==== Future Review Items + +These were explicitly flagged for post-MVP reconsideration: 1. *A5.1 / +D1.15*: Richer error handling model (exceptions, Result types) 2. *A4.4 +/ D1.15.1*: `+assert+` vs `+prove+` split for static verification 3. +*B3.1 / D2.11*: Module re-exports (Rust-style `+pub use+`) + +''''' + +See `+DECISIONS-LOCKED.md+` for full details on every decision. diff --git a/docs/spec/UNANSWERED-QUESTIONS.md b/docs/spec/UNANSWERED-QUESTIONS.md deleted file mode 100644 index 0f51264..0000000 --- a/docs/spec/UNANSWERED-QUESTIONS.md +++ /dev/null @@ -1,50 +0,0 @@ - -# TANGLE & TANGLE-JTV — Questions Status - -Last updated: 2026-02-12 - ---- - -## ALL QUESTIONS RESOLVED - -All 21 questions have been answered and locked into DECISIONS-LOCKED.md. - -### Resolution Summary - -| # | Question | Decision | Locked As | -|---|----------|----------|-----------| -| A1.1 | Identity width | Word[0] + auto-widening | D1.14 | -| A1.2 | Close validation | No permutation check | D1.17 | -| A1.3 | Polymorphic boundaries | Width inference, no HM | D1.21 | -| A2.1 | Exhaustiveness scope | Width-aware warning | D1.4 (updated) | -| A2.2 | Self-crossings | Allow, warn, desugar to (~a) | D1.19 | -| A3.1 | Name conflicts | Unified namespace, warn on shadow | D1.15.3 | -| A3.2 | Weave visibility | Can see all of Γ | D2.8 | -| A3.3 | Module system | Flat for MVP | D1.22 | -| A4.1 | Length function | Standard library (Tier 3) | D1.23 | -| A4.2 | Pipeline precedence | Lower than `.`, readability sugar | D1.20 | -| A4.3 | Twist operator | Context-dependent (standalone vs weave) | D1.18 | -| A4.4 | Assertion decidability | Runtime only MVP; future: assert vs prove | D1.15.1 | -| A5.1 | Error handling | Halt/panic MVP; noted for future review | D1.15 | -| A5.2 | Error messages | Name-based with positional hints | D1.15.2 | -| A6.1 | Primitives vs library | Three-tier split | D1.16 | -| B1.1 | Harvard calling TANGLE | Yes, @pure only non-recursive | D2.9 | -| B1.2 | Reverse embedding | Implicit scalar Unembed | D2.10 | -| B1.3 | Turing completeness | Via pattern matching + recursion | D1.24 | -| B2.1 | Data encoding | JTV for complex data, TANGLE = topology | D1.25 | -| B2.2 | Generator partitioning | N/A — resolved by B2.1 | D1.25 | -| B3.1 | Module re-exports | Private for MVP; noted for future review | D2.11 | - -### Future Review Items - -These were explicitly flagged for post-MVP reconsideration: -1. **A5.1 / D1.15**: Richer error handling model (exceptions, Result types) -2. **A4.4 / D1.15.1**: `assert` vs `prove` split for static verification -3. **B3.1 / D2.11**: Module re-exports (Rust-style `pub use`) - ---- - -See `DECISIONS-LOCKED.md` for full details on every decision. diff --git a/docs/tech-debt-2026-05-26.adoc b/docs/tech-debt-2026-05-26.adoc new file mode 100644 index 0000000..17ddb3a --- /dev/null +++ b/docs/tech-debt-2026-05-26.adoc @@ -0,0 +1,70 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 SPDX-FileCopyrightText: 2026 +Jonathan D.A. Jewell (hyperpolymath) –> + +== Tech-Debt Audit — tangle — 2026-05-26 + +*Source:* estate-wide automated scan 2026-05-26. *Companion:* +https://github.com/hyperpolymath/standards/tree/main/docs/audits[`+hyperpolymath/standards+` +2026-05-26-estate-*-debt audits]. *Combined severity:* `+LOW+`. + +This file records the _raw findings_ — it does not by itself fix the +debt. Each section ends with a '`Recommended next move`' line; closing +the debt is follow-up work. + +=== 1. Proof debt + +No proof-bearing files (`+*.v+`, `+*.lean+`, `+*.agda+`, `+*.idr+`, +`+*.idr2+`, `+*.fst+`, `+*.dfy+`, `+*.tla+`, `+*.ads+`, `+*.adb+`) found +in this repo. + +*Recommended next move:* none. + +=== 2. Licence debt + +[cols=",",options="header",] +|=== +|Field |Value +|LICENSE file |`+LICENSE+` +|SPDX header |`+MPL-2.0+` +|Manifest licence |`+NONE+` +|Body classifier |`+Palimp-MPL-2.0+` +|Severity |`+ok+` +|=== + +*Recommended next move:* none for licence. + +=== 3. Documentation debt + +[cols=",",options="header",] +|=== +|Field |Value +|README lines |196 +|`+docs/+` files |6 +|`+docs/+` LoC |3023 +|CHANGELOG.md |Y +|CONTRIBUTING.md |Y +|CODE_OF_CONDUCT.md |Y +|SECURITY.md |Y +|Severity |`+LOW+` +|=== + +*Recommended next move:* `+docs/+` has only 6 file(s). Aim for ≥10 +organised docs (architecture, usage, contributing-guide, +troubleshooting, design-decisions). The user’s bar for a +"`heavily-developed and well-organised wiki`" is ≥10 files with topical +organisation. + +=== Cross-references + +* Estate proof-debt audit: +`+hyperpolymath/standards/docs/audits/2026-05-26-estate-proof-debt.md+` +* Estate licence-debt audit: +`+hyperpolymath/standards/docs/audits/2026-05-26-estate-licence-debt.md+` +* Estate documentation-debt audit: +`+hyperpolymath/standards/docs/audits/2026-05-26-estate-documentation-debt.md+` + +''''' + +🤖 Generated by Claude Code estate-wide tech-debt scan (2026-05-26). +This file is informational — closing the debt is follow-up work owned by +the maintainer. diff --git a/docs/tech-debt-2026-05-26.md b/docs/tech-debt-2026-05-26.md deleted file mode 100644 index 6e41a29..0000000 --- a/docs/tech-debt-2026-05-26.md +++ /dev/null @@ -1,56 +0,0 @@ - -SPDX-License-Identifier: CC-BY-SA-4.0 -SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath) ---> - -# Tech-Debt Audit — tangle — 2026-05-26 - -**Source:** estate-wide automated scan 2026-05-26. -**Companion:** [`hyperpolymath/standards` 2026-05-26-estate-*-debt audits](https://github.com/hyperpolymath/standards/tree/main/docs/audits). -**Combined severity:** `LOW`. - -This file records the *raw findings* — it does not by itself fix the debt. Each section ends with a 'Recommended next move' line; closing the debt is follow-up work. - -## 1. Proof debt - -No proof-bearing files (`*.v`, `*.lean`, `*.agda`, `*.idr`, `*.idr2`, `*.fst`, `*.dfy`, `*.tla`, `*.ads`, `*.adb`) found in this repo. - -**Recommended next move:** none. - -## 2. Licence debt - -| Field | Value | -|---|---| -| LICENSE file | `LICENSE` | -| SPDX header | `MPL-2.0` | -| Manifest licence | `NONE` | -| Body classifier | `Palimp-MPL-2.0` | -| Severity | `ok` | - -**Recommended next move:** none for licence. - -## 3. Documentation debt - -| Field | Value | -|---|---| -| README lines | 196 | -| `docs/` files | 6 | -| `docs/` LoC | 3023 | -| CHANGELOG.md | Y | -| CONTRIBUTING.md | Y | -| CODE_OF_CONDUCT.md | Y | -| SECURITY.md | Y | -| Severity | `LOW` | - -**Recommended next move:** `docs/` has only 6 file(s). Aim for ≥10 organised docs (architecture, usage, contributing-guide, troubleshooting, design-decisions). The user's bar for a "heavily-developed and well-organised wiki" is ≥10 files with topical organisation. - -## Cross-references - -- Estate proof-debt audit: `hyperpolymath/standards/docs/audits/2026-05-26-estate-proof-debt.md` -- Estate licence-debt audit: `hyperpolymath/standards/docs/audits/2026-05-26-estate-licence-debt.md` -- Estate documentation-debt audit: `hyperpolymath/standards/docs/audits/2026-05-26-estate-documentation-debt.md` - ---- - -🤖 Generated by Claude Code estate-wide tech-debt scan (2026-05-26). This file is informational — closing the debt is follow-up work owned by the maintainer. diff --git a/llm-warmup-dev.adoc b/llm-warmup-dev.adoc new file mode 100644 index 0000000..b35091d --- /dev/null +++ b/llm-warmup-dev.adoc @@ -0,0 +1,19 @@ +== LLM Warmup — tangle (Developer) + +=== What is tangle? + +See README.adoc for overview. + +=== Key Commands + +* `+just setup+` — set up development environment +* `+just build+` — build the project +* `+just test+` — run tests +* `+just doctor+` — diagnose issues +* `+just heal+` — attempt auto-repair + +=== Quick Context + +* License: MPL-2.0 +* Part of hyperpolymath ecosystem +* See EXPLAINME.adoc for architecture diff --git a/llm-warmup-dev.md b/llm-warmup-dev.md deleted file mode 100644 index fb8ec72..0000000 --- a/llm-warmup-dev.md +++ /dev/null @@ -1,20 +0,0 @@ - -# LLM Warmup — tangle (Developer) - -## What is tangle? -See README.adoc for overview. - -## Key Commands -- `just setup` — set up development environment -- `just build` — build the project -- `just test` — run tests -- `just doctor` — diagnose issues -- `just heal` — attempt auto-repair - -## Quick Context -- License: MPL-2.0 -- Part of hyperpolymath ecosystem -- See EXPLAINME.adoc for architecture diff --git a/llm-warmup-user.adoc b/llm-warmup-user.adoc new file mode 100644 index 0000000..3c09745 --- /dev/null +++ b/llm-warmup-user.adoc @@ -0,0 +1,19 @@ +== LLM Warmup — tangle (User) + +=== What is tangle? + +See README.adoc for overview. + +=== Key Commands + +* `+just setup+` — set up development environment +* `+just build+` — build the project +* `+just test+` — run tests +* `+just doctor+` — diagnose issues +* `+just heal+` — attempt auto-repair + +=== Quick Context + +* License: MPL-2.0 +* Part of hyperpolymath ecosystem +* See EXPLAINME.adoc for architecture diff --git a/llm-warmup-user.md b/llm-warmup-user.md deleted file mode 100644 index d78df5f..0000000 --- a/llm-warmup-user.md +++ /dev/null @@ -1,20 +0,0 @@ - -# LLM Warmup — tangle (User) - -## What is tangle? -See README.adoc for overview. - -## Key Commands -- `just setup` — set up development environment -- `just build` — build the project -- `just test` — run tests -- `just doctor` — diagnose issues -- `just heal` — attempt auto-repair - -## Quick Context -- License: MPL-2.0 -- Part of hyperpolymath ecosystem -- See EXPLAINME.adoc for architecture diff --git a/playground/README.adoc b/playground/README.adoc new file mode 100644 index 0000000..54c2bc9 --- /dev/null +++ b/playground/README.adoc @@ -0,0 +1,44 @@ +== Tangle Playground + +A local PWA playground for the Tangle topological programming language. + +=== Status + +*Scaffold.* The directory structure is in place. The interactive +playground itself is not yet built. + +=== Intended architecture (pattern mirrors sibling language playgrounds) + +* *Compiler backend:* `+compiler/tangle-wasm/+` compiled to WASM +* *Runtime:* Deno or Bun serving the PWA shell + static assets +* *UI:* ReScript + React SPA with Monaco editor +* *Execution modes:* +** `+parse+` — show AST +** `+typecheck+` — show type errors + inferred types +** `+compile+` — PlanarDiagram / TangleIR output +** `+eval+` — step-through evaluator (PanLL timeline if available) +* *Share-by-URL:* URL-encoded source for sharing snippets +* *Examples:* `+playground/examples/+` — starter programs + +=== Directory layout + +.... +playground/ +├── README.md (this file) +├── public/ (static assets; PWA shell goes here when built) +└── examples/ (starter .tangle programs) +.... + +=== Next steps to build this out + +[arabic] +. Write a minimal Deno server that serves `+public/+` + a `+/run+` +endpoint +. Build tangle-wasm to WASM with `+wasm-pack+` or similar +. Add Monaco editor with Tangle syntax highlighting +. Add execution-mode tabs +. Add example loader wiring up `+playground/examples/+` + +See sibling playgrounds for patterns: - +`+/var/mnt/eclipse/repos/nextgen-languages/eclexia/playground/+` - +`+/var/mnt/eclipse/repos/nextgen-languages/betlang/playground/+` diff --git a/playground/README.md b/playground/README.md deleted file mode 100644 index 5ec438e..0000000 --- a/playground/README.md +++ /dev/null @@ -1,46 +0,0 @@ - -# Tangle Playground - -A local PWA playground for the Tangle topological programming language. - -## Status - -**Scaffold.** The directory structure is in place. The interactive playground -itself is not yet built. - -## Intended architecture (pattern mirrors sibling language playgrounds) - -- **Compiler backend:** `compiler/tangle-wasm/` compiled to WASM -- **Runtime:** Deno or Bun serving the PWA shell + static assets -- **UI:** ReScript + React SPA with Monaco editor -- **Execution modes:** - - `parse` — show AST - - `typecheck` — show type errors + inferred types - - `compile` — PlanarDiagram / TangleIR output - - `eval` — step-through evaluator (PanLL timeline if available) -- **Share-by-URL:** URL-encoded source for sharing snippets -- **Examples:** `playground/examples/` — starter programs - -## Directory layout - -``` -playground/ -├── README.md (this file) -├── public/ (static assets; PWA shell goes here when built) -└── examples/ (starter .tangle programs) -``` - -## Next steps to build this out - -1. Write a minimal Deno server that serves `public/` + a `/run` endpoint -2. Build tangle-wasm to WASM with `wasm-pack` or similar -3. Add Monaco editor with Tangle syntax highlighting -4. Add execution-mode tabs -5. Add example loader wiring up `playground/examples/` - -See sibling playgrounds for patterns: -- `/var/mnt/eclipse/repos/nextgen-languages/eclexia/playground/` -- `/var/mnt/eclipse/repos/nextgen-languages/betlang/playground/` diff --git a/proofs/README.adoc b/proofs/README.adoc new file mode 100644 index 0000000..2ce8fe9 --- /dev/null +++ b/proofs/README.adoc @@ -0,0 +1,56 @@ +== Tangle proofs + +Mechanised metatheory for the Tangle core type system, in Lean 4. + +* link:Tangle.lean[`+Tangle.lean+`] — the proofs (the repo’s *build +oracle*). +* link:lean-toolchain[`+lean-toolchain+`] — the pinned Lean version +(`+leanprover/lean4:v4.14.0+`). Single source of truth for the +toolchain. +* link:bootstrap-lean.sh[`+bootstrap-lean.sh+`] — installs that +toolchain. + +=== What is proven + +`+Tangle.lean+` mechanises type safety for the core language, all under +Lean’s kernel with *no `+sorry+`/`+axiom+`/`+admit+`* (enforced by CI): + +* *Progress, Preservation, Determinism, Type Safety* — for the let-free +fragment _and_ the echo-types fragment. +* *Echo types* (structured loss): `+Ty.echo+`, +`+echoClose+`/`+lower+`/`+residue+`, with the residue-recovery / +non-injectivity capstones. See the `+§ECHO-TYPES+` section of +`+Tangle.lean+` and +link:../PROOF-NARRATIVE.md[`+../PROOF-NARRATIVE.md+`] §2.5. +* *Decidability* (TG-2): `+infer ≡ HasType+`, type uniqueness, and a +`+Decidable (HasType [] e τ)+` instance. + +=== Building / verifying + +[source,sh] +---- +# 1. Install the pinned toolchain (idempotent). +./proofs/bootstrap-lean.sh + +# 2. Put lean on PATH for this shell. +eval "$(./proofs/bootstrap-lean.sh --print-path)" + +# 3. Verify — 0 errors means the proofs check. +cd proofs && lean Tangle.lean +---- + +==== Why `+bootstrap-lean.sh+` exists + +`+elan+` (the Lean toolchain manager) resolves toolchains from +`+release.lean-lang.org+`, which is *not on the network allowlist* in +sandboxed environments such as Claude Code on the web. GitHub release +assets _are_ reachable, so when the normal install path is blocked the +script fetches the pinned toolchain directly from `+github.com+`. On an +open network (e.g. GitHub Actions runners) it uses the normal `+elan+` +path. Either way it reads the version from `+lean-toolchain+`, so it +stays correct when the pin is bumped. + +CI runs the same oracle in +link:../.github/workflows/lean-proofs.yml[`+.github/workflows/lean-proofs.yml+`]: +`+lean Tangle.lean+` must report 0 errors and the file must contain no +`+sorry+`/`+axiom+`/`+admit+`/`+Admitted+` outside comments. diff --git a/proofs/README.md b/proofs/README.md deleted file mode 100644 index 58318b6..0000000 --- a/proofs/README.md +++ /dev/null @@ -1,53 +0,0 @@ - -# Tangle proofs - -Mechanised metatheory for the Tangle core type system, in Lean 4. - -- [`Tangle.lean`](Tangle.lean) — the proofs (the repo's **build oracle**). -- [`lean-toolchain`](lean-toolchain) — the pinned Lean version - (`leanprover/lean4:v4.14.0`). Single source of truth for the toolchain. -- [`bootstrap-lean.sh`](bootstrap-lean.sh) — installs that toolchain. - -## What is proven - -`Tangle.lean` mechanises type safety for the core language, all under Lean's -kernel with **no `sorry`/`axiom`/`admit`** (enforced by CI): - -- **Progress, Preservation, Determinism, Type Safety** — for the let-free - fragment *and* the echo-types fragment. -- **Echo types** (structured loss): `Ty.echo`, `echoClose`/`lower`/`residue`, - with the residue-recovery / non-injectivity capstones. See the - `§ECHO-TYPES` section of `Tangle.lean` and - [`../PROOF-NARRATIVE.md`](../PROOF-NARRATIVE.md) §2.5. -- **Decidability** (TG-2): `infer ≡ HasType`, type uniqueness, and a - `Decidable (HasType [] e τ)` instance. - -## Building / verifying - -```sh -# 1. Install the pinned toolchain (idempotent). -./proofs/bootstrap-lean.sh - -# 2. Put lean on PATH for this shell. -eval "$(./proofs/bootstrap-lean.sh --print-path)" - -# 3. Verify — 0 errors means the proofs check. -cd proofs && lean Tangle.lean -``` - -### Why `bootstrap-lean.sh` exists - -`elan` (the Lean toolchain manager) resolves toolchains from -`release.lean-lang.org`, which is **not on the network allowlist** in -sandboxed environments such as Claude Code on the web. GitHub release assets -*are* reachable, so when the normal install path is blocked the script fetches -the pinned toolchain directly from `github.com`. On an open network (e.g. -GitHub Actions runners) it uses the normal `elan` path. Either way it reads the -version from `lean-toolchain`, so it stays correct when the pin is bumped. - -CI runs the same oracle in [`.github/workflows/lean-proofs.yml`](../.github/workflows/lean-proofs.yml): -`lean Tangle.lean` must report 0 errors and the file must contain no -`sorry`/`axiom`/`admit`/`Admitted` outside comments. diff --git a/proofs/TG3-REFINEMENT.adoc b/proofs/TG3-REFINEMENT.adoc new file mode 100644 index 0000000..33171a4 --- /dev/null +++ b/proofs/TG3-REFINEMENT.adoc @@ -0,0 +1,256 @@ +== TG-3 — OCaml `+typecheck.ml+` refines the Lean `+HasType+` spec + +____ +*Status:* discharged at the _translation-validation_ level (2026-06-14). +Machine-checked half: +link:TG3Differential.lean[`+TG3Differential.lean+`] (496 obligations, +`+by decide+`), generated by +link:../compiler/test/tg3/tg3_emit.ml[`+compiler/test/tg3/tg3_emit.ml+`] +and verified by +link:check-tg3-differential.sh[`+check-tg3-differential.sh+`]. Argument +half: this document. +____ + +=== 1. What TG-3 asks, and how TG-2 reduces it + +TG-3 is the claim that the shipped OCaml type checker +(`+compiler/lib/typecheck.ml+`, `+infer_expr+`) *refines* the mechanised +typing spec (`+proofs/Tangle.lean+`, `+HasType+`): wherever both are +defined, the OCaml checker accepts exactly the Lean-well-typed terms and +assigns the Lean-prescribed type. + +TG-2 already proves, _in Lean_, that the algorithmic inferencer equals +the declarative judgment: + +.... +infer_iff_hasType : infer Γ e = some τ ↔ HasType Γ e τ (Tangle.lean:1588) +.... + +So `+HasType+` and `+infer+` are interchangeable, and TG-3 reduces to a +single cross-language statement: + +____ +*(TG-3′)* OCaml `+infer_expr+` agrees with Lean `+infer+` on the shared +core fragment. +____ + +This is a _translation-validation_ obligation, not a metatheorem about +the OCaml program: we validate agreement term-by-term over a corpus, +backed by a structural argument (§4–5) that explains why the agreement +is not accidental. A universal machine proof would require modelling the +OCaml implementation itself in Lean, which is out of scope (§7). + +=== 2. The shared core fragment + +Lean’s type algebra is +`+Ty = num | str | bool | word n | echo ρ τ | prod α β+` +(`+Tangle.lean:77+`). It has *no `+Tangle[A,B]+` type*. OCaml’s `+ty+` +(`+typecheck.ml:38+`) adds `+TTangle of boundary * boundary+` and a much +larger surface. The fragment on which the two type _languages_ coincide +— call it the *core fragment* — is generated by the constructors + +.... +IntLit · StringLit · BoolLit · Identity · BraidLit(idx ≥ 0) (leaves) +Var · Let (binding) +BinOp(Compose|Tensor|Add|Eq) · Pipeline (word/num/eq algebra) +EchoClose · Lower · Residue · Pair · Fst · Snd · EchoAdd · EchoEq (echo/product) +.... + +each with a 1:1 Lean counterpart +(`+.num .str .boolLit .identity .braidLit .var .lett .compose .tensor .add .eq .pipeline .echoClose .lower .residue .pair .fst .snd .echoAdd .echoEq+`). +`+eq+` is restricted to operands of equal _non-Bool_ type (`+num+`, +`+str+`, or same-width `+word+`); `+bool == bool+` is divergence *D2* +(§6). + +==== Type translation `+T+` + +.... +T(TNum)=num T(TStr)=str T(TBool)=bool T(TWord n)=word n +T(TEcho ρ τ)=echo T(ρ) T(τ) T(TProd α β)=prod T(α) T(β) T(TTangle _)=⊥ (undefined) +.... + +`+T+` is a total bijection between the *core* OCaml types and Lean +`+Ty+`, and is *undefined on every `+TTangle+`* — any OCaml result whose +type tree contains a `+TTangle+` anywhere has no Lean image and is a +divergence by construction. §4 shows core terms never produce such a +type, so `+T+` is total on the core image. + +=== 3. Constructors outside the core (extra-core) + +These have no faithful place in the shared fragment. Each is tagged +*declare-non-core* (intentionally outside the modelled language) or +*model-later* (a candidate for a future spec extension). + +[width="100%",cols="34%,33%,33%",options="header",] +|=== +|OCaml feature |Why outside core |Disposition +|`+close+` |*boundary gateway*: Lean types it `+word 0+`; OCaml lifts +`+Word → Tangle[I,I]+`, leaving `+T+`’s domain. The _only_ core +constructor that escapes. |divergence *D1* (§6) + +|`+TTangle+` layer: `+Cap+`, `+Cup+`, `+Mirror+`, `+Reverse+`, +`+Simplify+`, `+Twist+`, `+Crossing+`, `+Isotopy+`, and the +`+Word↔Tangle+` coercion arms of `+compose+`/`+tensor+` |Lean has zero +`+Tangle+`/category rules |declare-non-core + +|Arithmetic `+Sub+`, `+Mul+`, `+Div+`, unary `+Neg+`, `+Not+` |no Lean +rule (Lean models only `+add+`) |model-later + +|`+FloatLit+` |Lean `+num : Int → Expr+` has no float; both infer +`+Num+` but the term has no faithful Lean image |declare-non-core (Int +covers the Num-literal case) + +|`+Call+`, function `+Definition+`, two-pass program typing, placeholder +`+Word[0]+` params |Lean has only `+let+` + expressions, no definition +layer |model-later + +|`+Match+`/patterns, `+WeaveBlock+`, `+Computation+`, `+Assertion+` +|statement/pattern layer absent from Lean |model-later +|=== + +Because `+close+` is the sole core gateway into `+TTangle+`, every +divergence that the Tangle layer induces on otherwise-core terms is +reachable *only through a `+close+` subterm* — see D1’s family in §6. + +=== 4. Closure of the core under `+infer_expr+` + +____ +*Closure.* For every core term `+e+`, `+infer_expr [] [] e+` either +raises `+Type_error+` or returns a type *whose entire tree is free of +`+TTangle+`* (so in `+{TNum,TStr,TBool,TWord,TEcho,TProd}+` and +recursively so). +____ + +The strengthening "`__entire tree__`" is necessary: a naive "`top-level +type is not `+TTangle+``" IH would not survive +`+Fst+`/`+Snd+`/`+Lower+`/`+Residue+`, which can extract a nested +component — if a `+TTangle+` could hide inside a `+TProd+`/`+TEcho+`, a +projection would surface it. + +_Proof (structural induction on `+e+`; verified by an adversarial +sub-agent panel, 2026-06-14)._ The crux is that *no `+infer_binop+` arm +synthesises a `+TTangle+` from non-`+Tangle+` operands.* In `+Compose+` +(`+typecheck.ml:450+`), `+Tensor+` (`+:489+`) and `+Add+` (`+:507+`), +every `+TTangle+`-producing arm pattern-matches a `+TTangle+` in at +least one operand (the `+Word↔Tangle+` coercion arms `+:463–481+`, the +closed-tangle `+Add+` arm `+:510+`); with both operands `+Tangle+`-free, +only the `+Word,Word→Word+` (resp. `+Num,Num→Num+`) arm or the catch-all +`+type_error+` can fire. `+Eq+` (`+:543+`) only ever yields `+TBool+` or +`+Type_error+`. Hence a `+TTangle+` can enter a core term only if some +core _leaf or constructor_ already returned one — and enumerating the +core constructors’ direct results (literals→`+TNum/TStr/TBool+`, +`+Identity/BraidLit+` →`+TWord+`, `+Var+`→a `+Let+`-bound core type, +`+EchoClose+`→`+TEcho(TWord,TWord 0)+`, +`+EchoAdd+`/`+EchoEq+`→`+TEcho(TProd …)+` over `+Num/Str/Word+`, +`+Pair+`→`+TProd+`, `+Lower/Residue/Fst/Snd+`→a component of an +already-`+Tangle+`-free `+TEcho/TProd+` by the IH) shows none does. +Every `+TTangle+`-producing arm in `+infer_expr+` (`+Close+`, +`+Mirror+`, `+Simplify+`, `+Cap+`, `+Cup+`, `+Twist+`, `+Crossing+`) is +an *excluded* constructor. ∎ + +Consequence: `+T+` is defined on every accepted core term’s type, so +each core term yields a well-formed Lean obligation. + +=== 5. Agreement on the core + +On the core fragment, `+infer_expr+` and `+infer+` compute _the same_ +result under `+T+`, save for D2. The two algorithms are arm-for-arm +identical: braid width (`+width_of_generators+` = `+generatorWidth+`, +both `+foldl max (idx+1) 0+`), `+compose+` = `+max+`, `+tensor+` = +`+++`, `+eq+` requires equal width, the echo/product shapes match the +Lean `+infer+` arms, and `+let+`/`+var+` agree once names are read as de +Bruijn indices. This is corroborated machine-checked over *490 core +terms* (the `+CoreAgreement+` section of `+TG3Differential.lean+`): each +emits `+infer [] e = T(infer_expr e)+` and Lean’s kernel confirms it via +`+by decide+`. The corpus exercises width arithmetic over all word +pairs, the echo/product introductions and eliminations (incl. nested +projections), `+let+`-shadowing (the de Bruijn hazard), same- and +different-width `+eq+` (accept _and_ reject), and ill-typed terms +(reject-agreement). + +=== 6. Divergence catalogue + +Exactly two root causes; both confirmed by hand-trace and pinned in the +`+Divergences+` section of `+TG3Differential.lean+` (Lean side) and by +`+tg3_emit --check+` (OCaml side). + +[width="100%",cols="14%,20%,23%,20%,23%",options="header",] +|=== +|ID |term |OCaml |Lean |class +|*D1* |`+close(braid[s0])+` |`+Tangle[I,I]+` |`+word 0+` |type-mismatch + +|*D1b* |`+pipeline(close,close)+` |`+Tangle[I,I]+` |`+word 0+` +|type-mismatch + +|*D1c* |`+compose(braid[s0], close …)+` |*reject* |`+word 1+` +|accept/reject + +|*D1c′* |`+compose(close …, braid[s0])+` |*reject* |`+word 1+` +|accept/reject + +|*D1d* |`+add(close, close)+` |`+Tangle[I,I]+` |*reject* (`+none+`) +|accept/reject + +|*D2* |`+true == false+` |`+Bool+` |*reject* (`+none+`) |accept/reject +|=== + +* *D1 family* — root cause: `+close+`. OCaml lifts a closed braid into +the Tangle category (`+Tangle[I,I]+`); Lean keeps it in `+Word+` +(`+word 0+`, rule `+tCloseWord+`). Because OCaml’s `+close+`-result is a +`+TTangle+`, feeding it into `+pipeline+`, `+compose+`/`+tensor+` or +`+add+` either propagates the Tangle (D1, D1b, D1d) or trips OCaml’s +boundary-width guard so OCaml _rejects_ a term Lean accepts (D1c/D1c′). +All six involve a `+close+` subterm, hence all lie *outside* the core +fragment. +* *D2* — `+bool == bool+`. OCaml’s `+Eq+` has an explicit +`+TBool,TBool→TBool+` arm (`+typecheck.ml:550+`); Lean’s `+eq+` has no +bool case (`+tEqWord/Num/Str+` only), so `+infer+` returns `+none+`. +Retained in OCaml as an extra-core convenience used by +`+examples/braids_as_data.tangle+`; documented, kept out of the core +corpus. + +Neither divergence is an unsoundness _within_ either system — each is +internally consistent (Lean’s `+infer_sound+`/`+infer_complete+`; +OCaml’s checker is self-consistent). They are gaps in the _refinement_ +relation, arising precisely because Lean lacks a `+Tangle+` type and a +bool-eq rule. + +=== 7. What this establishes, and what it does not + +*Establishes.* On the core fragment, OCaml `+infer_expr+` provably +refines the Lean spec: closed under inference (§4), arm-for-arm equal to +the proven `+infer+` (§5), with the _complete_ divergence set catalogued +and machine-pinned (§6). 496 Lean kernel-checked obligations witness it; +1008 OCaml `+--check+` assertions pin the OCaml side and the de Bruijn +translation. + +*Does not.* This is translation validation over a finite (if broad) +corpus plus a structural argument — not a single Lean theorem +quantifying over all OCaml runs, which would require reflecting +`+typecheck.ml+` into Lean. The extra-core features (§3) are excluded, +not modelled. Refinement is the OCaml→Lean direction only: Lean can form +terms with no OCaml pre-image (e.g. `+echoVal+` over heterogeneous +components, or `+lower+`/`+residue+` off them) — OCaml’s `+TEcho+` is +confined to the three shapes `+(word n, word 0)+`, +`+(prod num num, num)+`, `+(prod ρ ρ, bool)+` — but completeness of +OCaml _against_ Lean is not part of refinement and is not claimed. + +=== 8. Reproducing + +[source,sh] +---- +# OCaml side (no Lean needed) — invariants, curated pins, de Bruijn, divergences: +cd compiler && dune runtest # runs tg3_emit --check (1008 assertions) + +# regenerate the obligation file from the OCaml checker: +cd compiler && dune exec ./test/tg3/tg3_emit.exe -- --emit ../proofs/TG3Differential.lean + +# machine-checked half — Lean kernel verifies OCaml ≡ Lean on the corpus: +./proofs/check-tg3-differential.sh # builds olean, checks 496 obligations +---- + +Representational contract honoured by the emitter: OCaml +`+Let(name,…)+`/`+Var name+` → Lean de Bruijn `+lett+`/`+var k+` with +shadowing (`+typecheck.ml+` named scope ↔ `+Tangle.lean+` indices); +braid indices are non-negative (Lean `+idx : Nat+`); the corpus is +closed (`+Var+` only under its binder). diff --git a/proofs/TG3-REFINEMENT.md b/proofs/TG3-REFINEMENT.md deleted file mode 100644 index 0ce4bdd..0000000 --- a/proofs/TG3-REFINEMENT.md +++ /dev/null @@ -1,201 +0,0 @@ - -# TG-3 — OCaml `typecheck.ml` refines the Lean `HasType` spec - -> **Status:** discharged at the *translation-validation* level (2026-06-14). -> Machine-checked half: [`TG3Differential.lean`](TG3Differential.lean) (496 -> obligations, `by decide`), generated by -> [`compiler/test/tg3/tg3_emit.ml`](../compiler/test/tg3/tg3_emit.ml) and -> verified by [`check-tg3-differential.sh`](check-tg3-differential.sh). -> Argument half: this document. - -## 1. What TG-3 asks, and how TG-2 reduces it - -TG-3 is the claim that the shipped OCaml type checker (`compiler/lib/typecheck.ml`, -`infer_expr`) **refines** the mechanised typing spec (`proofs/Tangle.lean`, -`HasType`): wherever both are defined, the OCaml checker accepts exactly the -Lean-well-typed terms and assigns the Lean-prescribed type. - -TG-2 already proves, *in Lean*, that the algorithmic inferencer equals the -declarative judgment: - -``` -infer_iff_hasType : infer Γ e = some τ ↔ HasType Γ e τ (Tangle.lean:1588) -``` - -So `HasType` and `infer` are interchangeable, and TG-3 reduces to a single -cross-language statement: - -> **(TG-3′)** OCaml `infer_expr` agrees with Lean `infer` on the shared core -> fragment. - -This is a *translation-validation* obligation, not a metatheorem about the OCaml -program: we validate agreement term-by-term over a corpus, backed by a structural -argument (§4–5) that explains why the agreement is not accidental. A universal -machine proof would require modelling the OCaml implementation itself in Lean, -which is out of scope (§7). - -## 2. The shared core fragment - -Lean's type algebra is `Ty = num | str | bool | word n | echo ρ τ | prod α β` -(`Tangle.lean:77`). It has **no `Tangle[A,B]` type**. OCaml's `ty` -(`typecheck.ml:38`) adds `TTangle of boundary * boundary` and a much larger -surface. The fragment on which the two type *languages* coincide — call it the -**core fragment** — is generated by the constructors - -``` -IntLit · StringLit · BoolLit · Identity · BraidLit(idx ≥ 0) (leaves) -Var · Let (binding) -BinOp(Compose|Tensor|Add|Eq) · Pipeline (word/num/eq algebra) -EchoClose · Lower · Residue · Pair · Fst · Snd · EchoAdd · EchoEq (echo/product) -``` - -each with a 1:1 Lean counterpart (`.num .str .boolLit .identity .braidLit .var -.lett .compose .tensor .add .eq .pipeline .echoClose .lower .residue .pair .fst -.snd .echoAdd .echoEq`). `eq` is restricted to operands of equal *non-Bool* type -(`num`, `str`, or same-width `word`); `bool == bool` is divergence **D2** (§6). - -### Type translation `T` - -``` -T(TNum)=num T(TStr)=str T(TBool)=bool T(TWord n)=word n -T(TEcho ρ τ)=echo T(ρ) T(τ) T(TProd α β)=prod T(α) T(β) T(TTangle _)=⊥ (undefined) -``` - -`T` is a total bijection between the **core** OCaml types and Lean `Ty`, and is -**undefined on every `TTangle`** — any OCaml result whose type tree contains a -`TTangle` anywhere has no Lean image and is a divergence by construction. §4 shows -core terms never produce such a type, so `T` is total on the core image. - -## 3. Constructors outside the core (extra-core) - -These have no faithful place in the shared fragment. Each is tagged -**declare-non-core** (intentionally outside the modelled language) or -**model-later** (a candidate for a future spec extension). - -| OCaml feature | Why outside core | Disposition | -|---|---|---| -| `close` | **boundary gateway**: Lean types it `word 0`; OCaml lifts `Word → Tangle[I,I]`, leaving `T`'s domain. The *only* core constructor that escapes. | divergence **D1** (§6) | -| `TTangle` layer: `Cap`, `Cup`, `Mirror`, `Reverse`, `Simplify`, `Twist`, `Crossing`, `Isotopy`, and the `Word↔Tangle` coercion arms of `compose`/`tensor` | Lean has zero `Tangle`/category rules | declare-non-core | -| Arithmetic `Sub`, `Mul`, `Div`, unary `Neg`, `Not` | no Lean rule (Lean models only `add`) | model-later | -| `FloatLit` | Lean `num : Int → Expr` has no float; both infer `Num` but the term has no faithful Lean image | declare-non-core (Int covers the Num-literal case) | -| `Call`, function `Definition`, two-pass program typing, placeholder `Word[0]` params | Lean has only `let` + expressions, no definition layer | model-later | -| `Match`/patterns, `WeaveBlock`, `Computation`, `Assertion` | statement/pattern layer absent from Lean | model-later | - -Because `close` is the sole core gateway into `TTangle`, every divergence that the -Tangle layer induces on otherwise-core terms is reachable **only through a `close` -subterm** — see D1's family in §6. - -## 4. Closure of the core under `infer_expr` - -> **Closure.** For every core term `e`, `infer_expr [] [] e` either raises -> `Type_error` or returns a type **whose entire tree is free of `TTangle`** (so in -> `{TNum,TStr,TBool,TWord,TEcho,TProd}` and recursively so). - -The strengthening "*entire tree*" is necessary: a naive "top-level type is not -`TTangle`" IH would not survive `Fst`/`Snd`/`Lower`/`Residue`, which can extract a -nested component — if a `TTangle` could hide inside a `TProd`/`TEcho`, a projection -would surface it. - -*Proof (structural induction on `e`; verified by an adversarial sub-agent panel, -2026-06-14).* The crux is that **no `infer_binop` arm synthesises a `TTangle` from -non-`Tangle` operands.** In `Compose` (`typecheck.ml:450`), `Tensor` (`:489`) and -`Add` (`:507`), every `TTangle`-producing arm pattern-matches a `TTangle` in at -least one operand (the `Word↔Tangle` coercion arms `:463–481`, the closed-tangle -`Add` arm `:510`); with both operands `Tangle`-free, only the `Word,Word→Word` -(resp. `Num,Num→Num`) arm or the catch-all `type_error` can fire. `Eq` (`:543`) -only ever yields `TBool` or `Type_error`. Hence a `TTangle` can enter a core term -only if some core *leaf or constructor* already returned one — and enumerating the -core constructors' direct results (literals→`TNum/TStr/TBool`, `Identity/BraidLit` -→`TWord`, `Var`→a `Let`-bound core type, `EchoClose`→`TEcho(TWord,TWord 0)`, -`EchoAdd`/`EchoEq`→`TEcho(TProd …)` over `Num/Str/Word`, `Pair`→`TProd`, -`Lower/Residue/Fst/Snd`→a component of an already-`Tangle`-free `TEcho/TProd` by -the IH) shows none does. Every `TTangle`-producing arm in `infer_expr` (`Close`, -`Mirror`, `Simplify`, `Cap`, `Cup`, `Twist`, `Crossing`) is an **excluded** -constructor. ∎ - -Consequence: `T` is defined on every accepted core term's type, so each core term -yields a well-formed Lean obligation. - -## 5. Agreement on the core - -On the core fragment, `infer_expr` and `infer` compute *the same* result under -`T`, save for D2. The two algorithms are arm-for-arm identical: braid width -(`width_of_generators` = `generatorWidth`, both `foldl max (idx+1) 0`), `compose` -= `max`, `tensor` = `+`, `eq` requires equal width, the echo/product shapes match -the Lean `infer` arms, and `let`/`var` agree once names are read as de Bruijn -indices. This is corroborated machine-checked over **490 core terms** (the -`CoreAgreement` section of `TG3Differential.lean`): each emits -`infer [] e = T(infer_expr e)` and Lean's kernel confirms it via `by decide`. -The corpus exercises width arithmetic over all word pairs, the echo/product -introductions and eliminations (incl. nested projections), `let`-shadowing (the -de Bruijn hazard), same- and different-width `eq` (accept *and* reject), and -ill-typed terms (reject-agreement). - -## 6. Divergence catalogue - -Exactly two root causes; both confirmed by hand-trace and pinned in the -`Divergences` section of `TG3Differential.lean` (Lean side) and by -`tg3_emit --check` (OCaml side). - -| ID | term | OCaml | Lean | class | -|----|------|-------|------|-------| -| **D1** | `close(braid[s0])` | `Tangle[I,I]` | `word 0` | type-mismatch | -| **D1b** | `pipeline(close,close)` | `Tangle[I,I]` | `word 0` | type-mismatch | -| **D1c** | `compose(braid[s0], close …)` | **reject** | `word 1` | accept/reject | -| **D1c′**| `compose(close …, braid[s0])` | **reject** | `word 1` | accept/reject | -| **D1d** | `add(close, close)` | `Tangle[I,I]` | **reject** (`none`) | accept/reject | -| **D2** | `true == false` | `Bool` | **reject** (`none`) | accept/reject | - -* **D1 family** — root cause: `close`. OCaml lifts a closed braid into the Tangle - category (`Tangle[I,I]`); Lean keeps it in `Word` (`word 0`, rule `tCloseWord`). - Because OCaml's `close`-result is a `TTangle`, feeding it into `pipeline`, - `compose`/`tensor` or `add` either propagates the Tangle (D1, D1b, D1d) or trips - OCaml's boundary-width guard so OCaml *rejects* a term Lean accepts (D1c/D1c′). - All six involve a `close` subterm, hence all lie **outside** the core fragment. -* **D2** — `bool == bool`. OCaml's `Eq` has an explicit `TBool,TBool→TBool` arm - (`typecheck.ml:550`); Lean's `eq` has no bool case (`tEqWord/Num/Str` only), so - `infer` returns `none`. Retained in OCaml as an extra-core convenience used by - `examples/braids_as_data.tangle`; documented, kept out of the core corpus. - -Neither divergence is an unsoundness *within* either system — each is internally -consistent (Lean's `infer_sound`/`infer_complete`; OCaml's checker is -self-consistent). They are gaps in the *refinement* relation, arising precisely -because Lean lacks a `Tangle` type and a bool-eq rule. - -## 7. What this establishes, and what it does not - -**Establishes.** On the core fragment, OCaml `infer_expr` provably refines the -Lean spec: closed under inference (§4), arm-for-arm equal to the proven `infer` -(§5), with the *complete* divergence set catalogued and machine-pinned (§6). 496 -Lean kernel-checked obligations witness it; 1008 OCaml `--check` assertions pin the -OCaml side and the de Bruijn translation. - -**Does not.** This is translation validation over a finite (if broad) corpus plus -a structural argument — not a single Lean theorem quantifying over all OCaml runs, -which would require reflecting `typecheck.ml` into Lean. The extra-core features -(§3) are excluded, not modelled. Refinement is the OCaml→Lean direction only: Lean -can form terms with no OCaml pre-image (e.g. `echoVal` over heterogeneous -components, or `lower`/`residue` off them) — OCaml's `TEcho` is confined to the -three shapes `(word n, word 0)`, `(prod num num, num)`, `(prod ρ ρ, bool)` — but -completeness of OCaml *against* Lean is not part of refinement and is not claimed. - -## 8. Reproducing - -```sh -# OCaml side (no Lean needed) — invariants, curated pins, de Bruijn, divergences: -cd compiler && dune runtest # runs tg3_emit --check (1008 assertions) - -# regenerate the obligation file from the OCaml checker: -cd compiler && dune exec ./test/tg3/tg3_emit.exe -- --emit ../proofs/TG3Differential.lean - -# machine-checked half — Lean kernel verifies OCaml ≡ Lean on the corpus: -./proofs/check-tg3-differential.sh # builds olean, checks 496 obligations -``` - -Representational contract honoured by the emitter: OCaml `Let(name,…)`/`Var name` -→ Lean de Bruijn `lett`/`var k` with shadowing (`typecheck.ml` named scope ↔ -`Tangle.lean` indices); braid indices are non-negative (Lean `idx : Nat`); -the corpus is closed (`Var` only under its binder).