Skip to content

Tick pipeline and systems

TickPipeline · ISimulationSystem

Kind Engine core
Project NextIteration.Engine/TickPipeline.cs, SystemRegistry.cs; NextIteration.Sdk/ISimulationSystem.cs
Exposes ISimulationSystem, TickContext, SystemRegistry.Activate/Deactivate
Consumes the active systems, the graph
Produces one resolved batch per phase, three per tick
Status designed · Phase 1 (#29)
PLAN §3.1–§3.9, §5.1–§5.3, §18.2, §18.9
Player Tinkering (switching systems)

The system contract

interface ISimulationSystem
{
    string Name { get; }
    SystemPhase Phase { get; }      // Environment · Agency · Event
    int Priority { get; }           // order within the phase
    IEnumerable<Intent> Process(ReadOnlyGraphView view, TickContext ctx);
}

That is the entire contract. A system reads the frozen view and yields intents. It cannot mutate the graph, call another system, know which systems exist, or hold state between ticks. (ComponentQuery was dropped from the interface at the Phase 1 design session; a system finds its nodes with view.NodesWithComponent(...) and declares them in its manifest.)

Two sanctioned exceptions, both rebuildable from the graph: read-only caches (path tables, compiled rules), and the option bus.

State across ticks (PLAN §3.9)

Anything that spans ticks is an attribute on the graph: a since-timestamp (heat.hot_since = world_time, test elapsed time), an accumulator (counter, EMA with a per-hour constant), or — last resort — a bounded FloatList. Never process memory, never the trace. When the owning system is off its accumulators freeze; on return it decides what a stale timestamp means.

Hot-toggle (PLAN §18.9)

Every system can be deactivated and reactivated at any tick boundary without breaking anything. The contract that makes it true: stateless between ticks; initialise missing attributes on first encounter; read defensively (TryGet, fallbacks); write only what you own; degrade gracefully. Engine infrastructure is not toggleable: PlayerActionSystem, the option bus, the clock, the trace, RuleSystem's host are registered outside the toggle set. The universe's SystemPolicy names the default loadout; new systems are registered inactive until their increment's done-when passes.

TickContext

record TickContext(int Tick, int WorldTime, int TicksPerDay, IReadOnlyList<SimulationEvent> Events,
                   IReadOnlyList<Option> Options, WorldConstants World)
{
    float PerTick(float perDay); float Hours(float n); float Days(float n);
    Random DeterministicRng(string purpose, long salt);
}

WorldTime is sim-minutes, engine-owned. PerTick/Hours/Days are the only place a tick count appears in a system (see Clock).

Manifest

Each system ships a manifest declaring reads/writes for components, attributes, edges and events, the options it publishes under writes.actions with their needs, and its sim-time settings. The engine builds the live world schema from manifests and warns at load on reads nothing writes (PLAN §22.2).

History

Phase Change
1 Introduced: three phases, one batch per phase, ComponentQuery dropped, TickContext.WorldTime/PerTick, §3.9 state rule, engine infrastructure outside the toggle set.

See also

The tick · Systems overview · Clock and simulation time · SYSTEM_DEVELOPMENT.md