SyFox / docs /ARCHITECTURE.md
Mr-DS-ML-85's picture
Upload folder using huggingface_hub
2b2bae2 verified
|
Raw History Blame Contribute Delete
31.6 kB

SyFox Architecture — the SI substrate core

This document specifies exactly what happens between "state in" and "decision out", and which mechanisms are ported from the Synthetic-Intelligence (SI) research substrate. The rule that governs this codebase:

The core is SI physics only. No transformer, no neural network, no pattern-matching classifier. Everything below is field dynamics over an explicit concept graph. Tools (JSON, CLI, HTTP, calibration math) live outside the core and never rewrite it.

1. Concepts and acoustic mass

Every lowercase folded token interned by the engine becomes a concept node (core/si_substrate.hpp, Substrate::intern). Nodes carry:

  • mass — a raw occurrence count: intern() adds exactly 1.0 each time the concept appears in any lesson. It is linear, not log-compressed. Lineage: SI "acoustic mass" — heavier units respond less to the same stimulus. The sub-linear behavior lives at the use sites, not in the counter: injection deposits energy / sqrt(mass) and Hebbian bind strength scales by 1/sqrt(mass), so frequent concepts ("the", "please") cannot flood the field.
  • energy — transient; injected and dissipated per decision.

(An earlier revision also carried a salience field. Audit found it was write-only — incremented at injection, read nowhere; gating selects sources by energy — so it was removed. Dead state in the core is doc debt.)

Token folding (fold) is deterministic string normalization (plural / -ed / -ing / trailing e), applied identically to states, options, and instructions. It is I/O hygiene, not linguistics and not pattern matching.

2. Lanes (Hebbian bindings)

Lanes are weighted edges between concepts, stored sparsely per node with a per-node lane cap (weakest lane evicted, bounded memory).

  • Bind (hebbian_lesson): for a labelled lesson, every active state concept binds to every outcome concept with η · (1/√mass_a + 1/√mass_b) · scale. Adjacent state tokens also bind (the co-occurrence fabric that lets energy diffuse inside a phrase). Lineage: SI Hebbian lane bindings in physics.hpp.
  • Weaken (weaken): counter-evidence subtracts lane weight; a lane whose weight reaches zero dissolves. Used by Noul lessons labelled false.
  • Decay (lane_decay): every lesson multiplies all lanes by 0.995 — unused routes fade.

Learning is substrate rewiring. There are no fitted weights anywhere in the core; the calibration tool (below) is external and read-only.

3. Injection

A state is tokenized; every token that exists in the vocabulary deposits inject_energy / sqrt(mass) on its node. Unknown tokens stay dark — this is the first half of the honest-silence contract (a state of nothing but unknown words settles zero energy and defers).

4. Settle (the System One pass)

settle() runs up to k_settle (default 8) dissipative diffusion passes:

  1. Sources are gated by source cap (source_cap, 24 by default): the top-K nodes propagate each pass — ranked by energy by default, or by salience when salience_gating is on. Gated nodes keep their energy (they remain readout-visible); the cap gates flow, it does not annihilate. (An earlier version pruned energy outright and destroyed 97% of the field — the gating form is the correct physics and the tests pin it.)

    SI salience lineage, restored after audit. The SI substrate runs a cavity salience integrator, s = tanh(s·decay + gain·|velocity|) (physics.hpp, salience_gain = 0.05, salience_decay = 0.995), and its TSDA layer samples the live working cap from [working_cap−4, working_cap] = [5,9] (Miller 7 ± 2). SyFox ports both: the integrator runs every pass on the motion proxy |ΔE| (a node at rest is an exact fixed point, mirroring SI's sparsity guard), and miller_window = true samples the live cap from [source_cap−4, source_cap] each decision. One deliberate adaptation: SI draws the sample from a seeded mt19937 stream; SyFox derives it from the decision's state hash, so the same state always settles to the same field bit-for-bit (the persistence contract outranks stochasticity). inject() spikes salience to 1.0 on touch (TSDA spike semantics).

    Benchmark (10 in-domain decisions, 3 domains). default energy gating 10/10 with calibrated-shaped confidences; salience ranking at the wide cap 4/10 (motion history is a poor selector when the cap rarely trims); salience + literal [5,9] window 10/10 argmax but probabilities saturate at 1.0 (calibration collapse — needs the v0.2 eval harness before adoption); Miller window at wide cap 9/10. Verdict: default stays energy-gated at a fixed 24; the SI-faithful modes ship behind config flags until a held-out eval says otherwise.

  2. Each source retains (1 − diffusion) of its decayed energy and flows diffusion out along its lanes, split proportionally to lane weight: next[b] += e·decay·diffusion·(w_ab / Σw_a).

  3. Total energy is non-increasing (dissipative); the pass loop stops early when the field relaxes (total_before − total_after < eps).

One settle per decision — all questions read the same settled field. Adding questions never re-settles the substrate: flat marginal latency by structure, not by scheduling.

Derivation, not retrieval. Because diffusion is multi-hop, a state that was never in any lesson still settles to a computed answer: energy crosses the co-occurrence fabric into outcome lanes laid down by other lessons. Probe (two lessons, alpha beta→x and beta gamma→y): the untaught state alpha alone settles with y at 0.494 — lesson 2 never mentioned alpha; the two-hop path alpha→beta→y carried the evidence. The boundary is the taught vocabulary and lane fabric: concepts never interned have no node, unknown words settle to zero energy and defer (§6). This is the substrate-level kernel of the SI stack's explicit derivation layers (meta-learner macro-rules, dreamer emergent resonances, analogical mapping) — not yet ported; see ROADMAP v0.3.

5. Readout (resonance sweep, two lanes)

Probes read the settled field at their own concepts: direct node energy plus a hop term through lanes. Two readout lanes exist because two question shapes need two different questions of the field:

  • Specific (choice, score): mean lane support — hop · Σ w·e_n / Σ w. Rewards precise coupling; a node bound diffusely to half the vocabulary cannot out-read a node bound exactly to this state. Options are then normalized by softmax at the fitted temperature.
  • Support (noul): active lane mass — hop · Σ w·e_n (unnormalized). A statement may be corroborated broadly; what matters is how much lane-connected energy the field offers it. The ratio to total field energy is the statement's support.

Both are field measurements. No weights are fitted at readout; no classes exist in the core.

6. Honest silence

If settled field energy is below silence_floor (0.05):

  • empty state → deferred: true, reason: "empty_state"
  • all-unknown vocabulary → reason: "unknown_vocabulary"
  • settled but dark → reason: "honest_silence"

The engine refuses to guess from nothing. Lineage: the SI interface's honest-silence dispatch — answers only when the readout actually collapsed.

7. Calibration (a tool, not core)

fit_calibration collects readout energies on labelled rows and fits, purely outside the core:

  • temperature per choice/score — golden-section search on NLL of softmax(E_correct/T, E_wrong/T).
  • Platt scaling for noul — logistic regression sigmoid(a·support + b) on supports, gradient descent to convergence (separable data needs a steep slope; the fit runs 4000 iterations with decaying lr).

Calibration changes how energies are reported as probabilities, never how they are produced. Confidence for choice/score is the normalized-entropy margin of the distribution; for noul it is |p − 0.5|·2.

8. Persistence

save_model writes substrate.bin (vocabulary + masses + lanes, binary), calibration.json, and meta.json. Loading is exact — the same state settles to the same readout bit-for-bit (pinned by tests).

9. Provenance

Mechanism Origin
Energy injection + field settle SI physics.hpp substrate dynamics
Source capping (top-K, energy or salience) SI working-set cap + TSDA live_cap ([cap−4, cap], Miller 7 ± 2)
Salience integrator tanh(s·decay + gain·motion) SI physics.hpp cavity salience (verified live there)
Hebbian lane bindings + decay SI lane learning
Honest silence SI dispatch contract
Typed Choice/Score/Noul API interface shape inspired by TypeSafe Jev
Temperature/Platt calibration classical statistics (tool layer)
Derivation layer (§10) SyFox-native design after studying SI meta_learner / dreamer / analogy as mechanism reference — no code copied; weight algebra on lanes instead of typed relation rules
No-regression gate (§11) SyFox-native: transactional derive + bit-exact fabric snapshot/restore; policy refined by a full strength-scan (taught-row integrity + no manufactured certainty)
Jev-parity bench (§12) SyFox-native: axis lineage from TypeSafe's published Jev material + community classification benchmarks; all numbers produced by this repo's binary
Recall (§13) Hopfield-style associative memory reinterpreted as settled-field cosine — SI-physics-native, zero symbol-space similarity

10. Derivation layer (offline, explicit)

SyFox's lanes so far carried only lived experience (learn). The derivation layer lets the field grow knowledge derived from its own fabric — the substrate-level kernel of what the upstream SI stack does with explicit rule machinery (meta-learner macro-rules, dreamer emergent resonances, analogical mapping). The primitives differ by constitution: SI composes typed relation triples over a fact graph; SyFox composes weighted lane paths — weight algebra and field dynamics, no classifiers. All engines are OFFLINE, explicit CLI steps; decide() stays read-only and byte-identical unless the operator derives on a model. Provenance: derived lanes carry a generation counter (experienced / human-promoted = 0, each composition step +1, cap 3), persisted as a versioned tail in substrate.bin; v1 files load clean (generation 0).

1. Lane induction, compose mode (syfox derive --model DIR): a two-hop path A→B→C is evidence for A↔C, with three guards that each came out of a real benchmark failure:

  • acoustic-mass damping — path evidence is damped by 1/√mass(B), the same law settle() applies to energy through B; without it, hub tokens ("the", "command") fabricated corroboration between unrelated concepts and two demo argmaxes flipped;
  • top-K corroboration (K=3) — a dense fabric offers hundreds of two-hop paths; treating them as independent evidence saturated the field (noul collapsed to 0.999 everywhere);
  • ghost-guarded verifier — every derived lane is re-checked against the LIVE fabric (snapshot ghosts of already-dissolved lanes cannot justify anything), over-claims are healed down to their justification, unsupported ones dissolve. Composition is raise-only: observed lanes are never weakened.

2. Lane induction, harvest mode (syfox derive --model DIR --examples FILE.jsonl): static algebra guesses; the settled field knows. Replay states through inject→settle and record which concept pairs genuinely co-activate. Dissipation does the filtering — cross-scenario energy decays before it registers. Observed lanes are untouchable; gen-1 lanes must be re-nominated by every run or they dissolve (justification is recomputable, hence deterministic). Labels are not needed: the field learns structure from unlabelled exposure.

3. Dreamer (syfox dream --model DIR [--steps N] [--seed S]): inject small random energy patterns, settle, and watch for undriven nodes that lit up without any direct lane to the driven set — reached only through the topology's own interference. Candidates go to model-*/mutations.jsonl. The substrate is never modified by dreaming; a human sets validated:true on a line and syfox promote applies it as a premise-grade lane. Same seed → same dream, bit for bit.

4. Analogy (syfox analogs --model DIR --concept WORD, read-only): a concept's signature is its lane neighbourhood (who it touches, both directions); structural isomorphism = signature Jaccard; novelty potential follows the L9 formulation Phi = I·exp(k·d). High Phi = structurally aligned AND fabric-distant: a transfer hypothesis for the human, never auto-applied.

Benchmark (v0.2 → v2.1, honest). The v0.2 verdict was measured on resubstitution (eval rows = training rows): compose sharpened tickets demos (technical conf 0.251→0.454) but flipped game/guard rows; harvest lifted billing 0.604→0.912 but flipped a close call; no strength avoided taught-row flips on the mixed-label fabrics. v2.1 replaces the measurement basis: the gate now replays the HELD-OUT split (generalization safety, not memorized behavior) and the harness decides per model — game ships derived (253 lanes, 0 held-out flips, accuracy held 0.667→0.667), tickets (9 flips) and guard (1 flip) ship un-derived with the reason logged. Same enforcement philosophy, honest measurement basis.

11. The no-regression gate (transactional derivation)

Derivation writes into the fabric; the gate (core/gate.hpp, CLI syfox derive --gate FILE.jsonl) makes that write safe by construction:

  1. replay every labelled row + generated close-call probes (cross-domain state mixtures, deterministic generator shared with bench) → baseline decision signatures;
  2. snapshot the fabric bit-exactly — snapshot_fabric() copies each node's lane vector in insertion order plus the provenance map, because settle() sums over lanes in vector order (a weight set is not the state);
  3. run the derivation (conservative presets: harvest co_floor 0.15/gain 0.35/budgets 8·512, compose gain 0.25/top-2/budget 4);
  4. replay the same probe set → compare;
  5. policy: (a) any argmax flip on a TAUGHT row reverts — labelled knowledge must survive derivation; (b) any RISE in mean confidence on the MIXED probes reverts — close-call states are ambiguous by construction, their argmax may re-resolve, but manufactured certainty about them is the exact failure the gate exists to kill;
  6. revert = restore_fabric(snapshot) → the fabric is bit-identical and decide() output is byte-identical (pinned by test); commit = the caller saves the model.

Strength-scan evidence (scripts/syfox_gate_scan.cpp, all strengths from default down to 32 lanes): tickets reverts everywhere (8–18 taught flips — its seed data mixes refund/invoice labels across billing and sales), guard reverts at every useful strength, game commits at the conservative strength. Per-model outcome: model-game ships derived (668 lanes, 0 taught flips, mixed mean confidence 0.975→0.886 — the fabric got MORE honest about close calls; demo argmaxes 3/3 unchanged; make models reproduces). model-tickets and model-guard ship un-derived because the gate proves it, not because a human remembered to check.

12. The Jev-parity benchmark (syfox bench)

core/bench.hpp measures the axes the System One model class is judged on (axis lineage verified against TypeSafe's published Jev material and the community classification benchmarks, Sept 2026): decision accuracy, latency percentiles, calibration (ECE, 10 bins, + conf-when-correct vs conf-when-wrong gap), honesty (OOD probes built from deterministic nonsense vocabulary checked against the model's own — untaught tokens must defer), guardrail hold precision/recall (noul confusion at the 0.5 threshold), determinism (full replay compared byte-wise), and close-call margin distribution (mixed cross-domain states; the same generator the gate replays). Accuracy/calibration/guardrail aggregate over LABELLED rows only; unlabelled mixed probes never pollute accuracy denominators (a real bug the e2e suite caught). Every report carries a jev_reference block with the PUBLISHED figures (67.8% workflow accuracy, 70–500 ms, pi-warden 88% hold precision) for side-by-side reading — axes shared, numbers not compared against toy-data resubstitution.

Seed-model results, v2.1 methodology — HELD-OUT split (70/30, stratified, deterministic; make bench-heldout), post-gate derivation state. The v0.2 table that stood here measured in-domain resubstitution (eval rows = training rows) and is retired; in-sample numbers remain available via make bench as a regression contrast only.

model held-out choice acc (n) score acc (n) choice ECE OOD defer p50 / p95
tickets 1.000 (6) 0.667 (6) 0.012 1.00 64 / 80 µs
game (derived, gate PASS) 0.667 (3) — 0.329 1.00 29 / 40 µs
guard 0.750 (4) — 0.200 1.00 34 / 45 µs

Reading: the held-out gap against in-sample (tickets 1.000 vs 1.000; guard 0.750 vs 0.778) is now measured instead of assumed. Calibration is fitted on held-out rows only (2–3 scalars; multi-class NLL objective, 1-bit ECE adoption guard) — tickets reaches ECE 0.012; game/guard are held above the 0.1 bar by a single held-out error each, which is arithmetic (1 wrong of 3–4 emitted forces ECE ≥ ~0.2), not a tuning failure. The headline metric is the coverage-vs-accuracy curve (make coverage): tickets trades 100% coverage @ 83.3% accuracy for 50% coverage @ 100% — the confident subset is trustworthy, measurably. Paraphrase augmentation was implemented, measured on the held-out split, and REJECTED by default (intern mass is linear, injection damps 1/√mass: re-teaching near-duplicates re-weights the field toward the training surface forms; tickets 1.000 → 0.500). The derivation gate replays held-out rows and decides per model: game ships derived, tickets/guard ship un-derived. Honesty stays structural (1.00 OOD defer everywhere); latency is three to four orders of magnitude under the Jev band with the same one-pass shape.

13. Recall (associative retrieval in energy space)

core/recall.hpp, CLI syfox recall --state '...' --memories FILE.jsonl. Content-addressable memory the only way the constitution allows: settle the query into an energy fingerprint (one float per node, L2-normalized), settle each stored memory the same way, rank by cosine of the two settled fields. No token comparison, no string distance, no n-gram overlap, no embedding table, no transformer — similarity is measured in the substrate's own state space, so two states resonate exactly as far as the field routes them together. Unknown vocabulary resonates with nothing (empty hits — honest silence, since inject skips unknown tokens). Read-only, bit-deterministic; memory stores accept {"state","label"} rows or the training schema (label = first label value). On the derived game model the zombie query recalls the flee lessons at 0.9696–0.9421 with fight lessons at ≤0.856.

14. v3 — the hidden-test firewall and the evidence ledger

14.1 Firewall (core/firewall.hpp)

The 70/15/15 train/cal/hidden contract is enforced where a typo cannot bypass it: the CLI consults the file's split role (decided by its filename suffix — _train, _cal, _hidden, _heldout, anything else is unclassified and stays readable, because worksheets and paraphrase files must remain learnable) before opening anything.

role suffix learn calibrate derive --gate bench
train _train.jsonl YES yes yes yes
heldout _heldout.jsonl yes YES yes yes
cal _cal.jsonl no YES yes yes
hidden _hidden.jsonl NO NO NO YES

Rationale: calibration files exist to fit 2–3 scalars (temperature/Platt) on rows the fabric never learned from. Hidden files exist to be SCORED, once. A hidden row that leaks into any build path is not a mistake — it is a different (worthless) number. make firewall-check runs the four refusals against the real binary.

14.2 Evidence ledger (v3, Milestone 3)

Every lane key carries a LaneEvidence record: support_events, counter_events (anti-Hebbian dissolutions), generation (derivation provenance), first_seq / last_seq (teach-event window), and the engine-set context tag (which substrate/model owned the event). The ledger persists as an optional tail on substrate.bin; v2 files load unchanged (the tail is detected at EOF) and v3 files load on v2 readers that stop at the v2 end.

decide --evidence projects the ledger for the lanes the decision actually used — a READ-ONLY view. The field is driven by lane weights; the ledger never feeds back into physics. It exists so a decision can be audited after the fact: which lanes, how strong, taught when, by which corpus, disputed how many times.

14.3 Contradictions

Teaching the same (state, question) with a different outcome is a contradiction: it increments the learn report's contradictions counter, writes a contradiction record (old outcome, new outcome, both seq numbers, state hash, context), and marks the affected lanes with a counter event — the anti-Hebbian term weakens the disputed binding exactly as the physics specifies. There is no last-write-wins: the field keeps the binding its weights support, and the dispute stays on the record (contested: true in the decide evidence view). Silent override is a design error, and the adversarial suite (§15 of the README; make adv-big) tests for it with a control arm that separates contradiction-specific damage from the generic cost of re-teaching.

15. v3 — multicore settle and the GPU gate (M5)

15.1 CSR mirror

The settle hot path reads a compressed-sparse-row mirror of the out-lane fabric: csr_off_ (n+1 offsets), csr_dst_, csr_w_ — contiguous buffers, rebuilt lazily when the fabric mutates. The build copies each source's lane vector verbatim, so per-source iteration order is exactly the map order the sequential settle used: every float sum keeps its exact operand order and results are bit-identical. This is the layout a GPU port generalizes.

15.2 Deterministic OpenMP settle

make omp builds the same sources with -fopenmp. The diffusion pass partitions sources with a static schedule (contiguous ascending chunks); each thread scatters into its own buffer; the buffers are combined in ascending thread order; therefore every accumulator sees contributions in ascending SOURCE order — the sequential order. Bit-identity is a gate, not a hope: make omp-identity fails the build if sequential and --threads 2 reports differ in any block (routing, calibration, honesty, guardrail). Measured honestly: below ~10k nodes on a 2-core sandbox the deterministic parallel settle is slower than sequential (thread coordination exceeds the gain); it pays on denser fabrics.

15.3 Batched throughput and the GPU gate

bench --throughput N measures decisions/sec with N worker threads, each owning a PRIVATE engine copy (decisions mutate the field, so workers never share a substrate). It is a performance axis, not an accuracy headline — a non-zero checksum proves the work happened. Measured on the 3,518-node tickets fabric: 2,390 → 3,714 decisions/sec at N=2 on 2 cores.

The GPU port gate is MEASURED, not assumed: make density reports per- fabric density and mean out-degree (tickets 0.0067 @ degree 23.5, game 0.0458, guard 0.0485). A GPU port happens when dense substrates make the transfer costs pay for themselves — until then it stays design, and the SoA/CSR buffers above are the only GPU-specific preparation the core carries. No neural network enters the core at any point; the parallelism is the SAME physics, executed on more cores.

16. v3.2 — the semantic field, context-sensitive lanes, retrieval by default, the two-stage router

The largest boundary-layer addition since v3.0, and the first that adds a second field to the substrate. Everything below is deterministic, seeded by nothing, fitted to nothing — there is still no neural network, no transformer, and no pattern-matching classifier in the core.

Stage 1 + 4 — the semantic vector field (64-dim, resonance)

Every concept node carries a 64-dim semantic vector built in two deterministic steps. The LEXICAL LAYER hashes the concept string's character trigrams into 64 buckets with FNV-1a-signed weights and L2-normalizes — "card_arrival" and "card_delivery" share trigrams, so their base vectors align; unrelated words stay near-orthogonal. FABRIC GROUNDING then runs two smoothing passes over the Hebbian lanes (v_i <- normalize(v_i + 0.5 * lane-weighted mean of v_j)): the fabric's own co-occurrence structure shapes the vectors, which is meaning diffusing along the lanes, not a fit. From the vectors, three derived quantities:

  • omega_semantic (Stage 1, "concept frequency encoding") — a scalar projection onto one fixed deterministic direction, mapped to [0,1]. Two nodes with close omega resonate harder, like coupled oscillators that are nearly tuned; the fixed axis makes "card" map to the same omega in every fabric.
  • resonance edges (Stage 4, "semantic field") — the top-6 cosine neighbours with cos >= 0.50, stored as a CSR adjacency in the substrate's v4 file tail. During settle, every SOURCE (and only sources — the working set stays capped) leaks a fraction (sem_coupling 0.12) of its post-diffusion energy along these edges, distributed proportionally to cos x frequency-match. Energy is CONSERVED exactly: the pool is subtracted from the source and distributed; decay applies next pass as always.
  • typed reads (Option 2) — cos >= 0.82 reads as synonym-grade kin, >= 0.66 as related; syfox analogs and the evidence surface expose the type. The v2.1 synonym folding table remains the string-level canonicalization; the vectors add the fabric-shaped layer above it.

Readout gains a semantic-neighbour term (sem_hop 0.10 x cosine x neighbour energy): energy resting on semantically similar nodes counts for a probe even where no lane connects them.

Stage 2 — context-sensitive lanes

A lane may carry a CONTEXT SIGNATURE: required and forbidden context words, learned from the co-occurrence statistics of the lessons that laid it (add_ctx_support accumulates counts at learn time; finalize_contexts promotes surviving counts — top-4 with count >= 2 — into required sets, and cross-lane diffs (strong in a sibling lane's context, absent here) into forbidden words, top-2). At settle, a lane's effective weight is w x factor: any forbidden word present in the decision's own injected tokens -> x0.20; required words missing -> x0.60..1.0 interpolated by match count; all present -> x1.0 (bit-identical to the plain path). The node's total outflow scales by sum(w x f)/sum(w), so damped lanes carry LESS and the energy stays home — context-mismatched routes fade physically instead of being pruned by a rule. The same "card" can now route toward card_arrival when arrive/receive are in the state and toward card_delivery_estimate when estimate/how-long is.

Persistence and the replay contract

The semantic field, resonance edges and lane contexts live in a magic- guarded v4 tail of substrate.bin. Pre-v3.2 files simply end at the v3 evidence tail: has_semantics() is false and every semantic code path is inert, so every v2/v3 model replays bit-for-bit under the new binary (test-enforced). intern() invalidates the field when the fabric grows — a stale top-k neighbourhood must never be indexed — and the next save_model() rebuilds it deterministically. --no-semantics / set_semantics(false) is the runtime kill switch.

Retrieval by default

A model dir may ship memories.jsonl (rows {"label": ..., "state": ...}). load_model fingerprints each memory once (its own settled field, the recall.hpp Hopfield-style mechanism); every decide then ranks memories by settled-field cosine against the query and injects the top-5 outcomes at a faint dose (0.30 x inject_energy) BEFORE the state settles — a physical prior from lived experience, deterministic, bit-reproducible for the same state + memories. No memories file => the whole path is inert (pre-3.2 behavior). Flags: --memories FILE (explicit store), --retrieval-topk, --retrieval-dose, --no-retrieval. usage.retrieval discloses what primed the decision, in the CLI, the C API and the HTTP bridge alike.

Stage 3 — the semantic hierarchy

A model dir may ship hierarchy.json {"intents": {intent: category}, "categories": {category: {"criteria": ...}}, "floor": 0.35}. Both levels are TRAINED anchors in one fabric; at decide, stage-1 category energies scale the stage-2 intent candidates by floor + (1-floor) x cat/max_cat — a readout-side two-stage classification. MEASURED on bank77 (cal, 1,003 rows): gate OFF 0.133 > floor 0.85: 0.129 > 0.5: 0.113 > 0.35: 0.111 — the category readout is not additive on this fabric (consistent with the v3.1.0 finding that the hierarchical first-token split was measured-negative), so the shipped model-b77-sem carries floor 1.0 = gate off, kept as documentation. The mechanism stays available (--no-hierarchy to disable elsewhere).

The dedicated bank77 fabric + the two-stage router

The v3.2 answer to high-cardinality collapse is ARCHITECTURAL, as the v3.0 design intended: a DEDICATED fabric per hard domain, routed by a small dedicated router fabric.

  • model-b77-sem (dedicated bank77): 9,000 intent lessons + 9,000 category lessons (12 chunks), 1,648 nodes / 217,729 lanes, 7,728 resonance edges, 141,920 lane contexts, 256 retrieval memories, calibrated. Hidden (3,080 rows, scored once, energy-norm): 0.158 — vs 0.081 (v3.1.0 dedicated+opaque) and 0.023 (77-way in the shared giant fabric). Ablations on cal: --no-semantics 0.039 (the semantic field is the jump: 0.039 -> 0.133), retrieval neutral, hierarchy gate negative (above).
  • model-router16 (two-stage, stage 1): a 4,742-node fabric trained ONLY on router questions (16 anchors, one per giant domain, 60 rows/domain). Cal 16-way routing 0.444 (chance 0.0625), ECE 0.380 -> 0.086. decide --router model-router16 ... settles the state on the router fabric, picks the domain anchor, then the mapped domain fabric (router.json "models") decides the real questions; the route is disclosed in the output as route:{anchor,confidence,top,model}. Physics-based routing, no classifier — the two-stage architecture from the v3.0 design, now measured.

Zero-shot, re-measured under v3.2 (docs/ZEROSHOT.md Part 4)

Email spam on the tickets-only fabric (never taught spam): 6/6 (plain) and 6/6 (semantic rebuild). SMS spam: 5/6 both. Snake on the giant fabric: 1/8 both; Tic-tac-toe: picks 1 at conf 0 — multi-constraint composition is still not a fabric property, and the semantic field does not fake it. Honest as ever: the semantic field moves TRAINED-discrimination and vocabulary-overlap zero-shot, not symbolic reasoning.