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/README.md ADDED
@@ -0,0 +1,494 @@
1
+ # Myxo — the language of the Nexus
2
+
3
+ **Myxo 1.5** · a complete, from-scratch, **zero-dependency** language — its own parser, interpreter, stdlib, pattern matching, gradual types, real multi-core concurrency, a capability fence, tests, formatter, REPL, language server, and CLI.
4
+
5
+ A small, standalone and embeddable programming language whose runtime **is** the Nexus law:
6
+
7
+ > *Agents do not merge. Useful pathways reinforce. Useless pathways decay.*
8
+
9
+ That isn't a tagline bolted on top — it's the semantics. Functions are `agent`s.
10
+ Variables are *pathways* that gain strength each time they're read. You `decay` the ones
11
+ that go quiet, and `prune` sweeps the weak. Myxo is written in plain Node with **zero
12
+ dependencies**, so it runs by itself from the CLI, runs anywhere the Nexus runs, and embeds
13
+ inside any Node program.
14
+
15
+ Myxo is not just glue over Python, C++, or JAMES. Today it is a standalone `.myx` language
16
+ implemented in Node, with its own syntax, parser, interpreter, stdlib, tests, module rules,
17
+ formatter, REPL, and CLI. Its independence is semantic and operational: a `.myx` program can
18
+ run without Python, C++, JAMES, or MCP. Python, Node, Perl, shell, MCP tools, and compiled
19
+ binaries are foreign capabilities Myxo can call through the same outer fence and audit ledger.
20
+ See [`INDEPENDENCE.md`](INDEPENDENCE.md) and [`HOW_IT_WORKS.md`](HOW_IT_WORKS.md).
21
+
22
+ ```myx
23
+ agent fib(n) {
24
+ when n < 2 { report n }
25
+ report fib(n - 1) + fib(n - 2)
26
+ }
27
+
28
+ seed i = 0
29
+ reinforce i < 10 {
30
+ emit fib(i)
31
+ i = i + 1
32
+ }
33
+ ```
34
+
35
+ ## Run it
36
+
37
+ ```
38
+ node myxo.js examples/fib.myx # run a file
39
+ node myxo.js examples/the-law.myx --trace # run, then print the living mesh
40
+ node myxo.js # multi-line REPL (type an agent across lines)
41
+ npm test # full suite; optional runtimes are skipped if absent
42
+ npm run test:core # core language + formatter + MCP framing
43
+ npm run test:polyglot # Python/Node/Perl bridge checks
44
+ npm run test:myxo # Myxo testing ITSELF, in Myxo
45
+ node myxo.js test tests/ # run .myx test files (test "..." { expect X is Y / to fail })
46
+ node myxo.js fmt examples/fib.myx # print canonical parser-backed Myxo formatting
47
+ node myxo.js fmt file.myx --check # fail if file is not formatted
48
+ node myxo.js fmt file.myx --write # rewrite in place (comments preserved; --drop-comments to strip)
49
+ ```
50
+
51
+ `myxo fmt` is a canonical AST printer that **preserves comments** — it collects them from the real lexer and
52
+ re-attaches them by line (statement-granular: a comment trailing a one-line block or inside an inline
53
+ `agent(){}` may shift to its own line, but none are dropped or fabricated). `--drop-comments` strips them.
54
+
55
+ ## The words
56
+
57
+ Myxo keeps the building blocks but names them after the Nexus.
58
+
59
+ | You mean… | Myxo | Example |
60
+ |----------------------|-----------------|------------------------------------------|
61
+ | declare a value | `seed` | `seed power = 9` |
62
+ | change a value | `name = ...` | `power = power + 1` |
63
+ | remove a value | `decay` | `decay power` |
64
+ | print | `emit` | `emit "hi", power` |
65
+ | if / else | `when` / `otherwise` | `when x > 0 { } otherwise { }` |
66
+ | else-if chain | `otherwise when`| `when a {} otherwise when b {}` |
67
+ | while loop | `reinforce` | `reinforce x < 10 { x = x + 1 }` |
68
+ | count loop | `reinforce N times` | `reinforce 3 times { emit "tick" }` |
69
+ | iterate | `for each … in` | `for each x in [1,2,3] { emit x }` |
70
+ | function | `agent` | `agent greet(name) { report "hi " + name }` |
71
+ | anonymous function | `agent(...) {}` | `map(xs, agent(x){ report x * 2 })` |
72
+ | return | `report` | `report total` |
73
+ | true / false | `live` / `dead` | `when ready == live { }` |
74
+ | nothing | `void` | `seed best = void` |
75
+ | logic | `and or not` | `and`/`or` return the **value** — `x or 9` works |
76
+ | handle failure | `attempt` / `rescue` | `attempt { risky() } rescue err { }` |
77
+ | raise a failure | `fail` | `fail "no such pathway"` |
78
+ | import a strand | `weave` | `weave "math.myx"` (or `weave "m.myx" as m`) |
79
+ | export a name | `expose` | `expose area_circle` |
80
+ | declare capabilities | `needs` | `needs lookup, notify, spend(max 5)` |
81
+
82
+ **Values:** numbers, strings `"..."`, `live`/`dead`, `void`, lists `[1, 2, 3]`,
83
+ and a *mesh* (map) `{ "key": value }`. Index with `[]`; a missing mesh key reads as `void`;
84
+ negative list indexes count from the end. Strings interpolate embedded expressions with
85
+ `{ }` — `emit "strength of {key} is {m[key]}"` — and `\{` gives a literal brace.
86
+
87
+ ## Pattern matching
88
+
89
+ `match` runs the first arm whose **shape** fits, binding its names:
90
+
91
+ ```myx
92
+ match msg {
93
+ ["move", x, y] { go(x, y) }
94
+ { "kind": "ping" } { pong() }
95
+ [head, ...rest] { emit head, rest }
96
+ 0 { idle() }
97
+ _ { unknown(msg) }
98
+ }
99
+ ```
100
+
101
+ Patterns: literals (`0`, `"hi"`, `live`/`dead`/`void`), `_` (wildcard), a name (binds the value), `[list]` with an optional `...rest`, and `{ "key": pattern }` (matches a *subset* of a mesh). Patterns nest. Bindings are **linear** (a name binds once per arm) and scoped to the arm. If no arm matches, nothing runs — add `_` for a catch-all.
102
+
103
+ ## Pipelines & destructuring
104
+
105
+ `x | f` is `f(x)`; `x | f(a)` is `f(x, a)` (the piped value becomes the first argument). Pipes read top-to-bottom and chain:
106
+
107
+ ```myx
108
+ seed top = scores | filter(passing) | sort | first
109
+ ```
110
+
111
+ Destructure a list or mesh in one `seed` (reuses the pattern shapes; a non-match errors):
112
+
113
+ ```myx
114
+ seed [head, ...tail] = xs # head = xs[0], tail = the remaining list
115
+ seed { name, score } = player # binds the "name" and "score" fields
116
+ seed { "id": pid } = record # explicit key form
117
+ ```
118
+
119
+ ## Gradual types
120
+
121
+ Annotations are optional and **off by default** — a normal run stays fully dynamic. Pass `--strict` (and `myxo test` runs strict) to enforce them as runtime contracts:
122
+
123
+ ```myx
124
+ seed n: number = 5
125
+ agent area(w: number, h: number = w): number {
126
+ report w * h
127
+ }
128
+ ```
129
+
130
+ Types: `number`, `string`, `bool`, `list`, `mesh`, `agent`, `void`, `any`. Under `--strict`, a violation at a **seed**, a **parameter**, a **return**, or a **reassignment** of a typed binding raises a clear error. Honest scope: this is runtime contract-checking at those boundaries — not static inference, and containers aren't element-typed (`list` means "any list"). `:` introduces a type; defaults use `=`.
131
+
132
+ ## Concurrency: dispatch & gather
133
+
134
+ `dispatch f(x)` builds an **unstarted task**; `gather [...]` runs every task on its **own OS thread, in parallel**, blocks until all finish, and returns the results **in order**:
135
+
136
+ ```myx
137
+ agent slow(n) { seed s = 0
138
+ for each i in range(n) { s = s + (i % 7) }
139
+ report s
140
+ }
141
+
142
+ emit gather [dispatch slow(8000000), dispatch slow(8000000), dispatch slow(8000000)]
143
+ ```
144
+
145
+ `gather` is just an expression (its value is a list), so it composes: `gather tasks | sum`, `seed [a, b] = gather [...]`.
146
+
147
+ **Isolation is the safety model.** Each task runs in a *fresh* interpreter — it sees the stdlib, its own arguments, and itself (recursion), and **nothing else**. It can't read or mutate the parent's pathways, so there's no shared state to race on. The trade: values cross **by data** (`number`/`string`/`bool`/`list`/`mesh`/`void`) — handing a task an *agent*, or a non-finite number, is rejected at the boundary rather than silently mangled. A task that fails surfaces as a `gather:` error; a hung worker is reclaimed by a timeout. Zero new dependencies — same worker+`Atomics` bones as the live bridge. Full detail and the measured performance honesty in [`CONCURRENCY.md`](CONCURRENCY.md).
148
+
149
+ ### The Physarum scheduler
150
+
151
+ Where `gather` runs a fixed list, `schedule(name, workers, items)` runs a **batch through a learning pool**. It's the reinforce/decay law applied to *execution*: a batch is distributed across a pool of interchangeable worker-agents proportional to **conductance**, run in parallel, and each worker's conductance is updated from its measured speed — so fast workers pull more flux on later calls, and a worker that fails decays and its items reroute to the survivors.
152
+
153
+ ```myx
154
+ agent worker(chunk) { # batch in, batch out: one result per item, in order
155
+ seed out = []
156
+ for each x in chunk { out = out + [x * x] }
157
+ report out
158
+ }
159
+
160
+ emit schedule("squares", [worker, worker], [1, 2, 3, 4, 5, 6, 7, 8]) # -> [1, 4, 9, 16, 25, 36, 49, 64]
161
+ emit flows("squares") # each tube's learned conductance
162
+ ```
163
+
164
+ Adaptation is across calls (explore, then exploit); the invariants that never vary are: every item processed exactly once, results in item order, and a clearly-faster worker ends with higher conductance. Same isolation/data-boundary as `gather`. Detail in [`CONCURRENCY.md`](CONCURRENCY.md).
165
+
166
+ ### Cooperative concurrency: fibers & channels
167
+
168
+ `gather`/`schedule` are *parallelism* (many cores). Fibers are the other half — *concurrency*: many tasks interleaving on **one** thread, talking through **channels**. No shared memory; the value passes hand to hand.
169
+
170
+ ```myx
171
+ seed ch = channel()
172
+ agent producer(c) { seed i = 0
173
+ reinforce i < 3 { give i to c # send (parks only if a bounded channel is full)
174
+ i = i + 1 } }
175
+ agent consumer(c) { seed k = 0
176
+ reinforce k < 3 { take x from c # receive (parks until a value arrives)
177
+ emit x
178
+ k = k + 1 } }
179
+ spawn producer(ch) # start a fiber
180
+ spawn consumer(ch) # -> 0 1 2
181
+ ```
182
+
183
+ `spawn` starts a fiber, `yield` reschedules cooperatively, `await(fiber)` gets its result, `drain()` runs them all. The scheduler is single-threaded and **deterministic**, delivery is exactly-once/FIFO, and a fiber's failure or a deadlock always surfaces — never a silent hang. Detail and the honest limits in [`CONCURRENCY.md`](CONCURRENCY.md).
184
+
185
+ ## Handling failure
186
+
187
+ A program shouldn't die on one bad index. `attempt` runs a block; if a pathway fails — a
188
+ bad index, a type error, an unknown pathway, or an explicit `fail` — the failure is caught
189
+ and bound to a name as a mesh carrying `message`, `line`, and `value`:
190
+
191
+ ```myx
192
+ agent lookup(m, key) {
193
+ attempt {
194
+ when not has(m, key) { fail "no such pathway: " + key }
195
+ report m[key]
196
+ } rescue err {
197
+ report err["message"] # a failure becomes a graceful value, no crash
198
+ }
199
+ }
200
+ ```
201
+
202
+ `fail expr` raises a failure an enclosing `attempt` can rescue. `report` is **not** caught —
203
+ it still returns from the agent. And because `and`/`or` return the operand value,
204
+ `count[w] or 0` gives `0` when the key is missing. See `examples/resilient.myx`.
205
+
206
+ When a failure *isn't* rescued, it carries a **stack trace** — the chain of agent calls that
207
+ led there, innermost first — not just a line number:
208
+
209
+ ```
210
+ Myxo error (line 1): division by zero
211
+ in c (called at line 2)
212
+ in b (called at line 3)
213
+ in a (called at line 4)
214
+ ```
215
+
216
+ Deep traces are truncated, and runaway recursion fails as a clean `Myxo error (… call stack went
217
+ too deep …)` instead of a raw crash.
218
+
219
+ ## Modules: weave & expose
220
+
221
+ A file is a *strand*. It keeps everything private unless it `expose`s it; another strand
222
+ pulls those names in with `weave`:
223
+
224
+ ```myx
225
+ # geo.myx
226
+ agent area_circle(r) { report PI * r * r }
227
+ seed TAU = PI * 2
228
+ expose area_circle
229
+ expose TAU
230
+ ```
231
+
232
+ ```myx
233
+ # main.myx
234
+ weave "geo.myx" # flat: area_circle and TAU are now in scope
235
+ emit area_circle(2)
236
+
237
+ weave "geo.myx" as geo # or namespaced into a mesh
238
+ emit geo["TAU"]
239
+ ```
240
+
241
+ Paths resolve relative to the weaving strand. Modules run **once and are cached**, and
242
+ **circular weaves are caught**, not looped. And because weaving reads a file, **it's a
243
+ granted capability**: an embedded host that builds an interpreter without a module loader
244
+ (`run(src, { moduleLoader: null })`) fences `weave` entirely — a sandboxed agent script
245
+ can't reach the filesystem through it. The fence holds. See `examples/use-geo.myx`.
246
+
247
+ ## Capabilities: needs & the audit ledger
248
+
249
+ Myxo is the language you hand an *agent*, so safety is part of the execution model, not a bolt-on.
250
+ The interpreter can only compute; every real-world power (a db lookup, a message, a payment,
251
+ Python eval, a shell command, a compiled binary) is a **capability** the host grants across the
252
+ bridge. Myxo is designed as a capability-first embeddable language for agent scripts:
253
+
254
+ **1. A script declares what it may touch — and how far it may go.** `needs lookup, notify` is a
255
+ manifest. Once declared, calling a capability *not* in it is refused — **even if the host granted
256
+ it.** And a capability can carry a **value budget**: `spend(max 5, total 15)` caps a single call
257
+ (`max`) and the cumulative spend across the whole run (`total`), runtime-enforced. The script is
258
+ bounded by *its own word*, not by the host's restraint:
259
+
260
+ ```myx
261
+ needs lookup, notify, spend(max 5, total 15)
262
+ emit lookup("vallartas") # ok — declared
263
+ emit spend(4) # ok — within the per-call max and the run budget
264
+ emit spend(1000000) # refused: exceeds the per-call max of 5
265
+ emit purge("everything") # refused: 'purge' is not declared in this script's 'needs'
266
+ ```
267
+
268
+ That `spend(max 5, total 15)` is the exact shape of the real Nexus outward gate ($5/tx, $15/day)
269
+ — now a single line of the script's own contract instead of bespoke host code. See
270
+ `examples/outward-gate.myx`.
271
+
272
+ **2. Every privileged call is logged.** The runtime keeps an **audit ledger** — name, args, and
273
+ outcome of each capability call, *including refusals* — handed back to the host after the run
274
+ (even if it failed):
275
+
276
+ ```js
277
+ run(agentSrc, {
278
+ natives: { lookup, notify, spend }, // what the host is willing to grant
279
+ onAudit: (ledger) => console.log(ledger),
280
+ });
281
+ // [ { cap: 'lookup', args: ['vallartas'], ok: true, result: "..." },
282
+ // { cap: 'spend', args: ['1000000'], ok: false, error: 'not declared in needs' } ]
283
+ ```
284
+
285
+ Builtins (`len`, `emit`, `map`, …) are **not** capabilities — they're free. Only host-granted
286
+ powers are fenced and logged. See `examples/agent.myx` + `examples/host.js` for the whole story:
287
+ a fenced agent that overreaches, is stopped, and leaves a complete trail.
288
+
289
+ Important boundary: the fence governs the call into a capability. It decides whether the script
290
+ may call that verb, how many times or how much it may spend, and what gets logged. It does not
291
+ sandbox arbitrary code inside a granted runtime. For untrusted or model-written scripts, expose
292
+ narrow structured verbs like `score_lead(id)` or `resize_image(input, output)`, not broad verbs
293
+ like `pyeval`, `jseval`, `sh`, or raw executable launch.
294
+
295
+ ## The mesh: bridging MCP tools
296
+
297
+ Capabilities don't have to be hand-written. Hand `run` an **MCP client** and every tool it
298
+ exposes becomes a fenced Myxo capability automatically — so an Myxo script can drive your whole
299
+ tool catalog through one law. Whatever language or service is behind a tool (a Python query, a
300
+ Rust service, a shell command, a model), from inside the script it's just a verb it was granted:
301
+
302
+ ```myx
303
+ needs james_db_query, james_telegram_send
304
+
305
+ seed lead = james_db_query("SELECT name FROM leads ORDER BY score DESC LIMIT 1")
306
+ james_telegram_send({ "text": "new top lead: " + lead })
307
+ # james_pm2_action was bridged too, but never declared -> refused before the host is called
308
+ ```
309
+
310
+ ```js
311
+ run(src, {
312
+ mcp: {
313
+ tools: [ { name: 'james_db_query', inputSchema: { properties: { sql: {} }, required: ['sql'] } }, … ],
314
+ call: (name, args) => mcpServer.invoke(name, args), // your transport; returns the result
315
+ },
316
+ onAudit: (ledger) => console.log(ledger),
317
+ });
318
+ ```
319
+
320
+ A mesh argument maps to the tool's named arguments; a lone value fills its first required
321
+ property (so `query("SELECT …")` works). MCP-style results (`{ content: [...] }`) unwrap to
322
+ their text, and an error result becomes a rescuable `fail`. Every call is still bounded by the
323
+ script's `needs` manifest and its value budgets, and logged in the audit ledger — the manifest
324
+ decides *which* of the bridged tools this script may actually speak. See `examples/nexus-mesh.myx`
325
+ + `examples/mcp-host.js`.
326
+
327
+ ### Running it live (the wire)
328
+
329
+ Two helpers turn the bridge into a production path an MCP tool can call:
330
+
331
+ - **`myxo-run.js`** — `runScript(script, { client, allow, dir })` → `{ ok, output, audit, error }`.
332
+ Never throws (a tool handler wants a result). Adds a third gate, the **host allowlist** (`allow`
333
+ decides which tools are even *bridged* — absence beats refusal), on top of the script's `needs`
334
+ and its budgets. Production defaults require a `needs` manifest and fence `weave` unless the
335
+ host explicitly grants a module loader.
336
+ - **`myxo-live.js`** — `runLive(script, { tools, onCall, allow })` → `Promise<{ ok, output, audit }>`.
337
+ Real tools are **async**; Myxo is **synchronous**. This bridges them with zero dependencies via
338
+ `worker_threads` + `Atomics`: the script runs in a Worker and each call round-trips to the host's
339
+ async `onCall(name, args)`, the Worker parking until the result is posted back. The transport
340
+ stays abstract, so the same runner wires into any host. `timeoutMs` and `maxSteps` provide wall
341
+ clock and instruction-fuel backstops. See `examples/james-myxo-demo.js`.
342
+
343
+ This is how `james_nx_run` is built in the live Nexus: a curated, safe allowlist of JAMES tools,
344
+ an `onCall` over the real handlers, and `runLive` doing gated, audited work a local model's script
345
+ cannot exceed unless the host exposes a broader capability. The live JAMES surface deliberately
346
+ uses narrow read/request verbs rather than eval, shell, direct messaging, or direct writes.
347
+
348
+ The JAMES bridge deliberately exposes only narrow hands to Myxo. Current capabilities:
349
+
350
+ - `james_db_query`, `james_read_notes` — read paths.
351
+ - `james_approval_request`, `james_approval_list` — human-review queue only; no execution.
352
+ - `james_git_push_request`, `james_action_await` — outwardGate one-tap path for `git_push` only. It is not raw `james_action_stage`; the repo/branch still must pass JAMES's git allowlist and Milton must approve before anything pushes.
353
+
354
+ The unsafe/direct verbs stay absent: no direct memory write, no thought-board post, no Telegram
355
+ send, no PM2 control, no secrets, no sandbox exec, no rollback, and no generic outward action
356
+ staging. Myxo can ask for human review; it cannot quietly perform those side effects through
357
+ `james_nx_run`.
358
+
359
+ ## The Law engine
360
+
361
+ Every named pathway carries a **strength** that starts at 1 and rises each time the pathway
362
+ is read — *useful pathways reinforce through use*. Two builtins make the mesh visible and
363
+ self-pruning:
364
+
365
+ - `mesh()` — returns the live pathway graph as a mesh of `name: strength`
366
+ - `prune(threshold)` — removes pathways below `threshold`, returns how many fell
367
+
368
+ Run any script with `--trace` to watch the mesh as a bar chart of strengths after it ends.
369
+
370
+ ## Built-in agents
371
+
372
+ **Core:** `len` · `type` · `keys` · `values` · `has` · `range` · `push` · `pop` · `shift` ·
373
+ `unshift` · `str` · `num` · `mesh` · `prune`
374
+ **Strings:** `upper` · `lower` · `trim` · `split` · `join` · `replace` · `repeat` · `chars` ·
375
+ `starts` · `ends`
376
+ **Sequences (string or list):** `slice` · `find` · `reverse` · `sort` · `entries` · `merge`
377
+ **Math:** `abs` · `floor` · `ceil` · `round` · `sqrt` · `pow` · `log` · `sin` · `cos` · `tan` ·
378
+ `max` · `min` · `random`
379
+
380
+ And from `std.myx` (written in Myxo itself): `map` · `filter` · `reduce` · `sum` · `biggest` ·
381
+ `contains` · `count` · `first` · `last` · `clamp` · `words` · `lines`, plus the constants
382
+ `PI` and `E`.
383
+
384
+ > **Where Myxo is headed:** the full design — modules, async agents, the self-optimizing mesh,
385
+ > the finished capability fence, and the honest pitch for why Myxo becomes the go-to language of
386
+ > the agent era — is laid out in [`VISION.md`](VISION.md). *Leave nothing unimagined.*
387
+
388
+ ## Running Myxo Independently
389
+
390
+ Myxo is usable without JAMES/Nexus or any foreign runtime:
391
+
392
+ ```
393
+ node myxo.js examples/fib.myx
394
+ node myxo.js
395
+ node myxo.js fmt examples/fib.myx
396
+ npm test
397
+ ```
398
+
399
+ That standalone surface is part of the contract. Polyglot bridges add reach; they do not make
400
+ Myxo dependent on the bridged language.
401
+
402
+ ## Editor support (LSP)
403
+
404
+ `node myxo.js lsp` (or `npm run lsp`) starts a stdio JSON-RPC language server: live diagnostics (syntax/parse errors), hover docs on keywords and builtins, completion (keywords + builtins + the top-level names in your file), and format-on-command. Point any LSP client at the `myxo lsp` command.
405
+
406
+ Honest scope (v1): diagnostics are **syntax-only** — a file that parses but is semantically broken (a type error under `--strict`, a wrong arity) shows no squiggle until you run it. Completion is top-level / not scope-aware. No go-to-definition, references, or rename yet. Formatting **preserves comments** (statement-granular).
407
+
408
+ ## Previewing a script's reach: `myxo plan`
409
+
410
+ `node myxo.js plan <file>` is the **fence approval surface** — before you (or a gate) run a script, see exactly what host capabilities it *declares* (`needs`) versus what it *reaches for*, with referenced-but-undeclared flagged (the fence would deny) and over-grants called out. Exit `0` clean / `1` not-clean / `2` couldn't analyze, so a gate can branch on it.
411
+
412
+ ```
413
+ $ node myxo.js plan job.myx
414
+ Declared capabilities (needs):
415
+ db_query
416
+ Capabilities referenced in code:
417
+ db_query OK declared
418
+ telegram_send XX NOT declared (line 4) — the fence would deny it
419
+ VERDICT: 1 referenced capability(ies) not declared — this script would be REFUSED at runtime ...
420
+ ```
421
+
422
+ Honest scope: it's a **best-effort preview, not a sound gate** — scope-aware over direct call-sites, but it can't statically tell a host capability from a same-named user agent, nor follow a capability passed as a value or via `weave`. It discloses those blind spots on every run and defers to the **runtime fence** as the real boundary. Use it to see intent and catch mistakes; never approve on it alone.
423
+
424
+ ## Embedding Myxo in the Nexus
425
+
426
+ Myxo is built to be driven from Node. `require` it and run source in-process, handing your
427
+ own native functions across the host bridge:
428
+
429
+ ```js
430
+ const { run } = require('./myxo');
431
+
432
+ // Capture output as a string:
433
+ const text = run('emit 2 + 3', { capture: true }); // "5\n"
434
+
435
+ // Expose host capabilities to scripts (the path to james.* / db / telegram):
436
+ run('emit lookup("vallartas")', {
437
+ natives: {
438
+ lookup: (args) => queryNexus(args[0]), // your JS, callable as an agent in Myxo
439
+ },
440
+ });
441
+ ```
442
+
443
+ `run(src, opts)` options: `capture` (return output instead of printing),
444
+ `output` (a custom writer), `natives` (host capabilities — `name → fn(args, interp)`),
445
+ `mcp` (an MCP client `{ tools, call }` — every tool becomes a fenced capability),
446
+ `onAudit` (receive the capability ledger), `dir` (base directory for `weave`),
447
+ `moduleLoader` (override, or `null` to fence `weave`), `maxDepth` (recursion cap),
448
+ `maxSteps` (instruction-fuel cap), `requireManifest` (refuse capability calls until `needs`
449
+ is declared), and `trace` (append the mesh view).
450
+
451
+ ## Evals — the instrument (Phase 1)
452
+
453
+ Myxo's thesis is that a model writes correct, *safe* agent-code more reliably in Myxo than in
454
+ Python-in-a-sandbox. The only honest way to know is to measure it, so `myxo-evals/` is the
455
+ instrument: **30 golden tasks** across six buckets (data · control · agents · fence ·
456
+ concurrency · adversarial), each with a reference solution and discriminating checks.
457
+
458
+ ```
459
+ node myxo-evals/run-evals.js # --ref: run every task's reference solution (validates the set)
460
+ node myxo-evals/run-evals.js --model ollama # local free baseline (Ollama on :11434)
461
+ node myxo-evals/run-evals.js --model claude # frontier tier (ANTHROPIC_API_KEY; costs)
462
+ node myxo-evals/run-control.js [--model ...] # the Python control group — the Myxo-vs-Python delta
463
+ ```
464
+
465
+ The harness is adversarially hardened (two independent review passes): execution is
466
+ fuel-bounded so one runaway solution can't hang the run; **fence tasks are scored on the
467
+ capability audit ledger**, not just stdout, so a hardcoded-emit cheat fails; a required
468
+ construct (`match`, `dispatch`/`gather`, …) is gated against dead-branch and comment/string
469
+ bypasses; and a model's own test blocks are stripped before scoring. First baseline numbers
470
+ and the honest scope live in [`myxo-evals/BASELINE.md`](myxo-evals/BASELINE.md).
471
+
472
+ ## How it works
473
+
474
+ A classic tree-walking interpreter in four stages, one file each:
475
+
476
+ ```
477
+ .myx source → lexer.js → parser.js → interpreter.js ⇄ builtins.js → output
478
+ tokens AST walk + eval host bridge
479
+ ```
480
+
481
+ - **`lexer.js`** — text → tokens, tracking line/col for errors
482
+ - **`parser.js`** — recursive descent + precedence climbing → AST
483
+ - **`interpreter.js`** — the `Environment` (pathways + strength + closures) and evaluator
484
+ - **`builtins.js`** — native functions and `registerNative` (the host bridge)
485
+ - **`mcp-bridge.js`** — turns a catalog of MCP tools into fenced Myxo capabilities
486
+ - **`std.myx`** — the standard library, bootstrapped in Myxo
487
+ - **`myxo.js`** — CLI, REPL, and the `run()` embed API
488
+
489
+ Errors are a single `MyxoError` type carrying a line number, so the lexer, parser, and
490
+ interpreter all point at exactly where a program went wrong.
491
+
492
+ ## License
493
+
494
+ MIT.