Hyperon Experimental Deep Dive

Approved by Ursula Addison on 2026-05-14

Hyperon Experimental is the official trueagi-io Rust reference implementation of the MeTTa runtime — the foundational MeTTa substrate that every other MeTTa runtime ports, transpiles, embeds, or bridges to. It is maintained by trueagi-io and documented here at release v0.2.10 (February 2026). This card is a deep technical reference for its interpreter, type system, standard library, module system, storage index, and language bindings.

Last verified: 2026-06-01 (at HEAD 3f76dc46 / v0.2.10).

Source Identity

  • Origin: https://github.com/trueagi-io/hyperon-experimental
  • HEAD pinned: 3f76dc460da6961f57f69f6c3e550c59c74ada83
  • Tagged release: v0.2.10 (Merge PR #1075, 2026-02-11, Vitaly Bogdanov)
  • Tag timeline: v0.2.1 (2024-10-23) to v0.2.10 (2026-02-11), 10 minor releases over ~16 months
  • 7-crate Rust workspace: hyperon-common, hyperon-atom, hyperon-space, hyperon-macros, lib, c, repl
  • Non-workspace dirs: python/ (pybind11 bindings + sandbox), integration_tests/das/, docs/
  • Tracked-file inventory: 296 files (85 .rs + 67 .metta + 65 .py + 22 .md + smaller)
  • Primary maintainer: Vitaly Bogdanov (2,137 commits all-time)

Architecture

Interpreter Semantics

The interpreter is stack-based, plan/state-driven, and nondeterministic: it is not a deterministic "first match wins" rewrite engine — multiple matches produce multiple results. Key entry points in lib/src/metta/interpreter.rs:

  • interpret_step (L269) — main reduction step
  • interpret_stack (L374) — stack dispatch with depth enforcement (L392)
  • eval_impl (L504), eval_result (L559), query (L604)
  • chain (L687), collapse-bind (L746), unify (L809), superpose-bind (L893)
  • Native grounded-symbol calls (L922)

Boundary: programs requiring deterministic dispatch must use mutually exclusive patterns. Catchall equations ($_, $other) alongside specific equations produce multiple reductions — this is documented language semantics, not a defect.

Type System

Types are dynamically checked. In lib/src/metta/types.rs:

  • %Undefined% is a permissive wildcard — assigned to atoms without a user type, it matches any required type (L18-19)
  • check_arg_types (L65), get_atom_types (L327), get_application_types (L512), UndefinedTypeMatch (L526)
  • check_type (L602), validate_atom (L637)
  • Dependent-type tests at L817, L861, L1120, L1139
  • Open TODOs at L42, L379, L397, L494-499, L1177, L1225, L1298

Hyperon Experimental supports expressive type checking, but should not be described as a fully-settled categorical/dependent-type verifier.

Standard Library

The standard library is split between Rust-side token registrations under lib/src/metta/runner/stdlib/ and MeTTa-side definitions in stdlib.metta (1,421 lines). Cross-runtime audits must cover both layers.

Rust-side modules:

  • arithmetics.rs (L162-198): +, -, *, /, %, <, >, <=, >=, and, or, not, xor, division
  • atom.rs (L449-474): unique-atom, union-atom, intersection-atom, max-atom, min-atom, size-atom, index-atom, subtraction-atom, get-type, get-metatype, get-type-space
  • core.rs (L336-362): pragma!, nop, sealed, ==, match, if-equal, superpose, capture, _minimal-foldl-atom
  • debug.rs (L155-177): trace!, print-alternatives!, =alpha
  • math.rs (L408-443): pow-math, sqrt-math, abs-math, log-math, etc., plus PI and EXP constants
  • module.rs (L280-298): import! (L290), include, mod-space!, print-mods!, bind! (L269), module-space-no-deps
  • package.rs (L113-117): register-module!, git-module!
  • space.rs (L206-223): new-space, get-state, change-state!, get-atoms, add-atom, remove-atom

MeTTa-side definitions in stdlib.metta: return (L47), function (L54), eval (L61), chain (L78), unify (L88), cons-atom (L96), decons-atom (L103), collapse-bind (L239), superpose-bind (L246), metta (L255), switch (L345-362), if (L511-513), let/let* (L542-553), collapse (L1203), case (L1224-1233).

Note: there is no replace-atom! MeTTa op at HEAD. PATCH-2 from the AtomSpace Integration Phase 4 plan recommends adding it.

Built-in Modules

lib/src/metta/runner/builtin_mods/mod.rs registers six loaders:

  • random, skel, fileio, json
  • catalog (pkg_mgmt Cargo feature)
  • das (das Cargo feature, default-enabled per lib/Cargo.toml:46)

Each module pairs a .rs registration file with a .metta doc file (catalog.metta, das.metta, fileio.metta, json.metta, random.metta, skel.metta).

DAS is available as a default feature and builtin module surface, but this does not mean a running distributed DAS service is embedded in the local runtime — metta-bus-client connects to a remote DAS service.

Module System

Implemented and active but still evolving (per the "poor man's" public/private scope concept in docs/modules_internal_discussion.md).

lib/src/metta/runner/modules/mod.rs:

  • ModId (L27), MettaMod (L56), resource and loader fields (L58, L62)
  • import_dependency_as (L107), import_item_from_dependency_as (L131), import_all_from_dependency (L181)
  • Accessors path/name/package/space/tokenizer/resource (L251-278)
  • Descriptor state (L314), module init (L439), ModuleLoader trait (L563), Resource (L608)
  • Name resolution at mod_names.rs:265 and :276

Imports via import! (registered at stdlib/module.rs:290) create separate DynSpace instances.

AtomIndex / AtomTrie

The in-memory atom index lives in hyperon-space/src/index/:

  • AtomIndex (mod.rs:159), insert (:177), query (:192), remove (:207)
  • AtomTrie (trie.rs:201, 930 lines), insert (:232), query (:261), remove (:395)

Concentrated implementation period 2025-01-31 to 2025-02-11 (initial implementation, GroundingSpace integration, duplication strategy parameter, AtomStorage/AtomTrieNode separation, compactness improvements). Size-prefix optimization landed at 120c2279 (2025-08-26) — "Prefix expressions with size in atomspace index to recognize them faster".

No quantitative scaling ceilings are claimed at this time. The existing benches at hyperon-space/benches/atom_index.rs and lib/benches/grounding_space.rs operate at 100 / ×10 / ×100 atom scales only; an empirical bench harness would be required for any production scaling claims.

Hyperon Space Write API and Observer Pattern

(Phase 4 prior art — re-confirmed at HEAD.) The Hyperon Space write surface is complete at the Space / C / Python layers:

  • SpaceMut::add / remove / replace at hyperon-space/src/lib.rs:237/255/275
  • GroundingSpace[D] (generic over duplication strategy D) concrete impl at lib/src/space/grounding/mod.rs:14-21; inherent add/remove/replace at :70/:92/:119
  • C-API write surface at c/src/space.rs:140-143; observer registration at c/src/space.rs:464
  • Python write surface at python/hyperon/base.py:205-221
  • SpaceObserver / SpaceEvent / SpaceCommon observer pattern at hyperon-space/src/lib.rs:22-126
  • Single-process / single-threaded by intentional design (per maintainer comment at c/src/space.rs:117-119)

PATCH-1 (required for the Phase 4 mirror integration): the pybind11 binding for space_register_observer in python/hyperonpy.cpp is missing. Two strategies exist for closing the gap — a Rust-only bridge service (the Phase 4 implementation plan), or contributing the binding upstream via pull request.

Python Bindings

Broad coverage, with one gap:

  • SpaceRef (base.py:168), add_atom/remove_atom/replace_atom (L205-221)
  • RunnerState (runner.py:24), MeTTa class (L107), run (L206), evaluate atom (L216)
  • hyperonpy.cpp:1017-1026 interpreter stepping
  • hyperonpy.cpp:1047-1053 type checking and lookup
  • hyperonpy.cpp:1070-1122 run context, MeTTa construction, module loading

Gap: Python observer registration is not bound (PATCH-1 above).

EventAgent (PR #852, merged commit 2fd826d4 2025-03-14) ships at HEAD: python/hyperon/exts/agents/agent_base.py:202-293 defines EventAgent, with BasicEventBus at events/basic_bus.py:6. EventAgent uses a generic event bus, not bound to SpaceEvent/SpaceObserver — they are disjoint event paths in the same repo.

C Bindings

Broad runtime surface in c/src/:

  • space.rs:69 space_new; :140-170 add/remove/replace; :184-237 query/subst/count/iter; :401-419 event accessors; :464 space_register_observer; :632-673 event constructors
  • metta.rs:838-882 MeTTa instance construction; :957-969 space/tokenizer accessors; :1005 parser-input run; :1035 atom evaluation; :1062-1094 module loading; :1305-1407 runner-state stepping

The C headers are auto-generated by cbindgen (per c/cbindgen.toml); there is no source-controlled c/include/ directory.

Sandbox Modules

python/sandbox/ is a prototype zone, not part of the packaged Python module (python/pyproject.toml:38 packages only hyperon).

ModuleStatusNotes
sql_spacePrototypePostgres custom-Space; 130 lines; naive SQL string concat; not production
morkPrototypeTODOs at L32, L47
neurospacePrototypeNeuralSpace, IntentSpace
jettaExample onlyRequires cloning trueagi-io/jetta
numpyPrototypenumme.py experimental
pytorchPrototypetorchme.py Func-Signature JSON for type-aware tensor ops
bhv_bindingUnclassifiedNot enumerated
replUnclassifiedRelationship to top-level repl/ Rust crate not characterized
resolveUnclassifiedNot enumerated

These sandbox modules are precedent and examples, not packaged, supported interfaces.

Test Coverage

Multilayer:

  • Rust library tests in lib/tests/ + inline #[test] blocks (52 in interpreter.rs, 38 in types.rs)
  • C tests in c/tests/: check_atom.c, check_runner.c, check_space.c, check_types.c
  • Python tests in python/tests/
  • DAS integration tests in integration_tests/das/
  • Test-corpus path-count: 101 files

(This is a static inventory; the tests were catalogued, not executed.)

v0.2.x Runtime Quirks Re-Verified at v0.2.10

Three runtime quirks were originally documented at v0.2.1; they are re-verified here at HEAD 3f76dc46 (v0.2.10):

  • Q-1 — bind! + new-space: confirmed at HEAD. BindOp::execute (stdlib/module.rs:269+) registers a token in the tokenizer. No code path clears or garbage-collects atoms in an already-bound space. Operational guidance: do not treat !(bind! &name (new-space)) as a reset of an existing live space. Use an explicit (match &name (pattern) (remove-atom &name (pattern))) workaround.
  • Q-2 — cond: fixed since v0.2.1 (by removal). cond is not a builtin operator at HEAD. Use if, case, match, or user-defined equations. The original v0.2.1 quirk ("cond is non-reducing") no longer applies because cond is not implemented.
  • Q-3 — catchall multi-reduction: confirmed at HEAD. This is documented nondeterministic semantics, not a defect. Programs requiring deterministic dispatch must use mutually exclusive patterns — e.g., enumerate all symbols explicitly instead of relying on a generic variable fallback.

Provenance

This card is the deep-dive reference for Source 1 of the MeTTa runtime documentation pass (a three-way reviewer reconciliation, completed 2026-05-08). The full reconciliation and the Phase 4 write-API prior art are archived in the wiki repository at:

  • scripts/archive/metta_runtime_pilot/source1_hyperon_experimental/findings_reconciled_crossmodel.txt
  • scripts/archive/atomspace_integration_phase4/source2_hyperon_space_writeapi/findings_reconciled_crossmodel.txt (Hyperon Space write-API + observer pattern; PATCH-1 / PATCH-2)