Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Organism model

What

Castellan treats a harness as a living organism, not a static config file: a genome expresses coordination parameters, circulation vitals track field health tick-by-tick, and an immune gate rejects harmful topology mutations before they reach production.

Why

This layer turns “evolve topology” from a black box into something you can inspect, quarantine, and trust. Prefer organism terms over animal-pack or feudal metaphors — lexicon.

Read this page if you’re trying to understand what castellan vitals is actually showing you, why a mutation got rejected instead of accepted, or how genome lineage relates to the topology archive.

Status: Phases 1–4 are complete — circulation, DNA lineage, immune gate, and per-zone expression are all live in castellan-evolve/castellan-runtime.

Anatomy: where organism state lives

LocationHolds
castellan-core/organism.rsDNA types, circulation vitals, per-zone expression
castellan-substrate/pheromonePer-zone decay (falls back to a global lambda if unset)
castellan-runtime/circulationVitals computation + immune_fever tracking
castellan-runtime/engine.rsWires vitals, genome_id, fever, and decay into the run loop
castellan-evolve/genome.rsLineage, crossover, archive reconstruction
castellan-evolve/immune.rsThreat detection (ThreatPattern), auto_reject, quarantine recommendation
castellan-evolve/mutator.rsCrossover + cold-zone decay adjustment
castellan-cli/organism_cmd.rscastellan vitals, castellan genome list|lineage|map

Bio-novelty extensions (H1–H9)

MechanismSeam
Quorum phase locksQuorumSensor + FalseQuorum immune
Response thresholdsAgentNode.response_threshold + surplus dispatch
Cement morphogenesiscement deposits → MorphogenesisEngine
Trail / Physarum corridorsCorridorField
MAP-Elites archiveMapElitesArchive + castellan genome map
GRN expressionRegulatoryNetwork::express(vitals)
Live quarantineZoneQuarantine mid-run
Clonal immune memory.castellan/immune_memory.json

Circulation vitals also expose role_entropy, role_stickiness, inflammation, and mean_corridor_length when those mechanisms fire.

Organism loop

flowchart LR
    RUN[castellan run] --> VITALS[circulation vitals]
    VITALS --> EP[episode JSON]
    EP --> EV[castellan evolve]
    EV --> IMM[immune_report]
    IMM -->|accept| ARCH[genome archive]
    IMM -->|reject| QUAR[quarantine]

    classDef runtime stroke:#0969da,stroke-width:2px
    classDef evolve stroke:#d97706,stroke-width:2px
    classDef gate stroke:#1a7f37,stroke-width:2px

    class RUN,VITALS,EP runtime
    class EV,ARCH evolve
    class IMM,QUAR gate
  1. Every run expresses a CastellanGenome — the coordination and decay parameters active for that episode.
  2. The PheromoneField’s circulation health lands in the episode as CirculationVitals.
  3. castellan evolve mutates or crosses over (requires a Pareto front with ≥ 2 non-quarantined entries) candidate genomes, then gates every candidate through immune_report().
  4. Quarantined genomes are excluded from archive.nearest() — they can never be selected as a seed for a future castellan run --seed-archive.
  5. Per-zone decay gets tuned from the proposer’s cold-zone heatmap, so zones that go quiet decay differently from zones under constant pressure.

The immune gate, concretely

ImmuneReport carries two independent signals per candidate:

FieldMeaningEffect
auto_rejectSet when threats include RunawayParallel or other severe patternsCandidate never enters the archive this generation
quarantine_recommendedSet whenever any threat pattern is detectedCandidate is marked quarantined: true; excluded from future nearest() seeding even if accepted

A genome can be accepted into the archive but still quarantined — quarantine is about seeding safety, not archive membership. Check castellan genome list output for the quarantined flag per entry.

How operators use it

1. Run a goal — a genome is expressed automatically, no flags needed:

castellan run --goal "reach target" --plugin gridworld

2. Inspect circulation health for the most recent (or a specific) episode:

castellan vitals
castellan vitals --episode .castellan/episodes/<goal-id>.json

3. Evolve genomes from the episode corpus — this is where the immune gate runs:

castellan evolve --episodes 10 --workspace .castellan/episodes

4. List genomes and trace lineage:

castellan genome list
castellan genome lineage <genome_id>

5. Seed a new run from a surviving (non-quarantined) genome:

castellan run --goal "reach target" --plugin gridworld --seed-archive --write-back

Phase completion

PhaseDeliverableStatus
1 Circulationcirculation_vitals, castellan vitals, fitness dimension
2 DNAgenome_id lineage, archive seed reconstruction, castellan genome
3 ImmuneDrift + fitness + immune gate, quarantine, fever deposit
4 ExpressionPer-zone decay, crossover, flux-grid test, fever unit test

flux-grid (optional, experimental)

  • Feature flag: castellan-substrate/flux-grid — a vendored 64×64 Stigmergy grid.
  • Not enabled in default builds. The zone-keyed PheromoneField remains the default substrate.
  • Enable for experiments:
cargo build -p castellan-substrate --features flux-grid

Recipes

When a run’s fitness looks fine but the field “feels” unhealthy, check castellan vitals before trusting the number — circulation vitals surface stalls and dead zones that a single scalar fitness score can hide.

When castellan evolve keeps rejecting your best-looking candidates, dump immune_report reasoning via --plan (read-only, zero writes) before assuming the mutator is broken — the drift or immune gate may be catching a real structural problem.

When you want to know if a genome is safe to seed from, always check quarantined on castellan genome list, not just whether it’s present in the archive — presence and safety are separate signals.

When investigating a lineage regression, castellan genome lineage <id> walks parent_genome_id; note that crossover sets a full parent_ids list internally, but the CLI currently surfaces only the primary parent (see Known deferred below).

Failure paths / troubleshooting

SymptomLikely causeFix
castellan vitals reports no dataNo episodes yet, or wrong --workspaceRun castellan run first; confirm .castellan/episodes/ has files
Genome accepted but castellan run --seed-archive never picks itGenome is quarantined: trueCheck castellan genome list; quarantined entries are excluded from nearest()
Crossover never happensPareto front has fewer than 2 non-quarantined entriesRun more episodes/generations to build a larger accepted pool
Lineage shows only one parent for a crossover genomeCLI limitation — parent_ids is tracked internally but only parent_genome_id is surfacedKnown deferred; inspect the archive JSON directly for full parent_ids if needed
flux-grid feature won’t buildNot enabled in default feature setBuild with cargo build -p castellan-substrate --features flux-grid explicitly

Known deferred

  • flux-grid is not wired into the swarm-demo default path.
  • Full parent_ids lineage is not yet exposed by the CLI (only primary parent_genome_id).
  • RAH_MAX_DEPTH cycle avoidance between castellan-evolve and castellan-rah lives in castellan-core but isn’t documented end-to-end yet.

See also