Skip to content

Commit 01512e7

Browse files
feat(types,docs): Echo types in type checker + comprehensive documentation pass (#55)
Add Type::Echo / Type::EchoR structured-loss formers (distinct from carrier T; ghost-erased at runtime) to compiler/bet-core; lower + structurally unify them in compiler/bet-check (27 tests pass); Ty.echo / Ty.echoR formers in proofs/BetLang.lean (machine-checked via Lean 4 lake build, Progress/Preservation unaffected); echo-types entry in spec/SPEC.core.scm + grammar note; docs/echo-types.adoc design doc. Documentation pass: new EXPLAINME.adoc guided tour; README.adoc/README.md refresh; .machine_readable/6a2 STATE/META/ECOSYSTEM/AGENTIC (milestones, ADRs, ecosystem, agent protocol); betlang-specific contractiles (Mustfile/Dustfile/README). Echo operations (echo_intro, echo_to_residue, sample_echo, etc.) remain RESERVED/deferred.
1 parent bd4a599 commit 01512e7

16 files changed

Lines changed: 1060 additions & 624 deletions

File tree

.machine_readable/6a2/AGENTIC.a2ml

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#
44
# AGENTIC.a2ml — AI agent constraints and capabilities
55
[metadata]
6-
version = "0.1.0"
7-
last-updated = "2026-04-11"
6+
version = "1.1"
7+
last-updated = "2026-06-02"
88

99
[agent-permissions]
1010
can-edit-source = true
@@ -15,11 +15,30 @@ can-create-files = true
1515

1616
[agent-constraints]
1717
# What AI agents must NOT do:
18-
# - Never use banned language patterns (believe_me, unsafeCoerce, etc.)
18+
# - Never use banned language patterns in Lean: sorry, admit, Admitted, postulate, believe_me, assert_total, unsafeCoerce
19+
# - `axiom` is NOT banned — it is used for classified obligations (see docs/proof-debt.adoc)
1920
# - Never commit secrets or credentials
20-
# - Never use banned languages (TypeScript, Python, Go, etc.)
21+
# - Never use banned languages (TypeScript outside playground, Python, Go, Java, Kotlin, Swift, Node.js, npm)
2122
# - Never place state files in repository root (must be in .machine_readable/)
2223
# - Never use AGPL license (use MPL-2.0)
24+
# - PROOF-NEEDS.md is a stub — do not overwrite it; its intentional format is preserved
25+
# - Echo canonical operation names (echo_intro, echo_to_residue, etc.) are RESERVED — do not implement
26+
# - Echo T is distinct from T; no implicit Echo T → T coercion; unify(Echo T, T) must fail
27+
# - EchoR T operations are fully deferred; do not add runtime payload to Echo T / EchoR T
28+
29+
[agent-entry-protocol]
30+
# On entering a session working on this repo:
31+
# 1. Read .machine_readable/6a2/STATE.a2ml (current phase, blockers, next actions)
32+
# 2. Read .machine_readable/6a2/META.a2ml (ADRs, architecture decisions)
33+
# 3. If touching proofs: read PROOF-NEEDS.md and PROOF-STATUS.md
34+
# 4. If touching echo types: read docs/echo-types.adoc
35+
# 5. If touching governance: read .hypatia-ignore and .governance-allowlist
36+
37+
[agent-exit-protocol]
38+
# On completing a session:
39+
# 1. Update STATE.a2ml with session outcomes (last-updated, milestones completed, next actions)
40+
# 2. Update PROOF-STATUS.md if any proof obligations changed
41+
# 3. Commit documentation and state updates together with code changes
2342

2443
[maintenance-integrity]
2544
fail-closed = true
@@ -28,7 +47,20 @@ allow-silent-skip = false
2847
require-rerun-after-fix = true
2948
release-claim-requires-hard-pass = true
3049

50+
[proof-toolchain]
51+
lean-version = "leanprover/lean4:v4.15.0"
52+
build-command = "lake build"
53+
scan-command = "tools/proof-scan.sh"
54+
banned-patterns = ["sorry", "admit", "Admitted", "postulate", "believe_me", "assert_total", "unsafeCoerce"]
55+
permitted-axioms = ["substTop_preserves_typing # classified, standards#203, docs/proof-debt.adoc"]
56+
3157
[automation-hooks]
32-
# on-enter: Read 0-AI-MANIFEST.a2ml, then STATE.a2ml
58+
# on-enter: Read STATE.a2ml, then META.a2ml
3359
# on-exit: Update STATE.a2ml with session outcomes
3460
# on-commit: Run just validate-rsr
61+
62+
[typescript-policy]
63+
# No new TypeScript files.
64+
# Approved exemption: playground/** (6 .ts files, sandbox only).
65+
# Enforcement: .governance-allowlist + .hypatia-ignore.
66+
# Unblock condition: migrate playground to AffineScript or delete once experiment is settled.

.machine_readable/6a2/ECOSYSTEM.a2ml

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,61 @@
33
#
44
# ECOSYSTEM.a2ml — Betlang ecosystem position
55
[metadata]
6-
version = "1.0"
7-
last-updated = "2026-04-11"
6+
version = "1.1"
7+
last-updated = "2026-06-02"
88

99
[project]
1010
name = "Betlang"
1111
purpose = "Ternary probabilistic programming with Dutch book prevention and gambling harm reduction"
1212
role = "programming-language"
13+
license = "PMPL-1.0 (SPDX: MPL-2.0)"
14+
repo = "https://github.com/hyperpolymath/betlang"
1315

1416
[position-in-ecosystem]
1517
category = "probabilistic-programming"
18+
paradigm = ["functional", "probabilistic", "symbolic"]
19+
core-primitive = "(bet A B C) — ternary stochastic choice"
20+
type-system = "Hindley-Milner + Echo T / EchoR T structured-loss formers"
21+
proof-layer = "Lean 4 (machine-checked Progress + Preservation + monad laws)"
1622

1723
[related-projects]
18-
projects = [
19-
# No related projects recorded
20-
]
24+
# upstream / source-of-truth
25+
[[related-projects.upstream]]
26+
name = "echo-types"
27+
repo = "https://github.com/hyperpolymath/echo-types"
28+
language = "Agda"
29+
role = "Source of truth for Echo types (Echo f y := Σ(x:A), f x ≡ y proof-relevant fibre)"
30+
relationship = "betlang borrows the unary Echo T / EchoR T formers; does NOT implement the dependent fibre"
31+
32+
[[related-projects.upstream]]
33+
name = "EchoTypes.jl"
34+
repo = "https://github.com/hyperpolymath/EchoTypes.jl"
35+
language = "Julia"
36+
role = "Executable finite-domain companion to echo-types"
37+
relationship = "betlang canonical operation names mirror EchoTypes.jl (echo_intro, echo_to_residue, etc.)"
38+
39+
# engineering-position reference
40+
[[related-projects.alignment-target]]
41+
name = "affinescript"
42+
repo = "https://github.com/hyperpolymath/affinescript"
43+
language = "AffineScript / OCaml"
44+
role = "AffineScript compiler — RSR engineering position betlang is aligning toward"
45+
relationship = "betlang proof infrastructure and verification/ layout modelled on affinescript's RSR posture"
46+
47+
[[related-projects.alignment-target]]
48+
name = "affinescriptiser"
49+
repo = "https://github.com/hyperpolymath/affinescriptiser"
50+
language = "AffineScript"
51+
role = "AffineScript tooling"
52+
53+
# ecosystem tools
54+
[[related-projects.tooling]]
55+
name = "palimpsest-license"
56+
repo = "https://github.com/hyperpolymath/palimpsest-license"
57+
role = "PMPL-1.0 license definition (betlang uses PMPL-1.0 / SPDX: MPL-2.0)"
58+
59+
[external-dependencies]
60+
proof-verifier = "Lean 4 (leanprover/lean4:v4.15.0)"
61+
build-tool = "Lake (bundled with Lean 4)"
62+
racket = "8.11 / 8.12 / current"
63+
rust-edition = "2021"

.machine_readable/6a2/META.a2ml

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,67 @@
33
#
44
# META.a2ml — Betlang meta-level information
55
[metadata]
6-
version = "0.1.0"
7-
last-updated = "2026-04-11"
6+
version = "1.1"
7+
last-updated = "2026-06-02"
88

99
[project-info]
10-
license = "MPL-2.0"
10+
license = "PMPL-1.0 (SPDX: MPL-2.0)"
1111
author = "Jonathan D.A. Jewell (hyperpolymath)"
12+
contact = "j.d.a.jewell@open.ac.uk"
1213

1314
[architecture-decisions]
14-
decisions = [
15-
# No ADRs recorded
16-
]
15+
# ADR-001: Ternary core primitive
16+
[[architecture-decisions.records]]
17+
id = "ADR-001"
18+
title = "Ternary (bet A B C) as core primitive, not binary"
19+
status = "accepted"
20+
rationale = "Real-world decisions are three-valued; musical ternary form A-B-A provides compositional structure. Dutch book semantics require three outcomes minimum."
21+
22+
# ADR-002: Lean 4 + Lake for mechanised proofs
23+
[[architecture-decisions.records]]
24+
id = "ADR-002"
25+
title = "Lean 4 / Lake for proofs, pure-core (no Mathlib)"
26+
status = "accepted"
27+
rationale = "Lean 4 provides a buildable, CI-checkable proof project with Lake. Pure-core avoids Mathlib version coupling. Progress + Preservation + monad laws are mechanised; 0 sorry, 1 classified axiom."
28+
29+
# ADR-003: Echo T / EchoR T unary formers, distinct from carrier
30+
[[architecture-decisions.records]]
31+
id = "ADR-003"
32+
title = "Echo T and EchoR T as distinct unary type formers (not subtypes of T)"
33+
status = "accepted"
34+
rationale = "Upstream echo-types Agda repo defines Echo f y := Σ(x:A), f x ≡ y. BetLang is non-dependent; adds unary Echo T / EchoR T. Distinctness (unify(Echo T, T) fails) is the entire point of retained loss. Ghost/erased at runtime until operations demand payload."
35+
reference = "docs/echo-types.adoc, spec/SPEC.core.scm#echo-types"
36+
37+
# ADR-004: AffineScript replaces TypeScript/ReScript for editor tooling
38+
[[architecture-decisions.records]]
39+
id = "ADR-004"
40+
title = "AffineScript (not TypeScript or ReScript) for VS Code extension source"
41+
status = "accepted"
42+
rationale = "Hyperpolymath language policy: no new TypeScript. ReScript was the previous choice (now deleted). AffineScript is the canonical replacement. Playground TypeScript files are an approved time-limited exemption."
43+
reference = ".claude/CLAUDE.md TypeScript Exemptions table"
44+
45+
# ADR-005: Three-PR AffineScript alignment strategy
46+
[[architecture-decisions.records]]
47+
id = "ADR-005"
48+
title = "Separate PRs for proofs infrastructure, governance cleanup, and echo types"
49+
status = "accepted"
50+
rationale = "PR #53 (proofs) + PR #54 (governance) + PR #55 (echo types) kept independent so each is reviewable in isolation. Governance fixes isolated from proof infrastructure so neither blocks the other."
51+
52+
# ADR-006: Echo operation names mirror EchoTypes.jl (reserved/deferred)
53+
[[architecture-decisions.records]]
54+
id = "ADR-006"
55+
title = "Canonical echo operation names are RESERVED cross-repo anchors, not committed semantics"
56+
status = "accepted"
57+
rationale = "echo_intro, echo_to_residue, residue_strictly_loses, echo_input, echo_output mirror EchoTypes.jl for cross-repo conceptual consistency. Not implemented in BetLang yet — no runtime/proof story settled. Error-Lang's stability penalty for echo_to_residue does NOT apply to BetLang."
58+
reference = "docs/echo-types.adoc#deferred"
1759

1860
[development-practices]
1961
versioning = "SemVer"
20-
documentation = "AsciiDoc"
21-
build-tool = "just"
62+
documentation = "AsciiDoc (primary) + Markdown (secondary)"
63+
build-tool = "just (Justfile)"
64+
proof-build = "lake (lakefile.lean)"
65+
ci = "GitHub Actions (SHA-pinned)"
66+
package-management = "Guix (primary) / Nix (fallback) / Deno (JS)"
2267

2368
[maintenance-axes]
2469
scoping-first = true

.machine_readable/6a2/STATE.a2ml

Lines changed: 54 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,78 @@
55
[metadata]
66
project = "betlang"
77
version = "0.8.0-dev"
8-
last-updated = "2026-02-07"
8+
last-updated = "2026-06-02"
99
status = "active"
10-
session = "converted from scheme — 2026-04-11"
10+
session = "affinescript-alignment + governance + echo-types — 2026-06-02"
1111

1212
[project-context]
1313
name = "Betlang"
14-
purpose = """Safe probabilistic programming with Dutch book prevention and gambling harm reduction"""
15-
completion-percentage = 82
14+
purpose = """
15+
Safe probabilistic programming with Dutch book prevention and gambling harm reduction.
16+
Core primitive: (bet A B C) — ternary stochastic choice. Type system adds Echo T / EchoR T
17+
structured-loss formers (proof-relevant, ghost-erased). Proofs machine-checked in Lean 4.
18+
"""
19+
completion-percentage = 87
1620

1721
[position]
18-
phase = "v0.8-julia-backend-development" # design | implementation | testing | maintenance | archived
22+
phase = "proof-foundation + governance-alignment + echo-types-integration"
1923
maturity = "experimental" # experimental | alpha | beta | production | lts
2024

25+
[recent-sessions]
26+
# Session 2026-06-02: AffineScript alignment, governance cleanup, Echo types
27+
# PR #53: Lean 4 proof infrastructure (lakefile, proofs.yml, verification/, PROOF-STATUS.md)
28+
# PR #54: Governance/CI debt — Cargo.toml license, rackunit conflict, timeout-minutes,
29+
# .governance-allowlist, .hypatia-ignore, delete Java, ReScript → AffineScript
30+
# PR #55: Echo T / EchoR T type formers in Rust checker + Lean + spec + docs
31+
2132
[route-to-mvp]
2233
milestones = [
23-
# No milestones recorded
34+
"M1: Proof foundation — lakefile.lean + proofs.yml CI + banned-pattern gate [DONE #53]",
35+
"M2: Governance clean — licence, language policy, Racket tests, timeout [DONE #54]",
36+
"M3: Echo types core — Type::Echo/EchoR, unify, lower, Lean Ty.echo/echoR [DONE #55]",
37+
"M4: Discharge substTop_preserves_typing axiom (PROOF-STATUS TP-4)",
38+
"M5: Echo operations — echo_intro, proj1, echo_to_residue; typing rules",
39+
"M6: sample_echo / bet_echo probabilistic bridge",
40+
"M7: Julia backend Phase 2 — core language features",
2441
]
2542

43+
[proof-obligations]
44+
# See PROOF-STATUS.md for the full register (13 obligations)
45+
proved = ["TP-1 Progress", "TP-2 Preservation", "TP-3 Monad laws"]
46+
axioms = ["substTop_preserves_typing (classified, standards#203, docs/proof-debt.adoc)"]
47+
remaining = 10
48+
2649
[blockers-and-issues]
2750
issues = [
28-
# No blockers recorded
51+
"bet-wasm E0308: pre-existing WASM backend breakage (match arm type mismatch, not caused by any of #53-55)",
52+
"substTop_preserves_typing: classified axiom; discharge is M4 (Phase 2 proofs)",
53+
"Echo operations deferred: no echo_intro/proj1/echo_to_residue until runtime/proof story settled",
2954
]
3055

3156
[critical-next-actions]
3257
actions = [
33-
"Continue Julia backend Step 2: Core language features",
34-
")))
35-
(optional-future-work
36-
((",
37-
")
38-
(",
39-
")
40-
(",
41-
")
42-
(",
43-
")
44-
(",
45-
")
46-
(",
47-
")
48-
(",
58+
"Merge PR #54 → main (all-green)",
59+
"Rebase PR #53 onto updated main, re-CI, merge",
60+
"Retarget PR #55 to main, mark ready, merge",
61+
"Phase 2 proof obligations: discharge substTop_preserves_typing",
62+
"Echo operations pass: introduce echo_intro, echo_to_residue, proj1; typing rules in Lean",
63+
"sample_echo / bet_echo probabilistic bridge (Dist T → Echo T)",
4964
]
5065

66+
[language-policy]
67+
primary = "Racket" # core semantics
68+
proofs = "Lean 4" # mechanised safety proofs
69+
compiler-tooling = "Rust" # bet-core, bet-check, bet-parse, bet-wasm (paused)
70+
editor-tooling = "AffineScript" # replaces TypeScript/ReScript in editors/
71+
compute-backend = "Julia" # numerical/statistical kernel
72+
scripts = "Bash/POSIX shell + Just"
73+
config = "Nickel / 6a2 Scheme (.a2ml)"
74+
banned = ["TypeScript (except playground sandbox)", "Node.js", "npm", "Go", "Python", "Java", "Kotlin", "Swift"]
75+
5176
[maintenance-status]
52-
last-run-utc = "2026-02-07T00:00:00Z"
53-
last-result = "unknown" # unknown | pass | warn | fail
77+
last-run-utc = "2026-06-02T14:00:00Z"
78+
last-result = "pass" # unknown | pass | warn | fail
79+
# Racket tests: pass (current + 8.11 + 8.12 on PR #54)
80+
# Governance: pass (all checks on PR #54)
81+
# Lean proofs: pass (proofs.yml lake build on PR #53)
82+
# Echo types: pass (cargo test -p bet-check: 27 tests pass on PR #55)

0 commit comments

Comments
 (0)