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>
124 lines
5.5 KiB
Markdown
124 lines
5.5 KiB
Markdown
# 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:
|
||
|
||
```rust
|
||
#[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 1–2 only (price_current, price_trend). Struct sketch:
|
||
|
||
```rust
|
||
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:
|
||
|
||
```rust
|
||
/// 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
|
||
|
||
```bash
|
||
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
|
||
```
|