Energy / Co-evolution Engine — Parameter Reference & Scenario Plan
Living document. Last updated (after the §17 demand-/depletion-limited CAPTURE fix). Authoritative catalog of every knob in the chessboard engine (compute/scripts/evolve.py), what it means, its default, the methodology object it instantiates, its literature analog, and its dominant couplings — plus the scenario plan and expected regimes. Read with plan-energy-dynamics.md (build record) and design-energy-dynamics.md (vision/§14 unified model).
The coupling caveat (why this doc exists). Every parameter partially couples to every other through one shared balance
Δenergy = CAPTURE − TRANSFORM − MAINTENANCEand the share/influence logistic. It behaves like a coupled dynamical system: a change anywhere propagates (e.g. raisingextraction.halfslows drawdown → store stays high → ε stays high → more capture → faster climb → higher maintenance → …). There is no "independent" knob. This catalog plus the coupling map (§3) is the heuristic instrument until/unless we build an explicit state-space explorer. Discipline: regime-not-magnitude, observe-not-force, honest-negatives, cartography (all forms/params are analyst-modeled, open to challenge).
1. The model as built (one-screen review)
Per living agent, per step, in niche → resolved local context node:
move: agent strategy picks a transformation (directed|stochastic|follow|persist)
transform: cost = rate_weight · cost_scale · reconfig_factor(move) [if energy on]
energy < cost ⇒ STALL (no move; atrophy) [Inc-3 walls live here]
[population on] transformation must FIX: eff = realized_prob(p,N)·Pfix(s,N)
influence: logistic squeeze: influence ·= 1 + R·press·w ; press = 1 − occ/capacity
ENERGY: node pool/store → access split → capture → balance:
access_i = Pd(position) if energy.capture set, gated by store.gate, else influence
ε(s) = extraction efficiency on depletable stores (s = store/ref) [§17 / B]
capture_i = min( D_i , ε(s) · pool · access_i / Σaccess ) [§17]
D_i = demand ceiling (Holling-II saturation) if energy.demand set, else ∞
maint_i = flat scalar | Σ f(held levels) (P3 maintenance-of-complexity)
Δenergy_i = capture_i − last_cost − maint_i
energy ≤ 0 ⇒ DEATH (real removal, share redistributes, extinction event)
store = min(cap, max(0, pool − Σcapture) + replenish) [Inc-5]
stop: all dead | all done | horizon_years reached | max_steps
Emergent (NOT coded): parsimony-under-scarcity, boom-bust/overshoot-crash, layering-trap/walls, dilution/locality, drift-loss (popgen). Invariants: I1 (no energy block ⇒ byte-identical pre-energy) and I2 (§6d-legacy + P3 contexts ⇒ byte-identical) proven 11/11 byte-identical at every increment.
2. Parameter catalog
Notation: path is the JSON location in a compute/configs/contexts/<ctx>.json. "Methodology" = the Cx/Cm/etc. object it instantiates. "Lit" = §17.8 literature analog.
2A. Engine structure (no energy needed)
| Param | Path | Type / default | Meaning | Methodology | Key couplings |
|---|---|---|---|---|---|
arrangement | top | str (req) | which manifestation arrangement (biology/entity/…) | the domain | sets coherence manifold for _coherent |
chain_level | top | str (req) | level within the arrangement (e.g. organism-architecture) | Sc / chain level | sets primitive set + rate tables |
niches.<n>.capacity | niche | float (req) | finite competitive mass of the niche | Ecosystem Rg carrying capacity | × R ⇒ competitive equilibrium; default energy pool if no energy_pool |
agents[].mn / target | agent | str | start manifestation / directed endpoint | Mn | target may be omitted for non-directed strategies |
agents[].rate | agent | str | rate schedule key (calibration) | Tj / kinetics | sets rate_weight per move → transform cost & wall-clock |
agents[].influence0 | agent | float / 1.0 | initial competitive share weight | — | seeds logistic; default access when no energy.capture |
horizon_years | top | float / none | wall-clock stop (Σ rate·step_years) | Tj horizon | interacts with rate/step_years; deep-time domains need large values |
max_steps | top | int / 50 | hard step cap | — | truncates slow regimes; raise for long climbs |
2B. Energy — master switch & budget
| Param | Path | Type / default | Meaning | Methodology | Lit / couplings |
|---|---|---|---|---|---|
energy.enabled | energy | bool / false | turns the whole energy/selection/death layer on | — | OFF ⇒ I1 byte-identical (pure topo+logistic) |
energy.start | energy | float / 1.0 | initial per-agent energy (agent energy0 overrides) | initial Cx state | buffer before first starvation; couples to maint/cost |
energy.pool_per_step | energy | float / niche.capacity | flat per-step niche energy supply (non-store nodes) | Cx En availability (flow) | primary scarcity dial with maintenance.scale; Rosenzweig "enrichment" axis |
energy.cost_scale | energy | float / 1.0 | scales every transform cost (rate_weight·cost_scale) | Cm Cs (transform draw) | × rate_weight × reconfig = move affordability; raises stall rate |
2C. CAPTURE term (§14 unified + §17 fix)
capture_i = min( D_i , ε(s) · pool · access_i / Σaccess )
| Param | Path | Type / default | Meaning | Methodology | Lit / couplings |
|---|---|---|---|---|---|
energy.capture.form | energy.capture | flat-per-level|primitive-weighted|coherent-only / (absent⇒access=influence) | position-dependent capture capability (access) | Cm Pd (production/capture) | absent ⇒ legacy influence-share (I2). primitive-weighted ⇒ deep structure captures superlinearly |
energy.capture.scale | energy.capture | float / 1.0 | scales access weight | Cm Pd | only relative (normalized by Σaccess) — affects split, not absolute |
energy.demand.form | energy.demand | need-multiple|flat / (absent⇒D=∞) | §17(A) per-agent saturation ceiling | Cm Cs requirement-bounded draw | Holling Type II. absent ⇒ no cap (byte-identical). Caps how much of pool is actually drawn |
energy.demand.headroom | energy.demand | float / 2.0 | D_i = H·(last_cost+maint) (need-multiple) | metabolic requirement × buffer | H→1 knife-edge (no reserve); H large ⇒ ceiling rarely binds |
energy.demand.value | energy.demand | float / ∞ | D_i = V (flat form) | fixed absorptive capacity | flat ceiling regardless of need |
store.extraction.form | node | power|saturating / (absent⇒ε≡1) | §17(B) depletion-dependent extraction efficiency (depletable stores only) | Cm Cy (store) × Cx En state | Monod/Holling-II / Hotelling. absent ⇒ ε≡1 (byte-identical, one-step-drain) |
store.extraction.k | node | float / 0.0 | ε = s^k (power); k=0⇒ε≡1, 1=linear, >1 sharper | extraction-difficulty curvature | governs asymptote sharpness; k=0 is the byte-identical default |
store.extraction.half | node | float / 0.25 | ε = s/(s+h) (saturating) half-saturation | Monod K_s | smaller h ⇒ efficient until nearly empty; larger h ⇒ early throttling |
2D. MAINTENANCE & TRANSFORM (P3 + Inc-3)
| Param | Path | Type / default | Meaning | Methodology | Lit / couplings |
|---|---|---|---|---|---|
energy.maintenance (float) | energy | float / 0.05 | §6d flat scalar maintenance (back-compat) | Cm Cs basal draw | float ⇒ byte-identical §6d path |
energy.maintenance.form | energy.maintenance | flat-per-level|primitive-weighted|off-manifold-scaled / flat-per-level | maintenance-of-accumulated-complexity (the parsimony centerpiece) | Cm Cs of holding structure | dict opts into P3. primitive-weighted = convex (Σv²) ⇒ enables interior optimum |
energy.maintenance.scale | energy.maintenance | float / 1.0 | cost per held level | Cm Cs | primary scarcity dial with pool_per_step; raises parsimony pressure |
energy.maintenance.off_manifold_mult | energy.maintenance | float / 2.0 | ×cost when off-manifold (off-manifold-scaled) | coherence penalty (annotation→cost) | use sparingly: re-imports a coherence-as-fitness term (licensed-claims caution) |
energy.reconfiguration.rules[] | energy.reconfiguration | list {prim,at_or_above,factor} / none | Inc-3 analyst-declared wall: transform cost ×factor when raising prim≥level | open-Q#10 (declared, not derived) | × cost_scale = wall height; high factor ⇒ emergent never-cross (layering-trap) |
2E. Context / locality (Inc-2)
| Param | Path | Type / default | Meaning | Methodology | Couplings |
|---|---|---|---|---|---|
niches.<n>.energy_pool | niche | float / pool_per_step | niche-level energy supply override | Cx En (niche) | per-niche scarcity |
niches.<n>.context_nodes | niche | tree of {path: spec} | nested local Cx nodes (relaxation-resolved) | Cx locality co-varies Sc (§7.0) | enables dilution/locality; absent ⇒ niche is one flat node (byte-identical) |
<node>.energy_pool | node | float / base_pool | flat local-node supply | Cx En (local) | crowding N agents on one node ⇒ density dilution (emergent Rg) |
agents[].context_node | agent | str / none | agent's path in the context tree | Cx position | which local node the agent draws from |
context_resolution_depth | top | int / none | relaxation knob: truncate ctx_path to N segments | Sc-bounded view() | coarser depth ⇒ more agents share a node ⇒ more dilution |
2F. Depletable stores (Inc-5)
A context_nodes entry that is a store dict (has store) instead of a flat energy_pool.
| Param | Path | Type / default | Meaning | Methodology | Lit / couplings |
|---|---|---|---|---|---|
<node>.store | node | float (req for store) | initial finite stock; persistent across steps | Cm Cy stock | with replenish ⇒ boom-bust if consumption≫replenish |
<node>.replenish | node | float / 0.0 | per-step refill added back | Cm Cy cycling / Pd inflow | the oscillation dial: replenish ≪ draw ⇒ crash; ≈ draw ⇒ limit-cycle candidate |
<node>.cap | node | float / ∞ | max store (also ε reference if set) | carrying capacity of the stock | caps recovery ceiling; sets s = store/cap |
<node>.gate.prim / .min | node | str / int | access only if pos[prim] ≥ min (Pd-unlock) | Cm Pd1→Pd2 phase transition | the "unlock a new energy KIND" wall; absent ⇒ open (byte-identical) |
<node>.extraction.* | node | see 2C | depletion-dependent ε on this store | Cm Cy×Cx En | the §17 asymptote; without it the store one-step-collapses |
2G. Population-genetics layer (deep, opt-in; biology)
| Param | Path | Type / default | Meaning | Lit / couplings |
|---|---|---|---|---|
population.enabled | population | bool / false | turns deterministic expected-fixation on (techno: leave off) | OFF ⇒ byte-identical |
population.size / agent pop_N | population/agent | float / 1e3 | effective population size N | origination ∝ 1/(Np); drift if Ns≲1 |
population.per_trial_prob / pop_p | population/agent | float / 1e-2 | per-trial transition prob p | realized_prob = 1−(1−p)^N |
population.selection_coeff / pop_s | population/agent | float / 0.0 | selection coefficient s | Kimura P_fix=(1−e^−2s)/(1−e^−2Ns); s=0 ⇒ neutral 1/N |
population_context / agent population_context | population/agent | str / none | lit-calibrated N/p/τ file | wires quantitative literature checkpoint |
2H. Behavior / strategy (plan §6o)
| Param | Path | Type / default | Meaning | Couplings |
|---|---|---|---|---|
behavior.enabled | behavior | bool / false | enable per-agent move policy | absent ⇒ all directed (byte-identical) |
agents[].strategy | agent | directed|stochastic|follow|persist / directed | move policy | only energetically consequential once energy/maint makes the path cost (§17/P3) |
2I. Fixed model constants (NOT config — but part of the coupled system)
These are hardcoded in evolve.py; documented because they couple like parameters. Changing them is an engine change (design-review-first).
| Constant | Value | Where | Meaning | Note |
|---|---|---|---|---|
R | 0.15 | influence logistic | competitive growth rate | with niche.capacity sets equilibrium speed |
| press weights | done 1.0 / contender 0.4 (growth); done 0.3 / contender 1.3 (squeeze) | influence logistic | established shielded in squeeze, capture more in growth | bounded determination (no runaway first-mover) |
| dilution floor | tot = Σaccess or 1.0 | capture | divide-by-zero guard; regime discontinuity when Σaccess<1 (partial vs full split) | §17.6: ε+demand demote its significance; flagged for regime-map |
| death threshold | energy ≤ 0.0 | selection | hard removal (not soft decay) | extinction = discrete Convergence Collapse |
3. Dominant coupling map (the "PDE matrix", qualitatively)
The interactions that actually move regimes (use this to reason about a sweep before running it):
- Scarcity axis =
pool_per_step(or storereplenish) ÷maintenance.scale× held-complexity. Tight ⇒ parsimony wins (minimal lineages out-survive climbers); abundant ⇒ all sustain. This is the single most load-bearing pair. - Boom-bust axis = store
store/replenish/extraction.{k,half}. Finite stock + replenish ≪ draw + ε(s)→0 ⇒ overshoot → gradual drawdown → crash → (if replenish can refill while consumption is low) recovery → limit cycle. This is the Rosenzweig–MacArthur structure; "enrichment" (raise store/replenish/pool) is predicted to destabilize into larger oscillations (paradox of enrichment) — expected, not a bug. - Demand ceiling
demand.headroomthrottles how much ofpoolis actually drawn ⇒ couples back into the scarcity axis (low headroom ≈ effectively less competition for the pool, store depletes slower). - Wall height =
reconfiguration.factor×cost_scale×rate_weight. Above the agent's affordable energy ⇒ emergent never-cross (layering-trap). - Dilution/locality =
context_nodestopology ×context_resolution_depth× agents-per-node. More co-accessors ⇒ smalleraccess_i/Σaccess⇒ less capture (emergent Rg density-dependence). - Competitive equilibrium =
niche.capacity×R× press weights. Sets where survivors settle after the energy layer decides who lives. - Population gate (biology) =
pop_N×pop_p×pop_s⇒ fixation speed ⇒ effective climb rate ⇒ feeds the scarcity axis (slow-fixing lineage pays maintenance while not advancing → starves = drift loss).
4. Scenario plan & expected regimes
Method: vary one axis at a time off a common baseline, predict the regime from §3 + the §17.8 literature, run, check the result maps to the prediction. "Maps back to what we expect" = the qualitative regime + response direction match (NOT absolute numbers — cartography). A non-matching result is investigated as likely our error (scoring/encoding/config) before being treated as a finding.
Baseline: biology-store-extraction-test (biology, organism-architecture, store 5.0 / replenish 0.05, extraction saturating h=0.25, demand need-multiple H=2, P3 flat-per-level maint).
| # | Scenario | Knob change vs baseline | Expected regime | Literature anchor | Verifies |
|---|---|---|---|---|---|
| S1 | Parsimony-under-scarcity | maintenance.scale ↑ / pool ↓ | minimal/stationary lineage survives; climbers starve extinct | metabolic cost of complexity; r/K | P3 centerpiece |
| S2 | Abundance | pool_per_step ↑ (or replenish ↑) | all lineages sustain; weak competitive sort only | — | scarcity axis sign |
| S3 | Boom-bust / limit-cycle | replenish swept toward draw rate; extraction.half mid | overshoot → gradual drawdown → crash; cycle if replenish≈draw | Rosenzweig–MacArthur | §17 fix unlocks this |
| S4 | Paradox of enrichment | store ↑ and/or replenish ↑ progressively | larger-amplitude oscillation, more extinction (counter-intuitive) | Paradox of enrichment | model reproduces the named destabilization |
| S5 | Extraction-curvature sweep | extraction k = 0 → 1 → 3 (power) | k0 = old one-step collapse; k↑ = stronger asymptote, slower drawdown, store never empties | Hotelling economic-vs-physical exhaustion | B mechanism monotonic & correct |
| S6 | Demand-ceiling sweep | demand.headroom 1 → 2 → 8 | low H = knife-edge no-reserve; high H = ceiling rarely binds → ≈ uncapped | Holling Type II handling-time | A mechanism monotonic |
| S7 | Wall / layering-trap | reconfiguration rule on a key prim, factor ↑ | agent stalls at the attractor for all steps, never crosses | open-Q#10 / lock-in | Inc-3 emergent wall |
| S8 | Locality / dilution | context_nodes crowded vs alone; resolution_depth | crowded node < baseline < alone | density-dependent Rg | Inc-2 participant-relativity |
| S9 | Gated unlock | store.gate on a prim; agent climbs through the gate | no capture until pos≥gate, then access opens (radiation) | Pd1→Pd2 phase transition | Inc-5 gate (not yet exercised) |
| S10 | Cross-domain transfer | run S1–S5 on entity / cognition / abiogenesis, common regime | same qualitative regimes, domain-characteristic timing | methodology: each level has own Cx/Cm | not tech-overfit |
Order: S5/S6 first (single-mechanism monotonicity sanity — cheapest, confirms the §17 build behaves), then S1/S2 (scarcity axis sign), then S3/S4 (the boom-bust/oscillation search — the headline open question), then S7/S8/S9 (walls/locality/gate), then S10 (cross-domain). Each run: confirm I1/I2 untouched (config-only changes), record regime vs prediction, honest-negative if a regime doesn't appear at the tried point (it's a parameter search, not a failure).
What "good" looks like: S5/S6 monotonic in the predicted direction; S1↔S2 flip across the scarcity boundary; S3/S4 produce the Rosenzweig–MacArthur stable→cycle→crash structure with enrichment destabilizing; S7 a clean never-cross; S10 same regimes across domains. That is the "maps back to what we expect" gate before any paper-harvest.
5. Scenario run log
S5/S6 — monotonicity sanity — PASS, both mechanisms correct in direction
Config-only contexts off the biology-store-test regime (I1/I2 untouched by construction). Sanity anchor biology-s5-extraction-k0 confirmed dynamics-identical to biology-store-test (whole-file diff differs only in the context/name metadata — not a model bug; my first sanity check was mis-specified, corrected). ε=s⁰≡1 reproduces the no-extraction path exactly ⇒ §17 byte-identical default holds at trace level.
- S6 (pure A, demand
need-multiple): clean full-range monotone confirmation. Climber energy/step:H=1holds dead-flat at 1.0 for 5 steps then declines, death@8 (vs @7) — the exact predicted signature (Δenergy=(H−1)·(last_cost+maint)=0while the ceiling binds ⇒ zero net flux ⇒ delayed starvation);H=2mild growth (1.0→1.87→…);H=8≡ baseline byte-for-byte (D_i>slice every step ⇒min()always uncapped ⇒ high-H limit). Mechanism A behaves exactly as the math says across the whole range. - S5 (pure B, extraction
power-k): monotone in the predicted direction, magnitude regime-gated. Total live-energy/step strictly ordersk0 > k1 > k3(higher k ⇒ ε smaller for s<1 ⇒ less extracted ⇒ more store residual = the asymptote, predicted). Key structural finding: the effect is small here because the dominant capture is the step-1 full-store windfall wheres=1and thepowerform hasε(1)=1^k=1∀k — sopowerdoes not throttle the windfall, it only shapes the depletion tail / asymptotic non-exhaustion. Thesaturatingform hasε(1)=1/(1+h)<1and does cap the windfall (cf.biology-store-extraction-test: 2.49→1.50 at step 1 under saturating h=0.25). ⇒ role split, both monotone:saturating= windfall cap + tail;power= tail/asymptote only. Implication for S3/S4: usesaturatingextraction for the boom-bust search (the one-step windfall must be throttled for a gradual cycle). - Outcome invariance (honest, not chased): death@7 + identical final distribution across all S5 and S6 (H≥2) — the climber's lethal factor in this regime is its off-manifold directed-climb cost, not the capture mechanism (regime-dependent; H=1 is the lone outcome shift and it occurs via the exact predicted zero-flux mechanism). Licensed claim = mechanisms monotone & correct in direction + the windfall/tail role split; not a fixed outcome. New contexts:
biology-s5-extraction-k{0,1,3},biology-s6-demand-h{1,2,8}.
S1/S2 — scarcity axis — FLIP confirmed, correct sign
Survivor count is monotone in available energy ⇒ the scarcity axis has the predicted sign and the survive/starve flip is present:
| Point | store / replenish / maint.scale | survivors | reading |
|---|---|---|---|
| S2 abundant | 30 / 2.0 / 0.015 | all 3 (climber holds 0.177) | abundance ⇒ even the complexity-climber sustains (the flip) |
| baseline | 5 / 0.05 / 0.015 | prok + vascular (climber extinct@7) | the parsimony-wins regime — minimal + incumbent persist, climber starves |
| S1 scarce | 1 / 0.02 / 0.05 | none (universal extinction@2) | OVERSHOT past the parsimony band into the known §6d universal-extinction corner |
Honest note: S1 was set too harsh and landed in universal-extinction (a documented degenerate corner), so the clean "minimal-wins-while-others-die" picture is the baseline, not S1; the parsimony band lies between baseline and S1. Not tuned to force a cleaner S1 (regime-not-magnitude / anti-p-hack) — precise band location is regime-map work (a finer scarcity sweep). New contexts: biology-s1-parsimony-scarce, biology-s2-abundance.
S3 — boom-bust search — HONEST NEGATIVE; two structural blockers localized
Replenish sweep {0.5, 1.5, 3.0}, saturating extraction h=0.25 (per the S5 windfall/tail finding), store 5, max_steps 120. No oscillation at any point (no overshoot→recovery; final distribution identical to S2-abundant). The non-result is structural, not a failure, and it precisely localizes what boom-bust requires:
- Run terminates at the "all done" stop (step 9). Directed agents reach their targets fast, so the simulation ends long before slow store-depletion dynamics can develop — there is no sustained consumption pressure to drive a cycle.
- Irreversible death. Dead agents are permanently removed (no recolonization/rebirth), so a sustained predator-prey limit cycle is structurally precluded by the current engine. The engine can produce a single overshoot→crash (the original
biology-store-testclimber@7) but not a repeating cycle.
⇒ Observing boom-bust needs (a) non-finishing consumption pressure — persist/target-less agents so the run doesn't end at "all done" (config-only, tryable), and/or (b) for a sustained cycle, a recolonization/rebirth mechanism (a real engine change, design-review-first, NOT to be added reactively). S4 (paradox-of-enrichment) is moot until S3 can produce a cycle and is deferred behind this decision. New contexts: biology-s3-replenish-{0p5,1p5,3p0}. Not p-hacked (no tuning to manufacture a cycle); the §14 lesson applies — a structure-dependent non-result is not a falsification, it is a localized design question.
(d-explore) — ls-population sustained-pressure phase map — BOOM-BUST+RECOVERY CONFIRMED + honest RM divergence
Config-only on the §6.7 plumbing (zero-reg by construction). Store 5.0, sat-ext h0.25, demand H2, scope.mode=ls-population, max_steps 60. Replenish swept:
| replenish | regime | detail |
|---|---|---|
| ≲ 0.15 | universal-extinction crash | sustained draw collapses the store; all extinct (.05@13, .15@24) |
| 0.3 – 0.6 | BOOM-BUST + RECOVERY (robust band) | overshoot → costly lineages extinct (colonial always first; vascular too at ≤.45) → survivor(s)+store crash to a trough then recover (rep .3 peak4.96→trough0.44@13→end6.08; .35/.45/.6 same signature; 1 survivor at .3–.45, 2 at .6) |
| ≳ 1.0 | all-sustain | minor transient then monotone growth |
Headline: the boom-bust the whole §17/§18 arc targeted is now demonstrated and robust across a band (not a knife-edge). The recovery arm — structurally blocked before §18 — is present without any rebirth (survivor + no-longer-over-drawn store rebound), exactly validating the §18.1 corrected analysis (store/reserve oscillation needs no population recovery; only a sustained cycle does). Emergent, not coded. Face validity: the costly off-manifold complexity-climber dies first under sustained pressure; the low-cost persister survives the bottleneck and recovers — parsimony-under-sustained-pressure, faithful.
Honest RM divergence (paradox-of-enrichment cross-check, rep 0.4, store 5→15→40): enrichment → fewer deaths, not more (store5: 2 deaths; store15: 2 but delayed; store40: 0, all sustain). This is the opposite of classical Rosenzweig–MacArthur — and it is correct: the current model is resource-depletion (consumer + finite store), not predator-prey — irreversible death, no predator-feedback oscillator (that is the deferred branch/population policy). Enrichment buffers the crash rather than destabilizing it. This quantitatively localizes what (b-policy) is for: sustained limit cycles AND the RM paradox genuinely require population-recovery/predator-feedback — confirming the contract's "policy-gated, not plumbing-gated" claim with evidence. The literature anchor is correctly not reproduced because its structural prerequisite isn't built yet (honest, expected — not a defect). New contexts: biology-d-lspop-rep{0p05,0p15,0p3,0p35,0p45,0p6,1p0,2p0}, biology-d-enrich-st{5,15,40}.
§7 split policy BUILT — engine OK; "RM VALIDATION" RETRACTED as an ARTIFACT (corrected on first visualization)
§7 implemented (5 additive edits): split config block + _split_fires trigger predicate (none default / off-maintenance-set / pressure-gated / stochastic, bounded by max_branches_per_lineage + min_steps_between); move-loop converts a normal move → §6.5 branch directive on fire, parent→persist (maintenance), child→directed (§7.2 asymmetry); _spawn_child honors child_strategy; conditional split output field. Zero-regression 13/13 byte-identical (split path dormant when no block), gates 331/333 + 202/0/25. The engine mechanism and zero-regression still stand. The validation claim below does not.
RETRACTION — the "RM paradox-of-enrichment CONFIRMED / discriminating cross-validation" claim was an artifact, found the moment the runs were first visualized (the original claim was inferred from the single turnover integer without looking at the dynamics).
What the figures (output/figures/evolve-biology-d-enrich-st{5,15,40}-split.png) actually show, corroborated by the engine code (evolve.py:399-424):
| store | lineages | deaths | dynamics (observed in the figure) |
|---|---|---|---|
| 5 | 10 | 9 | single spike (steps 1–4) → synchronized mass death step ~5 → 1 survivor flat |
| 15 | 33 | 32 | single spike (steps 1–6) → synchronized mass death step ~7 → 1 survivor flat |
| 40 | 62 | 61 | single spike (steps 1–7) → synchronized mass death step ~7–8 → 1 survivor flat |
- No oscillation, no recovery, no predator–prey feedback. Every run is one boom → one synchronized crash → a single survivor flat for 50+ steps. In all three,
deaths = lineages − 1(everything born dies except one founder). The lineage-tree panel is a dense uniform triangular stack — the textbook combinatorial-branch-artifact signature, not an ecological limit cycle. - Verified mechanism (code, not asserted):
off-maintenance-setfires whenever the divergence move leaves the coherent set; the colonial→vascular climber is permanently off-manifold, so the trigger fires nearly every eligible step.max_branches_per_lineage=4bounds one lineage, but every child is a fresh lineage with its own counter andmin_steps_between=1⇒ a geometric branch tree (1→4→16→…), all clones sharing the climber's doomed energy trajectory ⇒ they die together. "Enrichment scales turnover (10→33→62)" only because more store delays the shared death 1–2 steps, buying 1–2 more geometric generations. This is the trigger fighting an unreachable target — not Rosenzweig–MacArthur. - Discipline: reported as an honest-negative, not tuned away (observe-not-force / anti-p-hack). A genuine RM test would require population recovery via new viable lineages (not doom-inheriting clones), a trigger that does not fire every step on an off-manifold climber, and ideally a real consumer–resource/predator feedback rather than resource-depletion-only (the d-explore analysis already half-identified this). NOT to be retrofitted reactively — design-review-first if pursued.
- What still holds: the engine mechanism + zero-regression (above), and the separate no-split (d-explore) boom-bust band (rep 0.3–0.6): a single overshoot → trough → monotone survivor recovery, which the session-close honestly did not claim as a limit cycle. That result is unaffected by this retraction.
Contexts retained as legitimate artifacts: biology-d-enrich-st{5,15,40}-split (now correctly understood as the artifact demonstrator). Instrument built this correction: plot_evolve.py rewritten dynamic-aware (union agent set, measures-optional, population/energy/lineage-tree/share panels).
Cross-domain drive — §3 stress-test made executable — consistent, honest, NO oscillation anywhere
The §3 conceptual stress-test was never run; now it is. Faithful biology-d-enrich-st15-split mirror authored onto each domain's own niche/agents/calibrated-rate: a no-split ls-population twin + a split run for abiogenesis / techno / cognition (config-only, additive; engine unchanged; figures output/figures/evolve-{abiogenesis,techno,cognition}-d-{lspop,split}.png).
| Domain (arrangement) | no-split ls-population | split (off-maintenance-set) |
|---|---|---|
| abiogenesis (biology) | sustained 60-step run; single overshoot → drawdown → staggered deaths (prok@22, vascular@24) → colonial survives | same combinatorial artifact — 32 lineages #b1..#b5, synchronized death @5–6, 1 survivor (vascular). Artifact generalizes wherever target is off-manifold |
| techno (entity) | sustained; git climbs to its 17-move target @17 then dies @26, at-protocol @59, incumbent postgres wins | byte-identical to no-split — the trigger NEVER fired (3 agents, 0 branches): git's climb to entity-system is coherent/on-manifold, so off-maintenance-set never triggers |
| cognition (cognition) | universal extinction @ step 7 (both) | universal extinction @ step 7 (both); split dormant |
Three findings, all honest:
- The engine's genuine (non-artifact) behavior is robust and consistent across 3 domains/2 arrangements: a single overshoot → drawdown → one survivor (competitive exclusion, staggered deaths). There is NO sustained oscillation / limit cycle anywhere. The no-split scope contract works (60-step sustained runs, correctly does not stop at all-done). This strongly suggests the entire RM/limit-cycle premise was structurally unreachable with the current mechanisms — not a tuning miss.
- The
off-maintenance-setsplit trigger has no useful regime. Off-manifold target ⇒ combinatorial artifact (biology, abiogenesis); coherent/on-manifold target ⇒ trigger never fires, split byte-identical to no-split (techno). It never produces useful cladogenesis — it is a miscalibrated cladogenesis model, confirmed across domains. (The techno split≡no-split byte-identity is itself a clean confirmation of the diagnosed root cause.) - The biology-calibrated energy regime does NOT transfer to cognition (universal extinction @7 — the transplanted pool/cost/maintenance/store scale mismatches
civilizational-cognitive-calibrated). Reported as an honest parameter-transfer negative; not tuned to fix reactively (observe-not-force). A faithful cognition run would need its own energy calibration — design-review-first if pursued.
Net (observation, not a verdict): driving all domains shows consistent no-split competitive dynamics; the off-maintenance-set trigger combinatorially explodes on off-manifold targets. This is what the system does under those settings — not the system's ceiling (only one trigger, population dropped, a slice of the space). Continued exploration below changes the picture. New contexts: {abiogenesis,techno,cognition}-d-{lspop,split}.
Population genuinely engaged + a new on-fixation trigger — paced cladogenesis WORKS
Exploration continued (per "stop deferring population; sweep the space; be proactive"). Two things put in:
Verified-in-code finding — the population fixation gate was inert as previously wired. realized_probability(p,N)=1−(1−p)^N saturates to exactly 1.0 whenever N·p≫1 (every cumulative-cell-year context: prok→euk N=1e30·p=1e-22; euk→bilat N=1e31·p=3e-11 → both 1.0). kimura_pfix returns exactly 1.0 when selection s is unset (the neutral zero-regression default). Contexts supply no s; the loader does not apply their subpopulation_fraction (1e-6). ⇒ eff = 1·1 = 1 ⇒ every move fixes instantly ⇒ population does not gate anything. This verifies the user's standing point that population was effectively deferred/absent — it is wired but a no-op without a real selection coefficient (or sub-population-filtered effective N).
Engine addition — split.trigger: "on-fixation" (additive, opt-in, zero-regression PROVEN). Cladogenesis coupled to an actual pop-gen fixation event (a divergent variant that has fixed founds a child; parent persists), instead of to the candidate move. Two guarded edits + _onfix_branch helper; only reachable when trigger=='on-fixation' AND a move fixes (inside the pop_on branch). Re-running representative existing contexts (legacy tj-directed, off-maint split, stochastic split, pop-lspop) ⇒ byte-identical; gates 331/333+202/0/25 held.
Result — with population genuinely engaged (real per-agent selection coefficient s, activating Kimura Pfix≈2s≪1), cladogenesis becomes population-rate-limited, NOT combinatorial:
| context | s | "fixing" delay events | branch events | lineages | reading |
|---|---|---|---|---|---|
biology-d-pop-split-onfix | unset | 0 (instant fix) | 30 | 33 | gate inert ⇒ every-step (= the artifact) |
biology-d-pop-onfix-s02 | 0.02 | 33 | 1 | 4 | fixation paced ⇒ one clean cladogenesis |
biology-d-pop-onfix-s05 | 0.05 | 30 | 1 | 4 | one branch |
biology-d-pop-onfix-s15 | 0.15 | 24 | 7 | 10 | paced radiation: branch count scales with s |
The lineage tree at s=0.15 is a sane radiation-then-pruning: ~10 lineages born spread over steps 5–13 (paced by the fixation clock), founders persisting as long bars — not the dense combinatorial stack. Branch count is monotone in the selection coefficient (1→1→7 as s 0.02→0.05→0.15): cladogenesis-rate is governed by the pop-gen fixation rate, exactly as a principled model should behave. This is what the system does when population is genuinely engaged — the combinatorial behaviour was a consequence of the inert gate, not an intrinsic limit. (Scope note: this is paced-cladogenesis working; it is NOT a re-validation of the retracted RM claim — that stays retracted. Separate, sound mechanism. Observation, open to challenge.) New: on-fixation engine trigger; contexts biology-d-pop-{lspop,split-offmaint,split-stoch,split-pressure,split-onfix,split-onfix-slowclimb}, biology-d-pop-onfix-s{02,05,15}.
Filled biology curve + cross-domain transfer — sweep-s-curve-cross-domain.png. Extended the biology curve to 8 points: branches 1,1,1,3,3,7,7,8 at s = 0.02, 0.04, 0.05, 0.08, 0.10, 0.15, 0.20, 0.30 (clean sigmoid; transition s≈0.05→0.08; plateau s≳0.15). Cap variants at s=0.15: cap=4 ≡ cap=8 (7 branches; cap not binding), cap=2 ⇒ 6 (only barely binding) — cap is not the dominant lever at these s values, the fixation/time budget is. No-split control with real s (biology-d-pop-lspop-s05): population gating reshapes the competitive dynamics too (staggered deaths colonial@34/vascular@37 vs. ungated 41/31 vs. no-population synchronized @7-8) — slower, more drawn-out exclusion. Cross-domain transfer at s ∈ {0.05, 0.15, 0.30}:
| domain (arrangement) | branches @ s=0.05 | @ s=0.15 | @ s=0.30 | reading |
|---|---|---|---|---|
| biology (biology) | 1 | 7 | 8 | paced radiation + pruning |
| abiogenesis (biology) | 1 | 7 | 8 | superimposes biology — same arrangement ⇒ same curve |
| techno (entity) | 0 (coexist, 0 deaths) | 0 (2 deaths) | 0 (1 death) | coherent climb ⇒ no divergent fixations ⇒ no cladogenesis; deaths vary non-monotone in s (regime substructure) |
Reading: arrangement determines whether on-fixation can fire at all (off-manifold-target arrangements ⇒ yes, paced cladogenesis; coherent-target arrangements ⇒ no, just slower competition under pop gating); selection coefficient sets the rate where firing is possible. New scripts: compute/scripts/plot_sweep_summary.py (domain-general, multi-series overlay). New contexts: biology-d-pop-lspop-s05, biology-d-pop-onfix-s{04,10,20}, biology-d-pop-onfix-s15-{cap2,cap8}, {abiogenesis,techno}-d-pop-onfix-s{15,30}. Figure: output/figures/sweep-s-curve-cross-domain.png. Observation, open to challenge.
Techno fine-grain + energy_frac + replenish + no-split controls.
- Techno death-count peak. Filled techno at s=0.08/0.10/0.20: deaths sequence
0,1,1,2,1,1across s=0.05/0.08/0.10/0.15/0.20/0.30 — a real non-monotone bump at intermediate s under the constant "no-speciation" envelope.sweep-s-curve-cross-domain-v2.png. - Energy_frac sweep at biology s=0.15. Branches
6,5,7,6,6at ef=0.20/0.35/0.50/0.65/0.80; symmetric split (ef=0.5) is the local peak (~15% effect; secondary lever to s).sweep-ef-curve-biology-s15.png. - Replenish sweep at biology s=0.15. Branches
3,7,7,7,15at replenish 0.20/0.40/0.60/1.00/2.00. Three regimes: starved (rep≤0.2 ⇒ energy bottleneck caps radiation), plateau (0.4–1.0 ⇒ s-budget caps radiation, more energy doesn't help), break-through (rep≥2.0 ⇒ enough energy unlocks fixations previously starved out). Enrichment monotonically increases turnover under the working mechanism — same qualitative direction as RM territory but arising from principled paced cladogenesis, not the retracted combinatorial artifact. Not claimed as RM validation; observation.sweep-rep-curve-biology-s15.png. - No-split-with-s controls (
{abiogenesis,techno}-d-pop-lspop-s05): abiogenesis no-split == biology no-split numerically (3/2/30, same arrangement); techno no-split ≡ techno on-fixation at s=0.05 (3/0/103) — on-fixation dormant in techno by design (coherent climb), confirmed.
Net: the engine + population-gated on-fixation mechanism is characterized along three independent dials (s, energy_frac, replenish) with reproducible, monotone-or-peaked, principled dose-response — domain-aware (arrangement gates whether cladogenesis fires at all). Real, presentable system structure. Gates green throughout (331/333+202/0/25); no engine changes since on-fixation (zero-reg proven byte-identical).
Continued probe: s × rep heatmap, reproducibility, binding-knob map.
-
s × rep 4×4 heatmap (
heatmap-s-x-rep-biology.png). s ∈ {0.05, 0.10, 0.15, 0.30} × rep ∈ {0.40, 1.00, 2.00, 3.00}, branches: bottom-left cool (1) → top-right hot (~30). Two notable features: (a) a recurring "15-branch ceiling" appears in multiple non-adjacent cells (s=0.05/rep=2.00, s=0.05/rep=3.00, s=0.15/rep=2.00) — a tier; (b) the s=0.15 column dips at rep=2.00 (15 branches) below its neighbors (s=0.10 → 19; s=0.30 → 22) — non-monotone-in-s pocket. Mechanism (observation): at higher s, faster fixation compresses the radiation window (births steps 5–13) and pruning closes it before more branches accumulate; at lower s the radiation spreads wider (births steps 5–22) → more branches. Counterintuitive but visible by direct comparison ofevolve-biology-d-pop-onfix-s{10,15}-rep200.png. -
Reproducibility — byte-identical under seed flip.
biology-d-pop-onfix-s15re-run withbehavior.seed=42is dynamics-identical to seed=0 (modulo context name). The on-fixation + directed + persist code path is deterministic at this configuration; results are structural, not noise. -
Steady-state cap, not time-budget cap. At the (s=0.15, rep=2.0) cell,
max_steps∈ {60, 120, 240, 480} all yield byte-identical 15 branches / 81 fixing-events. Same at the rep=3.0 cell (30 branches) for max_steps {60, 120, 240}. The heatmap is a true equilibrium map — each cell is the radiation-then-pruning fixed point. -
Binding-knob map at the (s=0.15, rep=2.0) cell (observation across 14 knobs tested; not a conclusion):
knob finding at this cell maintenance.scale DOMINANT lever — branches 59,30,15,7,1at mn=0.005/0.010/0.015(default)/0.025/0.050 (4× radiation when halved; near-extinction when tripled). The per-step structural-holding cost is the binding term.selection coefficient sbinds: 8-point sigmoid 1→8 across s=0.02→0.30 total energy budget (store, replenish) binds: same staircase 15→30 at thresholds (~rep 1.1, ~store 20); ceiling is energy-budget-driven, not per-knob demand headroom binds, NON-MONOTONE: branches 10,15,15,19,15at hd=1.0/1.5/2.0/3.0/5.0 — sweet spot at hd≈3.0energy_frac secondary (~15%); peak at ef=0.5 cost_scale essentially inert (branches all 15 across 0.05→0.40) capture.scale byte-identical 15 across 0.01/0.04/0.06 extraction.half byte-identical 15 across 0.10/0.50/1.00 max_branches_per_lineage not binding (cap 4→12 same; cap=2 ⇒ 11) max_steps not binding (60→480 byte-identical; STEADY-STATE) niche capacity not binding (1.0→5.0 same at this cell AND at the 30-branch rep=3.0 cell with 33 lineages) behavior.seed not binding (0→42 byte-identical: on-fixation+directed+persist is deterministic at this configuration) Reading (observation): the engine's bottleneck in this regime is the per-step structural-maintenance cost. Most fine-grained energy-shape knobs (capture form, extraction shape) and structural caps (cap, niche capacity, max_steps) are inert; the budget knobs (s, energy budget, headroom, maintenance) carry the dynamics.
-
Steady-state robustness: confirmed at three independent cells across radiation tiers in the extinction-heavy regime — 15-branch cell (max_steps {60,120,240,480} all 15); 30-branch cell (max_steps {60,120,240} all 30); 59-branch low-maintenance cell (max_steps {60,240} all 59). Each reaches a radiation-then-pruning equilibrium fixed point by step ~30.
-
Low-mn long-transient regime (mn ≤ 0.0015) — NOT in the short-horizon equilibrium class. Pushing mn lower at (s=0.15, rep=2.0) reveals a qualitatively distinct regime: branch count
15 → 30 → 59 → 115/115/119 → 153/194 → 290across mn 0.015 → 0.010 → 0.005 → 0.003/0.0025/0.002 → 0.001/0.0015 → 0.0005 (NON-MONOTONE in the very-low region; interior wobble 153/194/119 across 0.001/0.0015/0.002). Below mn≈0.0015 the system enters a sustained-population regime with rich oscillatory transient dynamics (alive dips to 3, recovers to 148–277; energy peaks-trough-peaks). LONG-HORIZON SETTLE TEST at mn=0.001, max_steps=1000: dynamics do equilibrate, just much later — last 200 steps have alive=85–93 (flat), 0 births, 8 slow-attrition deaths. So the regime is a long transient with oscillation, not a sustained limit cycle. Honest scope: low-mn extends the transient by ~order of magnitude and gives interesting cyclical phenomenology for hundreds of steps, but the eventual fixed point is still a fixed point. Figure:evolve-biology-d-pop-onfix-s15-rep200-mn0p001-ms400.png,sweep-mn-curve-fullspan-s15-rep200.png. -
mn dominance verified across 4 biology cells and 2 domains. Strong monotone dose-response at (s=0.05, rep=0.40), (s=0.05, rep=2.0), (s=0.30, rep=2.0), (s=0.30, rep=3.0); ratios consistent. Abiogenesis tracks biology proportionally (e.g. mn=0.005 → 30 branches vs biology 59 at the same s=0.15). Techno stays at 0 branches across all mn (arrangement gate dominates: coherent climb ⇒ on-fixation never fires regardless of mn), though mn still affects death timing in techno (0→3 deaths across mn 0.005→0.050). The
mn × sheatmap at rep=2.0 (heatmap-mn-x-s-biology-rep200.png) shows the interaction: mn drives variation vertically (1 → 89); s amplifies at low mn (30 → 89 across bottom row) but barely matters at high mn (1 → 1 → 3 across top row). -
Phase map closed out (5 slices) spanning the on-fixation parameter space:
mn × sat rep=2.0 (heatmap-mn-x-s-biology-rep200.png)mn × repat s=0.15 (heatmap-mn-x-rep-biology-s15.png) — crisp tier-quantizationmn × repat s=0.30 (heatmap-mn-x-rep-biology-s30.png) — smoother gradient (tiers weaken at higher s)rep × sat mn=0.005 (heatmap-s-x-rep-biology-mn0p005.png)store × repat s=0.15, mn=0.015 (heatmap-store-x-rep-biology-s15.png) — the energy-axis pair
The
store × repslice shows clean substitutability between the two energy reservoirs: at low replenish (≤1.0) the store dominates (rep value barely matters; branches go 3/7/15/30 across stores 5/15/30/60); at higher replenish both axes contribute; diagonal iso-bands persist; 59 at the (store=60, rep=3.0) corner. Confirms the "total energy budget" reading —store + replenish · stepsare interchangeable up to a shape factor.Branch counts cluster on iso-tier values (1, 3, 7, 15, 30, 60-ish, 126) with diagonal iso-bands in the (mn, rep) plane — not a simple closed-form product (rep/mn ranges 80–300 within the "30" tier alone). Tiers geometrically double, consistent with a "lineage-generation count under energy budget" interpretation (hypothesis, not conclusion).
-
Cross-domain mn × rep grid: biology vs abiogenesis cell-by-cell IDENTICAL across all 20 cells (s=0.15, rep ∈ {0.40, 1.00, 2.00, 3.00} × mn ∈ {0.005, 0.010, 0.015, 0.025, 0.050}). Same arrangement ⇒ same dynamics, confirmed comprehensively not just spot-check.
-
Two qualitatively distinct sustained-population regimes (deaths ≪ lineages):
- Very-low-mn regime (≤0.0015): long oscillatory transient (alive dips deep, recovers, dips again across ~300 steps); eventually settles by step ~800. mn=0.0005 ms=200 ⇒ alive_max=277, alive_min=3.
- Paced-accumulation regime (low-s + high-rep + low-mn, e.g. s=0.05, rep=3.0, mn=0.005): population monotonically climbs 3 → 33 with 0 deaths and accumulating energy. No extinction pressure because slow fixation plus abundant energy keeps the energy budget always ahead of demand. Different mechanisms, same outcome class. The sustained-population attractor is multiply-accessible through the parameter space.
-
Cells already known steady-state (60→480 byte-identical): the extinction-equilibrium regime (mn ≥ 0.005 at moderate rep). Long-transient and paced-accumulation regimes need longer max_steps; settled by ms=800 in the ms=1000 test.
New contexts authored this batch: ~50 across the mn × s, mn × rep, rep × s grids + steady-state probes + cross-domain transfer. Scripts: plot_sweep_heatmap.py (multi-series 2D); plot_sweep_summary.py (multi-series 1D overlay).
Manifestation-space coverage — the radiation explores LOCALLY
User-raised coverage concern: do the branched lineages actually recover known manifestations, or just wander the lattice abstractly? Built compute/scripts/analyze_branch_mn_recovery.py — for each lineage's final position, matches against all biology Mns at the chain level (exact for point Mns, range-bracketed for bracketed Mns).
Result (observation, not conclusion): every lineage in every run lands at a position matching SOME known Mn (100% match rate, 0 novel positions), BUT this is partly an artifact of 3 wide-range "ecological role" Mns (habitat-engineer, primary-producer, decomposer-recycler) whose position ranges match nearly anything. The structurally specific Mns recovered are ~7–11 out of 69 available, regardless of how rich the radiation is.
| Setup | Lineages | Unique Mns recovered |
|---|---|---|
| 3-founder default (phylogenesis-stem prok/colonial/vascular) | 18 | 10–11 |
| 3-founder + low mn (richer radiation) | 62 | 10 (no gain) |
| 3-founder + very-low mn (long transient) | 235 | 10 (no gain) |
| 4-founder diverse (amphi / arabid / c-elegans / castor) | 12 | 14 |
| 4-founder spread (chlamy / acropora / drosophila / callorhinchus) | 11 | 13 |
| 4-founder spread + low mn (63 lineages) | 63 | 14 (no gain over the 11-lineage 4-founder run) |
Reading: the cladogenesis mechanism is fundamentally a local-diversification tool (branches diverge by single-primitive moves from parents, stay in parents' manifestation neighborhood), NOT an exhaustive Mn-discovery tool. Each founder seeds a small local Mn cloud (~3 specific Mns); total coverage is bounded by founder-region diversity, not by lineage count. Adding 200 more branches at the same founder positions yields ZERO new Mn coverage. To cover the full Mn library would need either (a) many more diverse founders, (b) multi-primitive divergence moves, or (c) a long-distance migration/jump mechanism — none currently implemented. New contexts: biology-d-pop-onfix-s15-rep200-{diverse-founders,spread-founders,spread-mn0p005}. New script: analyze_branch_mn_recovery.py.
This is a real mechanism characterization finding — it matches how biological speciation actually works (gradual divergence from parents, not global jumps), but it means the engine in current form does not serve as an exhaustive manifestation-space mapper. Open question for any future design: should it?
New scripts: compute/scripts/plot_sweep_heatmap.py (2D-grid heatmap, domain-general). Figures: heatmap-s-x-rep-biology.png, sweep-{cap,ms,nc,st,hd}-curve-at-s15-rep200.png. Many new probe contexts under biology-d-pop-onfix-* (cap/ms/nc/st/hd/cs/mn/cp/eh variants + s×rep grid cells + seed42 control).