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>
This commit is contained in:
2026-04-08 16:20:29 +02:00
co-authored by Claude Sonnet 4.6
parent 385f07b11e
commit 9d9ea96be1
6 changed files with 494 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
# 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
```