Files
settled-reach/docs/sprints/sprint-34/server.md
T
jpmschweitzerandClaude Sonnet 4.6 9d9ea96be1 chore(meta): plan Sprint 34: Pulse
Close Phase 2 — wire econ-sim into game server tick loop, expose price
history and trade flows via implant insert panel, add economics debug
console commands for runtime event injection and parameter mutation.

New tickets: #821 (server tick integration), #822 (IPC bridge v21),
#823 (debug command handler), #824 (economics insert panel),
#825 (debug console econ commands). Existing: #810, #785, #811, #748,
#814, #695. 11 tickets total across server, client, copy, planning.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:20:29 +02:00

5.5 KiB
Raw Blame History

Sprint 34: Pulse — Server Tasks

Goal: Close Phase 2 — wire the economics simulation into the live game, expose price history and trade flows in the implant, and make the economy observable and tweakable at runtime.

Branch: sprint-34/server Agents: Dudley (simulation), Tyre (architecture)

New Tickets

# Title Blocked by
#810 Event input port implementation #809 (done)
#821 Integrate econ-sim into game server tick loop #810
#822 Expose economy state over IPC bridge to client #821
#823 Economics debug command handler — event injection and parameter mutation #821

Key Decisions

  • decisions/economics.md — D-178 (model architecture — Leontief + tâtonnement + agents), D-179 (stability criteria), D-180 (event input port — EconEvent struct and visibility modes), D-181 (7-signal vocabulary per node), D-183 (iterative dev cycle)
  • decisions/architecture.md — D-020 (IPC architecture — ObserverSnapshot + PlayerAction), D-031 (tick-to-time mapping — 10 ticks = 1 game-minute)

Notes

#810 — Event input port implementation

The EconEvent struct (D-180) must be added to tooling/econ-sim/src/model.rs or a new events.rs module. The port is the typed interface through which all external disruptions enter the simulation. An event carries:

EconEvent {
  target:     Node | NodeSet | Corridor | TradeRoute | Currency | Commodity,
  effect:     ProductivityMultiplier | CapacityMultiplier | DemandShock | ExchangeShock,
  duration:   ticks,
  visibility: Global | Proximate(hops) | Disclosed(specific_nodes) | Hidden,
}

Visibility modes are defined in D-180. For this sprint, only Global and Proximate need to be exercised — Hidden is Phase 3 territory (requires the player inspect verb). The port must accept events from: (a) the server tick loop (#821), and (b) debug commands (#823). Test: inject a supply shock, verify cascade propagates and prices recover within 200 ticks per D-179 Test 3.

#821 — Integrate econ-sim into game server tick loop

The econ-sim is currently a standalone CLI binary at tooling/econ-sim/. This ticket makes it run inside the server process. Approach:

  1. Extract the simulation logic from tooling/econ-sim/src/main.rs into a reusable library crate (e.g. tooling/econ-sim/src/lib.rs or a new server/src/economy/ module — Tyre to decide the crate boundary).
  2. Add a bevy_ecs System that advances the economy N ticks per game tick (rate TBD — likely 1 economy tick per 10 game ticks given D-031 tick-to-time mapping).
  3. Store the current economy state as a Resource in bevy_ecs so downstream systems (#822, #823) can query it.
  4. Economy state must include all 7 D-181 signals per active node so the bridge can later serialize the relevant subset.

Key files: server/src/simulation/ticker.rs (where per-tick systems run), tooling/econ-sim/src/model.rs (simulation state), tooling/econ-sim/src/trade.rs (tâtonnement step). The DB at server/data/systems.db is already populated from Sprint 33.

Do NOT load the econ DB on every tick — load once at server startup into the bevy_ecs Resource.

#822 — Expose economy state over IPC bridge to client

Extend ObserverSnapshot to version 21 with an economy_snapshot field:

#[serde(default)]
pub economy_snapshot: Option<EconomySnapshot>,

EconomySnapshot carries per-system data for the client's economics panel (#824). Phase 2 deliverable is D-181 signals 12 only (price_current, price_trend). Struct sketch:

pub struct EconomySnapshot {
    pub tick: u64,
    pub nodes: Vec<EconNodeSnapshot>,
}

pub struct EconNodeSnapshot {
    pub system_id: u32,
    pub commodity_id: u32,
    pub price_current: f64,
    pub price_trend: f64,   // delta over last N ticks
}

Add EconStateQuery to the PlayerAction enum for on-demand pulls — the client does not need economy data every tick (that would balloon snapshot size). The server responds to EconStateQuery by populating economy_snapshot on the next snapshot. Without a query, economy_snapshot is None.

Update PROTOCOL_VERSION to 21 in server/src/bridge/types.rs.

#823 — Economics debug command handler

Extend DebugCommandKind in server/src/bridge/types.rs with three new variants:

/// Inject an economic event into the running simulation.
InjectEconEvent {
    system_id: u32,
    commodity_id: Option<u32>,  // None = system-wide
    effect: EconDebugEffect,
    magnitude: f64,
    duration_ticks: u32,
},
/// Mutate a tâtonnement parameter at runtime.
SetEconParam {
    param: EconParamKind,  // Alpha | Beta | CorridorFriction { system_a, system_b }
    value: f64,
},
/// Return all 7 D-181 signals for a named system.
GetEconState {
    system_id: u32,
},

Wire these into the existing debug command dispatch in server/src/simulation/ (wherever DebugCommandKind is matched). Return results via DebugResponsePayload.text as a human-readable multi-line string. Blocked by #821 (economy resource must exist to query or mutate).

Dependency Chain

#810 (event port) → #821 (server tick integration) → #822 (IPC exposure)
                                                    → #823 (debug command handler)

#822 and #823 are parallel after #821 completes.

PR Workflow

tea pr create --repo jpmschweitzer/settled-reach --login schweitz \
  --title "feat(simulation): economics in-game tick loop and IPC bridge" \
  --description "Sprint 34 server work" \
  --base main --head sprint-34/server