trioron — a guided tour

Watch a single substrate cell grow into a population that learns to feel. Each chapter has one knob — the same one you'd pass into the trioron API. The simulation is stochastic, so replay any scene to see a different path through the same mechanism; the trend is reliable, the exact path is not.

population: 0 / 200  ·  divisions: 0
1 / 3Genesis

this is the substrate. it knows nothing yet.

8
1.00× slow it down to watch the red frustration glow build before division fires
↓ low
↑ high
visual

trioron API equivalent: trioron.Substrate(l0_dim=8)

geometry & mechanics — the math
valence(x) = 2·(x − cx) / W     ∈ [−1, +1]    (positive = right side of dish)
arousal(y) = 2·(cy − y) / H     ∈ [−1, +1]    (positive = upper half)

cell.specialty (hue 0..360°) = atan2(arousal(cell), valence(cell))
classify(point): nearest cell wins; correct iff hueDist(specialty, label) < 50°

frustration += 0.06 per miss; decays ×0.992 per tick
division fires when frustration > frustration_threshold

absorption fires when |donor − host| < absorption_radius
              AND donor.poolTag == host.poolTag        (or pool_match_required = 0)
              note: seed mismatch alone is lossless via W = R·S handshake;
                    pool mismatch (different shared factor S) is the deep blocker

dream: each tick picks nearby cell pairs, flares a synaptic downscale between them,
       capped at max_downscales_per_layer total flares per dream phase

apoptosis: cells with firing-recency > 200 ticks fade out; floor at MIN_LIVE_POP = 5
           phase A — L1 branch (body) fades over ~40 ticks
           phase B — L0 ring lingers as a ghost ~80 ticks → substrate is conserved

decision boundaries (Russell circumplex):
  valence_thickness ∝ mean over cells of |x − cx| / (W/2)   (HAPPY ↔ SAD axis)
  arousal_thickness ∝ mean over cells of |y − cy| / (H/2)   (ANGRY ↔ CALM axis)
  each axis thins when the task that built it loses replay

inner_ring_radius (L0) = 2 + l0_dim × 0.5
body_radius        (L0 + L1) = inner_ring_radius + branch_width × 0.5
where the metaphor diverges — read this if you're going to build with the real API

The petri dish is a guide, not the architecture itself. Some of its visual mechanics are architecturally accurate; others are simplifications or proxies. The table below lists every conflation worth flagging.

visual in the dishwhat it really isnote
branch_width → outer body size; wider = faster spatial spread → faster convergence L1 hidden width per branch — per-specialist capacity Capacity does not speed convergence in real trioron. Demo's spread-effect is purely a side-effect of repulsion physics + division spawn-distance scaling with body radius.
inner-ring color (different lineage = "wrong seed") pool tag = shared factor S in W = R·S Seed mismatch alone is solved by the 4-byte handshake (bit-exact). Different shared S = different training pool, which is the real semantic blocker scene 7 is about.
apoptosis: cell fades to nothing L1 branch is pruned; L0 substrate is conserved Why phase B leaves an L0 ghost ring. The shared substrate isn't destroyed — only the specialist branch's parameters are.
division: child appears at 1.6 × outerRadius from parent no spatial analog — growth = adding hidden nodes (n_grow_per_task) Trioron has no 2D space. Demo uses spatial separation as a stand-in for "new specialist for unmet data."
frustration as a red glow around a single cell per-step loss accumulation against a per-task running threshold Glow location in the dish is meaningful (which specialist is failing) — the actual trigger math (eps-loss, see triggers.py) is per-task, not per-cell-position.
manifold replay = ghost data points re-firing sampling from stored per-class (μ, σ) on L0 latent code-space Architecturally accurate at the conceptual level. The ghost data points are the replay; the demo just shows them at the same coordinates as the original task instead of in latent space.
donor "drifts in" then "docks" a pretrained branch is added to a MultiBranchOrganism via api.absorb() The spatial approach is theater; in reality absorption is instantaneous given compatibility (paste-and-go).
population_cap = ceiling on visible cells cap_bytes ceiling on trainable parameter bytes (ceilings.py) Cap is parameter-byte budget in real trioron, not headcount. The demo proxies it as headcount because cells in the dish all happen to have the same parameter footprint.

legend