Skip to content

Option bus

OptionBus · IOptionPublisher

Kind Engine infrastructure (not toggleable); publishers are systems (toggleable)
Project NextIteration.Engine/OptionBus.cs; NextIteration.Systems/Agency/BaselineOptions.cs
Exposes Option, IOptionPublisher, ctx.Options, the action registry
Consumes the Agency-phase view
Consumed by DecisionSystem; the trace (decision records); gap detection (Phase 2)
Status designed · Phase 1 (#35)
PLAN §3.3, §7.4.1, §7.4.2, §7.5, §22.2
Player Needs

DecisionSystem does not know what douse_fire is. Whoever introduces an action publishes scored options for actors; DecisionSystem applies personality weights and arbitrates. This is the Sims' "objects advertise what needs they satisfy", applied to systems and rules — and it is what lets a later phase add an action without editing the core.

record Option(
    NodeId Actor, string Action, NodeId? Target,
    string Need,                                  // hunger · warmth · safety · rest · curiosity (Phase 1)
    float  Score,                                 // before personality weighting
    string Reason,                                // human text — the trace and Explain this show it
    IReadOnlyDictionary<string, float> Inputs,    // what the score was computed from
    string Publisher);

interface IOptionPublisher { IEnumerable<Option> Publish(ReadOnlyGraphView view, TickContext ctx); }

How it runs

At the start of the Agency phase the engine calls every active publisher in (priority, name) order against the phase view and accumulates ctx.Options. Publishers run between PerceptionSystem (10) and DecisionSystem (30). Options never touch the graph — they are the one sanctioned within-phase channel, rebuilt every tick, discarded at phase end — so they bypass the resolver and the one-tick lag.

BaselineOptions (Phase 1)

The engine ships one publisher with the §7.4.1 formulas for eat, move, rest, pick_up, drop, fetch_water, douse_fire, tend_fire, gather_wood. Two rules it follows that every publisher must:

  • Never read a target's live attributes for a score. Danger and warmth at a target come from perception or memory (view.Facts, view.Known); the remembered food_value drives the hunger draw, not the bush's real one. Reading the truth is god-view, and it is what the spike's whole-map gradient did.
  • A composite score publishes one option with the dominant need. move to a target sums hunger_draw + safety_draw + explore_draw + warmth_draw − danger_at_target; the publisher emits one option per target with the full score, Need = the largest draw, and the components in Inputs. "Kira fled" is a move whose need is safety.

The action registry

Every publisher declares its actions under writes.actions in its manifest, each with its need. The world schema lists every action in the world and who offers it; capability-gap detection (Phase 2) classifies an unmet need against this list.

Hot-toggle and determinism

Toggle a publisher off and its actions stop being offered next tick; on, and they return. Publisher order is fixed; option order within a publisher is deterministic (iterate the view's query results in order, never a HashSet); arbitration is argmax with a StableHash tiebreak.

History

Phase Change
1 Introduced: Option with Need and Inputs, IOptionPublisher, BaselineOptions, the action registry, the five Phase 1 needs.

See also

DecisionSystem · From perception to Explain this · PerceptionSystem