myxo-lang 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CONCURRENCY.md +207 -0
  2. package/HOW_IT_WORKS.md +235 -0
  3. package/INDEPENDENCE.md +24 -0
  4. package/MYXO_PROMPT.md +139 -0
  5. package/README.md +494 -0
  6. package/ROADMAP.md +200 -0
  7. package/SPEC.md +181 -0
  8. package/VISION.md +249 -0
  9. package/builtins.js +361 -0
  10. package/command-fence.js +75 -0
  11. package/errors.js +45 -0
  12. package/examples/agent.myx +31 -0
  13. package/examples/fenced-agent.js +78 -0
  14. package/examples/fib.myx +11 -0
  15. package/examples/fibers.myx +57 -0
  16. package/examples/flow-routing.myx +12 -0
  17. package/examples/geo.myx +12 -0
  18. package/examples/hello.myx +2 -0
  19. package/examples/host.js +30 -0
  20. package/examples/james-myxo-demo.js +60 -0
  21. package/examples/living-mesh.myx +22 -0
  22. package/examples/match.myx +18 -0
  23. package/examples/mathlib.js +8 -0
  24. package/examples/mathlib.pl +11 -0
  25. package/examples/mathlib.py +23 -0
  26. package/examples/mcp-host.js +37 -0
  27. package/examples/nexus-mesh.myx +22 -0
  28. package/examples/nexus.myx +29 -0
  29. package/examples/ouroboros.myx +2 -0
  30. package/examples/outward-gate.myx +23 -0
  31. package/examples/physarum.myx +75 -0
  32. package/examples/polyglot-host.js +17 -0
  33. package/examples/polyglot.myx +11 -0
  34. package/examples/resilient.myx +28 -0
  35. package/examples/scheduler.myx +46 -0
  36. package/examples/the-law.myx +27 -0
  37. package/examples/use-geo.myx +9 -0
  38. package/format.js +206 -0
  39. package/interpreter.js +1092 -0
  40. package/lexer.js +173 -0
  41. package/mcp-bridge.js +77 -0
  42. package/mcp-framing.js +34 -0
  43. package/mcp-server.js +57 -0
  44. package/myxo-concurrent.js +110 -0
  45. package/myxo-live-worker.js +30 -0
  46. package/myxo-live.js +83 -0
  47. package/myxo-lsp.js +226 -0
  48. package/myxo-par-worker.js +39 -0
  49. package/myxo-plan.js +207 -0
  50. package/myxo-run.js +63 -0
  51. package/myxo.js +296 -0
  52. package/package.json +27 -0
  53. package/parser.js +662 -0
  54. package/polyglot-host.js +39 -0
  55. package/polyglot.js +191 -0
  56. package/receipt.js +71 -0
  57. package/std.myx +88 -0
  58. package/tools/memo-fuzz.js +224 -0
package/ROADMAP.md ADDED
@@ -0,0 +1,200 @@
1
+ # Myxo — Road to 1.0
2
+
3
+ > **Mission lock:** Myxo is the safe substrate for AI-generated code — the language a model writes when you can't afford to trust the model. **Not** a Python replacement.
4
+
5
+ Status when this landed: **v1.5.0**, 335 node tests + 11 self-host green, spec at `SPEC.md`.
6
+
7
+ ---
8
+
9
+ ## Arc's sharpening notes (2026-07-01)
10
+
11
+ **Verdict: green light.** This is the most disciplined plan written about Myxo and it is mission-true. Four sharpenings folded into how we execute — the plan text below is preserved verbatim as the source of record.
12
+
13
+ 1. **The two-agent adversarial gate is a STANDING requirement through Phases 2–4, not just "tests."** It has been Myxo's actual quality engine on every stone (it caught the memoization staleness, the value-budget-zero bypass, the warden metering flaw, the `myxo plan` false-cleans — all while green tests passed). Fuzzing (Phase 4) catches crashes; it does **not** catch subtle soundness/semantic bugs. Every language/fence change in Phases 2–3 ships only after cold-reviewer + adversary.
14
+ 2. **Never let a paid model gate the instrument.** Phase 1's frontier tier uses the **Claude API key we already have** (`ANTHROPIC_API_KEY`); the mid/small tier uses **local Ollama** (qwen2.5-coder / phi) — near-zero cost, fully repeatable. The eval harness must never be blocked on a bill.
15
+ 3. **The Week-3 baseline IS the first thesis verdict — read it then, not only at Phase 5.** If a frontier model already writes fenced Python-in-a-sandbox as reliably as Myxo at baseline, that's a yellow flag *before* sinking Phases 2–6. Treat the baseline delta as a leading indicator.
16
+ 4. **Phase 2's breaking-change window closes at Phase 7.** Almost no Myxo exists in the wild yet (examples + 2 dogfood apps), so spending breaks now is nearly free. Once Nexus dogfoods 3 live policies (Week 8), every break costs migration. Land all Phase-2 breaks before Phase-7 policies are written.
17
+
18
+ Phase 1 scaffold lives in `myxo-evals/` (built 2026-07-01; harness runs, seed golden tasks validated — expand to the full 30).
19
+
20
+ ---
21
+
22
+ ## 0. DEFINITION OF DONE
23
+
24
+ Languages are never finished; products are. "100%" means all of the following are true, checkable, and checked:
25
+
26
+ 1. **Spec locked at 2.0** — every breaking change spent, spec frozen, versioned, and small enough to live in a system prompt (≤ ~6K tokens).
27
+ 2. **Eval-proven** — a frontier model with only the spec in context passes ≥ 90% of the golden set; a mid-tier local model (7–14B) passes ≥ 60%. Numbers tracked per release, no regressions shipped.
28
+ 3. **Crash-free guarantee** — no input source text can crash the host process. Fuzzed to exhaustion; every failure is a clean MyxoError.
29
+ 4. **Fence complete** — per-module manifests, polyglot ungrantable-by-default, plan/fence parity documented, threat model written.
30
+ 5. **Nexus runs on it** — at least three real Nexus policies/routines in production Myxo for 30 days without a language-caused incident.
31
+ 6. **Distributed** — installable in one command, repo public, docs complete, the spec-as-prompt file downloadable as a product artifact.
32
+ 7. **Maintenance mode defined** — a written policy for what gets fixed (bugs, security) and what gets refused (features), so 1.0 stays 1.0.
33
+
34
+ Everything below exists to make those seven lines true.
35
+
36
+ ---
37
+
38
+ ## PHASE 1 — THE EVAL HARNESS (build this before touching the language)
39
+ **~2–3 weekends. Nothing else starts until this runs.**
40
+
41
+ The harness is the instrument; without it every later decision is vibes.
42
+
43
+ **Deliverables:**
44
+ - `myxo-evals/` repo directory: `tasks/` (one folder per task: `prompt.md`, `checks.myx` or expected-output file), `run-evals.js` (harness), `results/` (JSONL per run: model, task, pass/fail, error class, tokens).
45
+ - **30 golden tasks** across 6 buckets, 5 each:
46
+ 1. Data shaping (parse/filter/transform lists & meshes)
47
+ 2. Control flow (match, loops, attempt/rescue)
48
+ 3. Agents & closures (recursion, defaults, rest params, pipelines)
49
+ 4. Fence usage (needs manifests, budgets, correct denial handling)
50
+ 5. Concurrency (dispatch/gather, fibers/channels)
51
+ 6. Adversarial (tasks that tempt the footguns: newline gluing, mesh key coercion, identity equality)
52
+ - Harness runs: model + spec-in-context → generated Myxo → executed against checks via `run()` with `maxSteps` fuel → pass/fail + captured error.
53
+ - Baseline run against 3 models (one frontier via OpenRouter, one mid, one local 7B) and — this is the control group — the same 30 tasks in Python. The Python delta IS the product metric.
54
+
55
+ **Acceptance:** one command produces a scoreboard; results are git-committed; the first baseline numbers exist, however ugly.
56
+
57
+ **Why first:** every phase below claims to improve AI-writability. This is the only thing that can prove it.
58
+
59
+ > ### ✅ PHASE 1 COMPLETE (2026-07-02)
60
+ > - **30 golden tasks** (6 buckets × 5), reference set green (`--ref` = 30/30), each two-agent-gated.
61
+ > - **`run-evals.js`** hardened by cold-reviewer + adversary: audit-ledger scoring for fence tasks (a hardcoded-emit cheat fails), fuel-bounded execution (no infinite-loop hang), construct gate (dead-branch/comment/string-proof), self-test stripping, parse-first error classification, append-with-provenance results. Pinned by `test/evals.test.js` (18 regressions); full suite **371 node + 11 self-host green**.
62
+ > - **Generators:** `ollama.js` (free), `claude.js` (frontier, wired via the claude-api skill).
63
+ > - **Python control group** (`run-control.js` + 20 `control/` triples) for the Myxo-vs-Python delta; fence/concurrency correctly excluded (no fair plain-Python control — that's the moat).
64
+ > - **First baselines** in [`myxo-evals/BASELINE.md`](../myxo-evals/BASELINE.md). Headline: `qwen2.5-coder:7b` scores **0/30 on Myxo** (writes C-style syntax) while writing Python fine — a leading indicator that the mid-tier needs Phase 5's prompt-optimized `MYXO_PROMPT`. Frontier tier is **blocked on Anthropic API credits** (wired + proven-reachable, key balance empty).
65
+
66
+ ---
67
+
68
+ ## PHASE 2 — SPEND THE BREAKING CHANGES (language hardening)
69
+ **~3–4 weekends. The last time the language is allowed to change shape.**
70
+
71
+ Fix everything that the adversarial bucket and first baseline expose, plus the known footguns. Candidates, decided BY EVAL DATA, not taste:
72
+
73
+ - **Newline gluing** (`x` ⏎ `-3` → `x - 3`): adopt a restriction rule — a line starting with `(`, `[`, or unary `-` does not continue the previous statement unless the previous line is syntactically incomplete. Measure re-run of adversarial bucket before/after.
74
+ - **Mesh literal keys:** require quoted strings or `[expr]` computed-key syntax; make bare `{ a: 1 }` mean the literal key `"a"` (the JS convention every model already knows). The current pathway-value-as-key behavior is a model trap precisely because it defies the corpus prior.
75
+ - **Numeric key round-trip:** document loudly or fix; pick one, spec it.
76
+ - **Equality:** keep identity semantics but add a `same(a, b)` deep-equality builtin so models stop reaching for `==` on lists (they will — the corpus taught them Python).
77
+ - Anything else the adversarial evals surface with ≥ 2 model failures.
78
+
79
+ **Rule for this phase:** every change ships with (a) spec diff, (b) eval re-run showing improvement or neutrality, (c) migration note. Anything that grows the spec meaningfully must buy its tokens with eval points.
80
+
81
+ **Acceptance:** adversarial bucket pass rate ≥ 80% frontier; spec still ≤ 6K tokens; CHANGELOG documents every break.
82
+
83
+ ---
84
+
85
+ ## PHASE 3 — FENCE COMPLETION (the moat, finished)
86
+ **~2–3 weekends. This is the product's reason to exist; it gets full rigor.**
87
+
88
+ - **Per-module manifests:** a weaved strand's `needs` no longer merges program-wide. A strand gets only what it declares AND the weaving script re-grants: `weave "x.myx" granting lookup, notify`. Undeclared+ungranted = denied at the strand's call sites. This closes the widening hole in §6/§7 of the spec.
89
+ - **Polyglot lockdown:** `pyeval/jscall/sh/...` become `unsafe`-classed natives — hosts must pass `allowUnsafe: true` AND the script must declare them AND `myxo plan` flags them in red. Default embed cannot grant them. Document plainly: an unsafe grant nullifies the fence.
90
+ - **Budget completeness:** add call-rate budgets (`needs notify(per_run 10)`) alongside value budgets; audit ledger gains a monotonic sequence number and wall-clock timestamps (forensics-grade).
91
+ - **Threat model document** (`SECURITY.md`): what the fence guarantees, what it explicitly does not (inside-a-native behavior, side channels, plan unsoundness), the injection scenario walked end-to-end (untrusted text → model → Myxo → fence catches the exfil attempt). This document is also marketing — it's the honest artifact competitors won't write.
92
+ - **Fence test suite:** 40+ tests, every denial path, every budget edge (negative, NaN, boundary), manifest/grant matrix, module re-grant matrix.
93
+
94
+ **Acceptance:** fence tests green; a written attack scenario per fence feature with its test; `SECURITY.md` reviewed against Vol 1 §14 trifecta (private data / untrusted input / exfil channel — show which leg the fence breaks).
95
+
96
+ ---
97
+
98
+ ## PHASE 4 — RUNTIME ROBUSTNESS (crash-free, bounded, measured)
99
+ **~2–3 weekends.**
100
+
101
+ - **Fuzzing:** grammar-aware fuzzer (generate from the AST shapes) + mutation fuzzer over the corpus of all eval tasks and tests. Target: 1M+ inputs, zero host crashes, zero hangs (fuel + timeout enforced everywhere, including inside `gather` workers and fibers). Every crash found becomes a regression test.
102
+ - **Resource guarantees, spec'd:** maxDepth, maxSteps, gather timeout, fiber step budget, and (new) a memory ceiling per run — documented numbers, tested at the boundary.
103
+ - **Performance baseline:** a small benchmark suite (parse speed, interp ops/sec, gather scaling across cores, memoization hit behavior). Not to win benchmarks — to detect regressions and to state honest numbers in docs. Tree-walker speed is fine for the niche; say so plainly rather than promising otherwise.
104
+ - **Determinism audit:** enumerate every source of nondeterminism (random, timing in route/schedule, gather ordering guarantees) in one doc section. AI-generated code gets retried and diffed; knowing exactly what's deterministic is a feature.
105
+
106
+ **Acceptance:** fuzz campaign report committed; zero known crash inputs; benchmark suite runs in CI (plain git hook is fine); determinism section merged into spec.
107
+
108
+ ---
109
+
110
+ ## PHASE 5 — AI ERGONOMICS (tune the language like a model)
111
+ **~2–3 weekends. This is where the strategy becomes visible.**
112
+
113
+ - **Errors as retry-fuel:** rewrite every MyxoError to the tool-error standard — what was wrong, where, what valid looks like. `"mesh key must be a string: got number 1 at line 4 — write { \"1\": ... } or [expr]: ..."`. Then MEASURE it: eval harness adds a retry loop (model sees error, gets one fix attempt); track first-try vs post-retry pass rate. Error quality now has a number.
114
+ - **The spec-as-prompt artifact:** `MYXO_PROMPT.md` — the spec distilled for a context window: grammar, semantics, fence rules, 10 canonical examples, the 5 traps. This file is a first-class product deliverable, versioned with the language. Test it: eval runs use ONLY this file, not the full spec.
115
+ - **Canonical corpus:** 50 idiomatic Myxo programs (the eval solutions, cleaned + annotated). Serves as few-shot material, documentation examples, and — if Myxo ever earns fine-tuning — the seed dataset.
116
+ - **`nx fix` (stretch):** feed a failed run's source + error to a model with MYXO_PROMPT and apply the patch. Dogfoods the whole thesis in one command.
117
+
118
+ **Acceptance:** post-retry pass rate ≥ 95% frontier / ≥ 75% mid-tier on golden set; MYXO_PROMPT ≤ 6K tokens and passes evals standalone.
119
+
120
+ ---
121
+
122
+ ## PHASE 6 — CONCURRENCY: FINISH OR CUT (decide, don't drift)
123
+ **~2 weekends if finishing the short list; 1 evening if cutting.**
124
+
125
+ The spec's §17 lists designed-but-unbuilt items. 1.0 discipline: each one gets built or moved to a "post-1.0, maybe never" list — nothing stays "coming."
126
+
127
+ - **Build (recommended):** channel `select` with timeout, closeable channels. These complete the fiber story to minimally-useful; agent code genuinely needs timeout-or-value.
128
+ - **Cut (recommended):** suspension across called-agent boundaries, worker pools, inter-task channels. Real engineering cost, marginal for the niche; the current clean errors already say "not supported" honestly.
129
+
130
+ **Acceptance:** §17 is empty or renamed "Out of scope (final)"; whatever shipped has fence-grade tests.
131
+
132
+ ---
133
+
134
+ ## PHASE 7 — NEXUS INTEGRATION (dogfood or die)
135
+ **Runs in parallel from Phase 3 onward; 30-day soak before 1.0.**
136
+
137
+ - Port three real Nexus behaviors to Myxo: (1) an intent-routing policy, (2) an EOD data-shaping pipeline, (3) one fenced tool-calling routine with budgets (the spend cap demo is the flagship — `needs spend(max 5, total 15)` guarding a real action is the whole pitch in one line).
138
+ - Nexus embeds via `myxo-run.js` allowlist host; every audit ledger flows into Nexus's SQLite log.
139
+ - Keep a friction journal: every time writing real Myxo annoys you or a model, it's an issue. The journal drains into Phases 2/5 while they're still open.
140
+
141
+ **Acceptance:** 30 consecutive days, three policies live, zero language-caused incidents, friction journal empty or deferred-with-reasons.
142
+
143
+ ---
144
+
145
+ ## PHASE 8 — SPEC 2.0 + DOCS (the freeze)
146
+ **~2 weekends.**
147
+
148
+ - **Spec 2.0:** current spec + all Phase 2–6 changes, re-edited to the same honest voice, token-counted, frozen. Semver from here: 2.x additive only, breaking = 3.0 = probably never.
149
+ - **Docs site (single static page is fine):** the pitch (safe substrate thesis + SECURITY.md), 15-minute tutorial, the spec, MYXO_PROMPT download, the eval scoreboard (public numbers — your credibility artifact), embed guide.
150
+ - **README rewrite** around the mission sentence, with the spend-cap demo above the fold.
151
+
152
+ **Acceptance:** a stranger can go from zero → embedded fenced script in 15 minutes using only the docs; every claim in the docs traces to a test or an eval number.
153
+
154
+ ---
155
+
156
+ ## PHASE 9 — SHIP
157
+ **1 weekend.**
158
+
159
+ - npm publish (`myxo` or nearest available name — check now, squat early), GitHub public with license (MIT recommended for adoption; the moat is the eval-driven design process and your velocity, not the code).
160
+ - Launch posts where the actual audience lives: r/LocalLLaMA (the fence + local-model eval numbers ARE the hook), Hacker News (Show HN), lobste.rs. Lead with the scoreboard and the spend-cap demo, not the language tour.
161
+ - 1.0 tag = the Definition of Done checklist, checked, in the release notes.
162
+
163
+ ---
164
+
165
+ ## PHASE 10 — MAINTENANCE MODE (staying finished)
166
+ **Written policy, ~1 evening.**
167
+
168
+ - Fixed: crashes, fence bypasses, spec/implementation divergence, eval regressions.
169
+ - Considered: additive stdlib natives that don't grow MYXO_PROMPT.
170
+ - Refused by default: syntax, semantics, new paradigms. The spec being frozen IS the feature.
171
+ - Cadence: issues triaged weekly (30 min), patch releases as needed, eval suite re-run against new frontier models quarterly (free marketing when numbers improve without you touching anything).
172
+
173
+ ---
174
+
175
+ ## TIMELINE (honest, at real availability)
176
+
177
+ Assuming ~8–10 focused hours/week alongside the stores, Nexus, and the SaaS:
178
+
179
+ | Phase | Elapsed |
180
+ |---|---|
181
+ | 1 Eval harness | Weeks 1–3 |
182
+ | 2 Breaking changes | Weeks 4–7 |
183
+ | 3 Fence completion | Weeks 8–10 |
184
+ | 4 Robustness | Weeks 11–13 |
185
+ | 5 AI ergonomics | Weeks 14–16 |
186
+ | 6 Concurrency decide | Week 17 |
187
+ | 7 Nexus soak | Weeks 8–20 (parallel) |
188
+ | 8 Spec 2.0 + docs | Weeks 18–20 |
189
+ | 9 Ship | Week 21 |
190
+
191
+ **~5 months to 1.0.** Double it if the SaaS takes priority (it should when they conflict — see kill criteria). Git-from-minute-one, one phase per branch, no phase merges without its acceptance line checked.
192
+
193
+ ---
194
+
195
+ ## RISKS & KILL CRITERIA (pre-committed, so future-you doesn't negotiate)
196
+
197
+ - **Eval delta never materializes:** if after Phase 5 a frontier model writes fenced Python-in-a-sandbox as reliably as Myxo for the same tasks, the thesis is weaker than believed → finish Phase 7 only (Myxo stays as Nexus's policy DSL, a fine outcome) and skip 8–9. Decision point: end of Phase 5, by the numbers.
198
+ - **Time competition:** the vendor SaaS is the wealth vehicle; Myxo is leverage and craft. Any week both need the same hours, SaaS wins. Myxo phases are sized to survive interruption (each phase is independently valuable and git-frozen).
199
+ - **Scope creep:** the spec token budget is the tripwire. MYXO_PROMPT > 6K tokens = stop, cut, reassess. Small is the strategy; the moment it isn't small, there is no strategy.
200
+ - **Solo-maintainer risk:** mitigated by maintenance mode's refusal posture and the frozen spec — a finished small language needs hours per month, not per week.
package/SPEC.md ADDED
@@ -0,0 +1,181 @@
1
+ # Myxo Language Specification (v1.5)
2
+
3
+ The precise, honest reference for Myxo. Where this spec and the implementation disagree, that is a bug in one of them — file it. Scope notes mark, in plain language, what Myxo does **not** do, so nothing here oversells.
4
+
5
+ Myxo is a small, embeddable, dynamically-typed language whose runtime *is* the Nexus law: useful pathways reinforce, useless ones decay. Reference implementation: a zero-dependency tree-walking interpreter in Node (`C:\Users\Milton\myxo\`).
6
+
7
+ ---
8
+
9
+ ## 1. Lexical structure
10
+
11
+ - **Encoding:** UTF-8 source text. **Newlines are insignificant** (whitespace only); statements are not terminated by `;` or newlines — they end where the grammar says they end. ⚠️ Because of this, a line that begins with `(`, `[`, or `-` can glue onto the previous line (`x` ⏎ `-3` parses as `x - 3`; `f` ⏎ `(a)` as `f(a)`).
12
+ - **Comments:** `#` to end of line.
13
+ - **Numbers:** `123`, `1.5`. All numbers are IEEE-754 float64 (no integer type, no bigint — an integer above 2^53 loses precision).
14
+ - **Strings:** `"..."` double-quoted. Escapes: `\n \t \" \\ \{ \}` (an unrecognized escape drops the backslash: `\z` → `z`). **Interpolation:** `"x is {expr}"` — `{...}` holds any expression; `\{` is a literal brace. Nested strings inside interpolations are allowed.
15
+ - **Identifiers:** `[A-Za-z_][A-Za-z0-9_]*`.
16
+ - **Keywords** (reserved): `seed decay emit when otherwise reinforce times for each in agent report attempt rescue fail weave expose as needs live dead void and or not test expect match`.
17
+ - **Operators / punctuation:** `+ - * / % == != > < >= <= = ( ) { } [ ] , : | ...`
18
+ - **Type names** (contextual, only after `:` in an annotation): `number string bool list mesh agent void any` — not globally reserved.
19
+
20
+ ---
21
+
22
+ ## 2. Values & types
23
+
24
+ Eight value kinds: **number**, **string**, **bool** (`live`/`dead`), **void**, **list**, **mesh** (insertion-ordered map; **keys are coerced to strings** — `1` and `"1"` are the same key, and numeric keys don't round-trip as numbers), **agent** (closure), **native** (a host function; appears as an `agent`-kind value to `type`).
25
+
26
+ - `void` is a single value; anything missing or unreported is `void`.
27
+ - **Truthiness** (`truthy`): `void`, `0`, `""`, the empty list `[]`, and the empty mesh `{}` are **dead**; everything else is **live**.
28
+ - **Equality** (`==`): `void` equals only `void`; different kinds are never equal; numbers/strings/bools compare by value; lists/meshes/agents compare by **identity** (not structure). (Structural equality exists only inside `match`/`expect`.)
29
+ - `type(v)` returns one of: `number string bool void list mesh agent`.
30
+
31
+ ---
32
+
33
+ ## 3. Expressions
34
+
35
+ Precedence, lowest → highest:
36
+
37
+ 1. **`|` pipeline** (left-assoc): `x | f` ≡ `f(x)`; `x | f(a)` ≡ `f(x, a)` — the piped value is the **first** argument.
38
+ 2. `or` 3. `and` 4. `== !=` 5. `> < >= <=` 6. `+ -` 7. `* / %` 8. unary `not` / `-` 9. call `f(...)` and index `x[i]` (left-assoc, tightest).
39
+
40
+ - **`and`/`or` return VALUES, not just bools:** `a and b` → `a` if `a` is dead, else `b`; `a or b` → `a` if `a` is live, else `b`. So `x or default` works. Both short-circuit.
41
+ - **Arithmetic** `- * / %` requires two numbers (else error); `/` and `%` by zero is an error. **`+`** adds two numbers, **concatenates if *either* operand is a string** (the other is `stringify`d, so `"x" + 1` → `"x1"`), and **concatenates two lists** (`[1,2] + [3]` → `[1,2,3]`).
42
+ - **Comparison** (`< > <= >=`) is defined for two numbers or two strings; anything else errors. `== !=` is defined for all values.
43
+ - **Indexing** `x[i]`: lists by integer (negative indexes count from the end: `a[0-1]` is the last); strings by integer → a one-character string; meshes by key. Out-of-range list read errors; a missing mesh key reads `void`.
44
+ - **List literal** `[a, b, ...]`, **mesh literal** `{ k: v, ... }` — mesh keys are **expressions** evaluated then **coerced to a string** (so `{ 1: "x" }` and `{ "1": "y" }` collide; a bare `{ a: 1 }` uses the *value* of pathway `a` as the key). Trailing commas allowed.
45
+ - **Agent expression** `agent(params) { body }` — an anonymous closure (see §5).
46
+ - Literals: `live`, `dead`, `void`, numbers, strings.
47
+
48
+ ---
49
+
50
+ ## 4. Statements
51
+
52
+ - **`seed name = expr`** — bind a pathway in the current scope. **`seed name: Type = expr`** — typed (see §11). Destructuring: **`seed [a, ...rest] = expr`** and **`seed { a, b } = expr`** / **`seed { "k": v } = expr`** (§9). Re-seeding rebinds.
53
+ - **`name = expr`** — reassign an existing pathway (errors if unseeded). **`x[i] = expr`** — set a list/mesh slot.
54
+ - **`decay name`** / **`decay x[i]`** — remove a pathway / slot.
55
+ - **`emit a, b, ...`** — print the space-joined `stringify` of the arguments + newline.
56
+ - **`when cond { ... }`** with optional **`otherwise { ... }`** or **`otherwise when ...`** (chained). Each block runs in a fresh child scope.
57
+ - **`reinforce cond { ... }`** — while-loop. **`reinforce N times { ... }`** — repeat N times.
58
+ - **`for each x in iterable { ... }`** — iterate a list (elements), a mesh (keys), or a string (characters).
59
+ - **`agent name(params) { body }`** — declare a named agent (§5). Optional return type: `agent name(params): Type { ... }`.
60
+ - **`report expr`** (or bare `report` → void) — return a value from the enclosing agent; at top level it ends the program with that value.
61
+ - **`attempt { ... } rescue err { ... }`** — run a block; a `fail`/runtime error is caught and bound to `err`, a mesh `{ message, line, value }`. **`fail expr`** raises (a string or any value).
62
+ - **`weave "path" [as alias]`** + **`expose name`** — modules (§7).
63
+ - **`needs ...`** — capability manifest (§6).
64
+ - **`match subject { pattern { ... } ... }`** — pattern matching (§8).
65
+ - **`test "name" { ... }`** + **`expect ...`** — the test runner (§10).
66
+ - Any expression alone is an expression-statement.
67
+
68
+ ---
69
+
70
+ ## 5. Agents (functions)
71
+
72
+ First-class lexical closures. **Parameters:** `name`, `name: Type`, `name = default`, `name: Type = default`, and a final `...rest` (gathers remaining args into a list). Defaults evaluate in call scope and may reference earlier parameters. Arity is checked (too few required / too many without `...rest` → error). `report` returns; falling off the end returns `void`. A recursion-depth guard (default 500) turns runaway recursion into a clean Myxo error; a runaway loop can be bounded by a `maxSteps` fuel option.
73
+
74
+ ---
75
+
76
+ ## 6. The capability fence (the moat)
77
+
78
+ The host grants natives via the embed API; an Myxo script reaches the outside world **only** through them. Enforced at every native call:
79
+
80
+ - **Manifest** — `needs lookup, notify` declares what the script may call. Calling an undeclared capability is **refused even if the host granted it**. With no `needs`, all granted natives are allowed (trusted top-level); a host may set `requireManifest` to demand a manifest first. A `weave`d strand's own `needs` merges into the **one program-wide** manifest — a module can widen the whole script's reach, so weave only trusted strands.
81
+ - **Value budgets** — `needs spend(max 5, total 15)`: `max` caps a single call's numeric first argument; `total` caps cumulative spend. For a non-numeric first argument, `total` counts **calls**. A negative/non-finite numeric budget argument is refused. Only successful calls count toward `total`.
82
+ - **Audit ledger** — every privileged call **and refusal** is recorded `{cap, args, ok, result|error}` and handed to the host (`onAudit`) even when the run fails.
83
+ - A capability denial carries an internal flag so a flow-router (§ below) propagates it rather than treating it as a transient failure.
84
+
85
+ **Honest boundary:** the fence governs *which* native a script may call, *how many times / how much*, and logs it — it does **not** sandbox the code *inside* a granted native (see polyglot, §12). For untrusted callers, grant only narrow, structured natives.
86
+
87
+ ---
88
+
89
+ ## 7. Modules
90
+
91
+ `weave "strand.myx"` loads a file once (cached, cycle-safe), importing its `expose`d names flatly; `weave "strand.myx" as m` namespaces them into a mesh `m["name"]`. Private by default. `weave` is itself fenced: a host that withholds the module loader disables it entirely.
92
+
93
+ ---
94
+
95
+ ## 8. Pattern matching (`match`)
96
+
97
+ `match subject { pattern { block } ... }` runs the first arm whose pattern matches, binding names in a fresh child scope. No arm matches → nothing runs (use `_` for a catch-all). Patterns:
98
+
99
+ - `_` wildcard (binds nothing); a bare `name` binds the whole value; a **literal** (`0`, `"s"`, `live`/`dead`/`void`, negative numbers) matches by structural equality.
100
+ - `[p, ..., ...rest]` — a list of exactly that length (or `>=` with `...rest`); elements matched recursively.
101
+ - `{ "key": pattern, ... }` — a mesh that **has** each key (a subset; extra keys are fine); `{ name }` is shorthand for `{ "name": name }`.
102
+
103
+ Patterns are **linear**: a name may bind at most once per arm (a repeated name is a parse error). The subject is evaluated once.
104
+
105
+ ---
106
+
107
+ ## 9. Pipelines & destructuring
108
+
109
+ - **Pipeline** `x | f` / `x | f(a)` — see §3 precedence. Pure sugar for a call; fully fenced/budgeted/audited/memoized like any call.
110
+ - **Destructuring** `seed PATTERN = expr` reuses the §8 patterns. A non-match is an error (no partial binding). Bindings are linear. Type-safe (a string does not match a list pattern).
111
+
112
+ ---
113
+
114
+ ## 10. The test runner (`myxo test`)
115
+
116
+ `test "name" { ... }` runs only under `myxo test` / `runTests` (inert in a normal run). Inside, `expect`:
117
+
118
+ - `expect e` — `e` must be live (an uncalled agent/native is rejected: "did you forget to call it?").
119
+ - `expect a is b` / `a is not b` — deep structural equality.
120
+ - `expect e to fail` / `to fail with "substr"` — `e` must raise an **intentional** failure (a `fail`, or a fence/budget denial); an incidental runtime error makes the test *error*, not pass.
121
+
122
+ A test with zero expectations, a `report` in its body, or a runtime error is a failure. `node myxo.js test <file|dir>` reports per-test, exits non-zero on any failure or if no tests ran. `myxo test` runs **strict** (§11) by default.
123
+
124
+ ---
125
+
126
+ ## 11. Gradual types
127
+
128
+ Optional annotations: `seed n: Type = v`, `agent f(x: Type = d, ...rest): Type`. Types: `number string bool list mesh agent void any` (`any` always matches). **Off by default** — a normal run ignores annotations and stays dynamic. Under **`--strict`** (and `myxo test`), annotations are enforced as **runtime contracts** at four boundaries: seed-init, parameter (at the call), return, and **reassignment** of a typed binding.
129
+
130
+ **Honest scope:** this is runtime contract-checking, **not** static type inference — no unions, no generics, no flow analysis. Containers are not element-typed (`list` means "any list"). Grammar: `:` introduces a type, `=` a default.
131
+
132
+ ---
133
+
134
+ ## 12. Polyglot bridge & flow-routing (library, not core syntax)
135
+
136
+ The **polyglot** verbs are host-installed natives, governed by the §6 fence; **`route`/`flows`** are core control-flow builtins (always present, **not** fenced themselves) — what the fence governs is the *providers* a router calls, when those are capabilities:
137
+
138
+ - **Polyglot** — `pycall`/`pyeval` (Python), `jscall`/`jseval` (Node), `plcall`/`pleval` (Perl) call functions/expressions in those runtimes (value-mapped JSON in/out); `bridgeExec` wraps any executable; `sh` runs a shell line. ⚠️ These are **arbitrary-code** verbs: granting one grants that runtime's full power — the fence bounds *which* verb and *how often*, not what the verb's code does.
139
+ - **Flow-routing** — `route(name, [providers])` returns a router that learns which interchangeable provider to use (conductance = an EWMA of recent success+speed; traffic ∝ conductance; instant failover; a fence denial propagates rather than rerouting). `flows(name)` shows conductances. It is exploit-leaning with hand-tuned constants; there is no automatic language-routing beyond this.
140
+
141
+ ---
142
+
143
+ ## 13. Concurrency: parallelism (`dispatch`/`gather`/`schedule`) & cooperation (fibers + channels)
144
+
145
+ `dispatch f(args…)` builds an **unstarted task** (a handle) capturing the agent and its evaluated arguments; nothing runs yet. `gather [t1, t2, …]` runs every task on its **own OS worker thread, in parallel**, blocks the calling thread until all finish, and returns their results **in dispatch order**. `gather` is an ordinary expression (its value is a list), so it composes (`gather ts | sum`, `seed [a, b] = gather […]`).
146
+
147
+ **Isolation is the safety model.** A dispatched task runs in a *fresh* interpreter: it sees the **stdlib**, **its own arguments**, and **itself** (recursion) — and nothing else. It cannot read or mutate the parent's pathways (a reach for one fails with `unknown pathway`), so there is no shared state to race on. Consequently arguments and results cross **by value** and must be plain **data** (`number`, `string`, `bool`, `list`, `mesh`, `void`); passing or returning code (an agent/native) is rejected at the boundary, and a **non-finite number** (NaN/Infinity) is rejected rather than silently nulled.
148
+
149
+ **Errors.** A task that `fail`s, throws, or errors at runtime surfaces promptly as a single `gather: <message>` (first error wins; all-or-nothing, like `Promise.all`). A true hard worker death (OOM/kill) is caught by a wall-clock timeout (default 30s). A `gather` is never memoized (spawning threads is an effect).
150
+
151
+ **Mechanism & limits.** Zero new dependencies — the same worker + `Atomics` + `SharedArrayBuffer` barrier as `myxo-live`; the interpreter runs at native speed inside a worker (measured). See `CONCURRENCY.md`. Limits, on purpose: one worker per task (no pool), self-contained agents only (no calls to *other* user agents from inside a task), and no inter-task channels — coordination is by structure (dispatch → gather), not message-passing. This is OS-thread parallelism, not cooperative coroutines.
152
+
153
+ **The Physarum scheduler.** `schedule(name, workers, items)` lifts `route` (the slime-mold selector, §12) to parallel batches: a **named, persistent pool** of interchangeable worker-agents (`worker(chunk) -> results`, batch in/out) over which a batch is distributed **proportional to conductance** (the same credit + explore-floor as `route`, with the credit persisted on the pool so trailing/recovered workers are still sampled across small batches), run on real worker threads **in parallel**, and reassembled at each item's original index. Each worker's conductance is updated from its **measured per-item speed** (EWMA, `quality = 1 + 8/(ms+1)`): fast workers pull more flux on later calls, a worker that errors decays and **its items reroute to the survivors** (single-tier failover; if all fail, `schedule` throws — never partial). `flows(name)` shows the learned conductances (for routers and pools alike). `schedule` is never memoized. The data boundary and isolation are exactly `gather`'s (items/results are plain data; no shared state — which is what makes the distribution race-free). Honest scope: adaptation is across calls (explore then exploit), timing is nondeterministic (the *invariants* — every item once, in order, faster-worker-ends-higher — are not), constants are hand-tuned and exploit-leaning. This is the living mesh applied to execution: the language becomes the scheduler.
154
+
155
+ **Cooperative concurrency (fibers + channels).** Where the above is *parallelism* (many OS threads), fibers are *concurrency* — many tasks interleaving on **one** thread, communicating through **channels**. `spawn f(args)` starts a fiber (returns a handle). `give VALUE to CHANNEL` sends; `take NAME from CHANNEL` receives, **parking** the fiber until a value is available (a `give` to a *full* bounded channel parks until space frees); `yield` reschedules cooperatively. `channel()` is unbounded, `channel(n)` bounded (backpressure). `await(fiber)` runs the scheduler and returns that fiber's reported value (re-raising its error); `drain()` runs all fibers; spawned-but-unawaited fibers also run at program end, and a fiber's error or a deadlock **always surfaces** (never silently dropped). Delivery is exactly-once, FIFO; the scheduler is single-threaded and **deterministic**. A channel is the only shared thing and the value moves hand to hand, so there is no shared mutable state to race on (and a channel is not data — it can't cross the `gather`/`dispatch` boundary). Honest scope: cooperative (not parallel); suspension composes through the fiber's own body and inside `when`/`match`/`for each`/`reinforce`/`attempt`, but **not** into a *called* agent's body (a clean error says so, not a silent failure); `await`/`drain` can't be called from inside a fiber; a runaway fiber is bounded by a step budget and errors rather than hangs; no `select`/timeouts/closeable channels yet. See `CONCURRENCY.md`.
156
+
157
+ ---
158
+
159
+ ## 14. The living mesh (runtime law)
160
+
161
+ Every pathway carries a strength; **reading reinforces it**. `strength(name)` introspects a **global** pathway's strength (a local/closure pathway reads `0`). A **hot, provably-pure** agent auto-**memoizes** — the runtime makes used paths faster, no keyword. Soundness: a result is cached only for a call proven pure — plain params; never tainted by a capability / `random` / `emit` / `weave` / a state-reading builtin / an outer write / a free *data* read (reading a free *agent* is exempt, for recursion); primitive args + result. A global **epoch** invalidates caches on any global write, **and on any reassignment or `decay` of an agent-valued binding** (this closes the one staleness the free-agent exemption would otherwise open). **`prune(threshold = 1)`** (returns the count reaped) and **`metabolize(threshold = 2)`** (returns a mesh `{reaped, count, promoted}`) are the decay verbs that sweep cold pathways — two distinct builtins, **not** aliases. There is **no** autonomous background GC.
162
+
163
+ ---
164
+
165
+ ## 15. Errors
166
+
167
+ One error type (`MyxoError`) carries a message, a source line, and — when it crossed agent calls — a stack trace (innermost first, truncated when deep). `attempt`/`rescue` catches Myxo errors (not internal control signals, not assertion failures). A raw JS stack overflow is converted to a clean Myxo error.
168
+
169
+ ---
170
+
171
+ ## 16. CLI & embedding
172
+
173
+ - **CLI:** `node myxo.js file.myx` (run) · `--trace` (print the mesh after) · `--strict` (enforce types) · `node myxo.js` (multi-line REPL) · `myxo fmt <file> [--check|--write|--drop-comments]` (AST formatter, one true style; **comments are preserved** — collected from the real lexer and re-attached by line, statement-granular; `--drop-comments` strips them) · `myxo test <file|dir>` · `myxo lsp` (stdio language server) · `myxo plan <file>` (capability preview — see below).
174
+ - **`myxo plan` (fence approval surface):** statically reports what host capabilities a script DECLARES (`needs`) vs what it REFERENCES, flagging referenced-but-undeclared (the fence would deny) and declared-but-unused (over-grant). Exit `0` clean / `1` not-clean / `2` couldn't analyze. It is a **best-effort preview, NOT a sound gate**: scope-aware over direct call-sites, but it cannot statically distinguish a host capability from a same-named user agent, nor follow a capability passed as a value / via `weave` — so it discloses these blind spots and defers to the **runtime fence** as the actual boundary. Use it to see intent and catch mistakes; never approve on it alone.
175
+ - **Embed:** `require('./myxo').run(src, opts)` and `runTests(src, opts)`. `opts`: `capture`, `output`, `natives` (host bridge), `mcp` (an MCP client → every tool becomes a fenced capability), `moduleLoader` (`null` fences `weave`), `dir`, `maxDepth`, `maxSteps`, `requireManifest`, `promoteAt` (memoization threshold; `1e9` disables), `strict`, `onAudit`. Production hosts: `myxo-run.js` (host allowlist) and `myxo-live.js` (sync-over-async worker bridge for async tools).
176
+
177
+ ---
178
+
179
+ ## 17. Not in v1.0 (honest)
180
+
181
+ Worker-thread parallelism (`dispatch`/`gather`/`schedule`) and cooperative concurrency (fibers + channels) both ship (§13). Still designed-but-not-built (see `VISION.md`): channel `select`/timeouts/closeable channels, suspension across called-agent boundaries, a thread-reuse worker **pool**, multi-tier failover, a bytecode VM / non-Node runtime, static type inference, element-typed containers, and a non-Node embedding wire. (`myxo fmt` now preserves comments, statement-granular — a comment trailing a one-line block or inside an inline `agent(){}` may shift to its own line, but none are dropped.) This spec describes only what ships today.