|
1 | | -# MeTTa TS 1.1.2 |
| 1 | +# MeTTa TS 1.1.3 |
2 | 2 |
|
3 | | -A pure-TypeScript implementation of [MeTTa](https://metta-lang.dev), the |
4 | | -OpenCog Hyperon language. The core engine runs in the browser, Node, Deno, Bun, |
5 | | -edge runtimes, and TypeScript-based agents with no native addon and no required |
6 | | -WASM. Optional host adapters can load Python or Prolog runtimes when a program |
7 | | -asks for them. |
| 3 | +MeTTa TS 1.1.3 improves nondeterministic evaluation and bounds every automatic |
| 4 | +table allocation. The default evaluator is faster than PeTTa on the four |
| 5 | +reported nondeterministic workloads while preserving Hyperon semantics. There |
| 6 | +is no benchmark mode, PeTTa mode, curry mode, or manually selected fast path. |
8 | 7 |
|
9 | 8 | ## Tested on Linux |
10 | 9 |
|
11 | 10 | This release is prepared on Linux with Node 22 and pnpm 11. The release gate |
12 | 11 | builds every package, typechecks the workspace, runs the full Vitest suite, |
13 | | -builds the GitHub Pages documentation, runs the oracle checks, and runs the |
14 | | -benchmark suite before tagging. Optional Python, Pyodide, SWI-Prolog, and |
15 | | -SWI-WASM adapters are built and covered by their available tests, with live |
16 | | -runtime checks depending on the host tools installed in the release |
17 | | -environment. |
18 | | - |
19 | | -The current conformance rerun reports Core/ST at 431 passed, 77 failed, 60 |
20 | | -expected failures, and 0 skipped. Full/ST with `fileio,json,random` reports 470 |
21 | | -passed, 174 failed, 4 expected failures, and 26 skipped. The remaining gaps are |
22 | | -the tracked parser/directive, kernel, typing, stdlib, feature, and concurrency |
23 | | -divergences, so this release should not be described as full Hyperon |
24 | | -conformance. |
25 | | - |
26 | | -## What's new |
27 | | - |
28 | | -### Integrated host interop release train |
29 | | - |
30 | | -This release includes the full local host-interop train that followed 1.1.0: |
31 | | -browser host adapters, Python and Prolog runtime splits, SWI-WASM, Pyodide, |
32 | | -source runners, async effects, CLI checks, and the eDSL host builders. |
33 | | - |
34 | | -### Browser Python and Prolog |
35 | | - |
36 | | -`@metta-ts/browser/host` composes optional host runtimes into the browser |
37 | | -runner. A browser app can now run the same `.metta` program shape as Node: |
38 | | - |
39 | | -```metta |
40 | | -!(import! &self "math.py") |
41 | | -!(py-call (math.add 40 2)) |
42 | | -
|
43 | | -!(import! &self "facts.pl") |
44 | | -!(prolog-call (edge alice $x)) |
45 | | -``` |
46 | | - |
47 | | -Python runs through `@metta-ts/py/pyodide`. Prolog runs through |
48 | | -`@metta-ts/prolog/swi-wasm`. The base `@metta-ts/browser` package stays |
49 | | -runtime-agnostic; Pyodide and SWI-WASM are only included when their adapter |
50 | | -subpaths are imported. |
51 | | - |
52 | | -### Prolog interop package |
53 | | - |
54 | | -`@metta-ts/prolog` is now part of the release. The root package contains the |
55 | | -generic bridge and MeTTa-side helper source. Runtime adapters live on subpaths: |
56 | | - |
57 | | -- `@metta-ts/prolog/swi-node` talks to a local `swipl` executable. |
58 | | -- `@metta-ts/prolog/swi-wasm` runs through `swipl-wasm`. |
59 | | - |
60 | | -The supported surface follows PeTTa where the operation is a host Prolog bridge: |
61 | | -`Predicate`, `callPredicate`, `assertaPredicate`, `assertzPredicate`, |
62 | | -`retractPredicate`, `prolog-call`, `prolog-consult`, and |
63 | | -`import_prolog_function`. |
64 | | - |
65 | | -MeTTa TS keeps Hyperon-style evaluation. There is no PeTTa mode and no curry |
66 | | -mode. Plain `.pl` imports and predicate calls are host capabilities, not a |
67 | | -second evaluator. |
| 12 | +builds the GitHub Pages documentation, runs the Hyperon oracle, runs the scale |
| 13 | +proof, and runs the benchmark suite before tagging. |
68 | 14 |
|
69 | | -### Runtime adapter split |
| 15 | +The final suite passed 109 test files and 1,063 tests, with 38 optional live |
| 16 | +integration tests skipped. The checked 270-assertion oracle passed all 23 |
| 17 | +corpus files. |
70 | 18 |
|
71 | | -The Python and Prolog roots no longer import runtime backends from their package |
72 | | -roots. Node-specific adapters are explicit subpaths: |
73 | | - |
74 | | -- `@metta-ts/py/pythonia` |
75 | | -- `@metta-ts/prolog/swi-node` |
76 | | - |
77 | | -Browser adapters are explicit subpaths: |
78 | | - |
79 | | -- `@metta-ts/py/pyodide` |
80 | | -- `@metta-ts/prolog/swi-wasm` |
81 | | - |
82 | | -That keeps default imports browser-clean and leaves optional dependencies behind |
83 | | -their adapter subpaths. |
84 | | - |
85 | | -### eDSL host helpers |
86 | | - |
87 | | -`@metta-ts/edsl/py` and `@metta-ts/edsl/prolog` provide dependency-free builders |
88 | | -for the host interop forms. They build ordinary atoms such as `py-call`, |
89 | | -`py-atom`, `prolog-call`, `Predicate`, and `import_prolog_function`. They do |
90 | | -not load Python, Prolog, Pyodide, SWI-WASM, or Node adapters. |
91 | | - |
92 | | -```ts |
93 | | -import { vars } from "@metta-ts/edsl"; |
94 | | -import { pyCall } from "@metta-ts/edsl/py"; |
95 | | -import { prologCall } from "@metta-ts/edsl/prolog"; |
96 | | - |
97 | | -const { x } = vars(); |
98 | | - |
99 | | -pyCall("math.add", 40, 2); // (py-call (math.add 40 2)) |
100 | | -prologCall(["edge", "alice", x]); // (prolog-call (edge alice $x)) |
101 | | -``` |
102 | | - |
103 | | -### Bounded structural tabling |
104 | | - |
105 | | -Automatic tabling now uses structural token keys and a bounded table space |
106 | | -instead of recursive printed-form keys. Pure overlapping-recursive calls can be |
107 | | -memoized without table growth being unbounded: |
108 | | - |
109 | | -- completed pure entries are capped and LRU-evictable; |
110 | | -- interner resets invalidate old opaque table keys; |
111 | | -- runtime rules are version-keyed; |
112 | | -- impure, meta, state, import, `match`, `collapse`, and concurrency paths stay |
113 | | - outside the table cache; |
114 | | -- direct active variant recursion uses local-linear completion for finite answer |
115 | | - sets; |
116 | | -- non-cyclic calls keep exact ordered-bag memoization. |
| 19 | +The external Core/ST conformance result is unchanged from the untouched 1.1.2 |
| 20 | +baseline: 431 passed, 77 failed, 60 manifest expected failures, and 0 skipped. |
| 21 | +The remaining failures are existing parser, directive, kernel, typing, and |
| 22 | +stdlib contract differences. This release does not claim full specification |
| 23 | +conformance. |
117 | 24 |
|
118 | | -The stale-key path reported during release review is covered by a regression: |
119 | | -old tail-call pending keys cannot write into a new interner generation after a |
120 | | -table-space reset. |
| 25 | +## Nondeterministic execution |
| 26 | + |
| 27 | +The new checked benchmark keeps four query shapes reported by Patrick Hammer |
| 28 | +as ordinary `.metta` files. Five-run subprocess medians include startup: |
| 29 | + |
| 30 | +| Program | PeTTa | MeTTa TS | Speedup | |
| 31 | +| -------------------------------- | --------: | --------: | ------: | |
| 32 | +| filtered `matespacefast` matches | 5738.1 ms | 3344.2 ms | 1.72x | |
| 33 | +| 22^4 `superpose` cross product | 388.7 ms | 148.5 ms | 2.62x | |
| 34 | +| nondeterministic tabled `fib(7)` | 180.1 ms | 99.6 ms | 1.81x | |
| 35 | +| duplicate-heavy `TupleConcat` | 178.8 ms | 101.1 ms | 1.77x | |
| 36 | + |
| 37 | +The harness validates 234,256 cross-product results, 196 distinct Fibonacci |
| 38 | +answers, the exact `TupleConcat` sequence, and the embedded matespace |
| 39 | +assertion. Run it with `pnpm bench:nondeterminism`. |
| 40 | + |
| 41 | +A slot-based choice evaluator handles closed pure `let`, `let*`, `superpose`, |
| 42 | +integer arithmetic, comparisons, `if`, and constructor tuples. Unsupported, |
| 43 | +redefined, ill-typed, async, or executable-grounded forms stay on the normal |
| 44 | +interpreter path. Result order and multiplicity are unchanged. |
| 45 | + |
| 46 | +`unique-atom(collapse(call))` can evaluate a supported static pure integer |
| 47 | +recurrence as a first-seen answer set. Closed pure choice products also retain |
| 48 | +first-seen answers as they emit instead of materializing a duplicate bag first. |
| 49 | +An ordinary `collapse(call)` still returns its exact ordered bag with duplicate |
| 50 | +derivations. Ground answer deduplication uses structural hashes with equality |
| 51 | +checks instead of a quadratic scan. |
| 52 | + |
| 53 | +## Bounded automatic tabling |
| 54 | + |
| 55 | +Automatic table admission remains conservative. The whole rule dependency |
| 56 | +graph must be pure, the call key must be safe, and the recursive component must |
| 57 | +branch back into itself at least twice. Linear recursion stays on the normal |
| 58 | +compiled path. |
| 59 | + |
| 60 | +The policy does not assume that every recursive program is safe to memoize and |
| 61 | +does not let admitted tables grow until the process runs out of memory. It |
| 62 | +combines the static overlap test with one global runtime budget. Exceeding the |
| 63 | +active-state budget returns `TableResourceLimit`; it does not continue toward |
| 64 | +an out-of-memory failure. |
| 65 | + |
| 66 | +Completed and active tables now share these default ceilings: |
| 67 | + |
| 68 | +- 50,000 entries |
| 69 | +- 1,000,000 answers |
| 70 | +- 1,000,000 retained atom cells |
| 71 | +- 100,000 cells in one entry |
| 72 | +- 250,000 interned leaves |
| 73 | + |
| 74 | +Completed tables are removed in least-recently-used order. Active tables are |
| 75 | +not evicted while their producer runs, so they return `TableResourceLimit` when |
| 76 | +the shared budget cannot fit more state. The consumer-directed recurrence memo |
| 77 | +uses the same entry, answer, cell, and per-entry limits. Interner generations |
| 78 | +prevent stale tail-call keys from writing after a reset. |
| 79 | + |
| 80 | +Direct active variant recursion still uses local-linear fixed-point completion. |
| 81 | +Non-cyclic calls preserve exact ordered bags. The evaluator does not infer |
| 82 | +Picat-style `min` or `max` answer subsumption. |
| 83 | + |
| 84 | +## Matching and scale |
| 85 | + |
| 86 | +Ground runtime facts now have a nested argument-functor index. A pattern such |
| 87 | +as `(num (M $x))` selects the `M` bucket instead of scanning every `num` fact. |
| 88 | +The matcher falls back to complete candidates when a non-ground fact could |
| 89 | +unify. |
| 90 | + |
| 91 | +A finite in-memory match whose result is discarded by a standard |
| 92 | +`let ... (empty)` is removed before enumeration. The optimization declines for |
| 93 | +custom grounded matchers, mutable state handles, changed standard forms, and |
| 94 | +non-memory spaces. |
| 95 | + |
| 96 | +The 30,000-fact scale gate also runs larger actual MeTTa workloads: |
| 97 | + |
| 98 | +| Program | Checked result | Time | |
| 99 | +| -------------------------- | ------------------------------: | -------: | |
| 100 | +| 24^4 pure choice product | 331,776 answers | 81.2 ms | |
| 101 | +| duplicate tuple product | 50 values from 500,000 branches | 30.8 ms | |
| 102 | +| nondeterministic `fib(10)` | 2,817 distinct answers | 73.4 ms | |
| 103 | +| nested runtime match | 30,000 answers | 647.3 ms | |
| 104 | + |
| 105 | +## Correctness fixes |
| 106 | + |
| 107 | +- `superpose` in the choice evaluator now strips a collapsed bag's leading |
| 108 | + comma marker. The recursive `supercollapse` corpus case remains empty as |
| 109 | + Hyperon requires. |
| 110 | +- Choice planning now respects application type errors, expression-headed |
| 111 | + rewrite rules, and replaced sync or async grounded operations. |
| 112 | +- Nested indexing no longer changes candidate enumeration when a pattern has |
| 113 | + no nested-head constraint. |
| 114 | +- Active table entries and answers count against the same global resource |
| 115 | + budget as completed entries. |
| 116 | +- The purity firewall now treats custom sync and async grounded operations as |
| 117 | + effectful unless they are the unchanged implementation of a known-pure |
| 118 | + built-in. File, catalog, random, time, output, fresh-identity, and host calls |
| 119 | + cannot enter automatic tables transitively. |
| 120 | +- File handles can be closed immediately with `file-close!` and are also closed |
| 121 | + when their grounded atom is collected. Dictionary spaces and file records use |
| 122 | + weak-key storage instead of lifetime-unbounded global maps. Grounded behavior |
| 123 | + and non-default grounded types remain on the lossless atomspace path. |
| 124 | +- Grounded-operation registration invalidates evaluated terms, table analyses, |
| 125 | + and compiled closures that may encode the previous dispatch behavior. |
| 126 | +- DAS gateway binding responses must contain exactly one MeTTa atom per value. |
| 127 | + Malformed or multi-atom wire values now fail at the decode boundary. |
| 128 | +- Git imports pass an end-of-options marker before the repository path. |
| 129 | +- The unused `streamEmit`, `tableBackchain`, and `trieSpace` experimental |
| 130 | + options have been removed. They never selected an implementation. |
121 | 131 |
|
122 | 132 | ## Install |
123 | 133 |
|
124 | 134 | ```bash |
125 | | -npm install @metta-ts/core |
126 | | -npm install -g @metta-ts/node |
127 | | -npm install @metta-ts/py pythonia |
128 | | -npm install @metta-ts/prolog |
| 135 | +npm install @metta-ts/core@1.1.3 |
| 136 | +npm install -g @metta-ts/node@1.1.3 |
129 | 137 | ``` |
130 | 138 |
|
131 | | -Browser projects that use optional host runtimes should also install the runtime |
132 | | -adapter they import: |
| 139 | +Optional host packages use the same version: |
133 | 140 |
|
134 | 141 | ```bash |
135 | | -npm install pyodide swipl-wasm |
| 142 | +npm install @metta-ts/py@1.1.3 pythonia |
| 143 | +npm install @metta-ts/prolog@1.1.3 |
136 | 144 | ``` |
137 | 145 |
|
138 | 146 | ## Provenance |
139 | 147 |
|
140 | 148 | - Semantics: [hyperon-experimental](https://github.com/trueagi-io/hyperon-experimental). |
141 | | -- Python interop surface: PeTTa's `py-call` and Hyperon's |
142 | | - [`py-atom`](https://trueagi-io.github.io/hyperon-experimental/reference/atoms/) |
143 | | - family. |
144 | | -- Prolog interop surface: PeTTa-compatible predicate bridge forms where they do |
145 | | - not depend on PeTTa's evaluator. |
146 | | -- Verified spec and differential oracle: |
147 | | - [LeaTTa](https://github.com/MesTTo/LeaTTa). |
| 149 | +- Verified differential semantics: [LeaTTa](https://github.com/MesTTo/LeaTTa). |
| 150 | +- Host compatibility: PeTTa-compatible Python and Prolog bridge forms where |
| 151 | + they do not depend on PeTTa's evaluator. |
148 | 152 | - License: [MIT](LICENSE). |
0 commit comments