feat(simulation): economics integration — D-180 event port, D-181 signals, IPC bridge, debug commands (#810 #821 #822 #823) #125

Closed
jpmschweitzer wants to merge 0 commits from sprint-34/server into main
Owner

Summary

Implements the full Sprint 34 economics pipeline across four tickets:

  • #810 (EventPort / D-180)EconEvent struct with Target/Effect/Duration/Visibility variants; EventPort typed input queue for external disruptions; D-179 Test 3 upgraded from placeholder to real CapacityMultiplier shock injection (max_dev 4.1%, within ±5% spec)
  • #821 (server tick integration) — econ-sim extracted as library crate (lib.rs + sim.rs); Simulation stateful runner; EconSimResource + EconStateResource (7 D-181 signals per active node); tick_economy_simulation Bevy system advances 1 economy tick per 10 game ticks (D-031); graceful no-op when systems.db absent
  • #822 (IPC bridge) — Protocol v20 → v21; EconStateQuery PlayerAction variant; EconomySnapshot/EconNodeSnapshot wire types; EconQueryBuffer + serve_econ_state_query system; economy_snapshot field on ObserverSnapshot
  • #823 (debug commands)InjectEconEvent (fires D-180 events from console), SetEconParam (runtime α/β tuning — ALPHA/BETA promoted to pub const + Simulation fields), GetEconState (7-signal human-readable dump); EconDebugEffect and EconParamKind enums

Test plan

  • cargo check — zero errors, zero warnings
  • cargo clippy — clean
  • cargo fmt — applied
  • 1147 unit tests pass (cargo test --lib)
  • Integration tests pass (cargo test --test integration_layer3)
  • Pre-push hook: fmt OK, clippy OK, ruff OK
  • D-179 stability: cold-start ±3.8%, long-run ±1.2%, shock recovery 4.1%, cross-zone ±0.9%
  • Live Gauntlet test with systems.db present (validates try_load_economy hot path)
  • Client-side: send EconStateQuery{system_id: "sol"} and verify economy_snapshot appears

🤖 Generated with Claude Code

## Summary Implements the full Sprint 34 economics pipeline across four tickets: - **#810 (EventPort / D-180)** — `EconEvent` struct with Target/Effect/Duration/Visibility variants; `EventPort` typed input queue for external disruptions; D-179 Test 3 upgraded from placeholder to real CapacityMultiplier shock injection (max_dev 4.1%, within ±5% spec) - **#821 (server tick integration)** — econ-sim extracted as library crate (`lib.rs` + `sim.rs`); `Simulation` stateful runner; `EconSimResource` + `EconStateResource` (7 D-181 signals per active node); `tick_economy_simulation` Bevy system advances 1 economy tick per 10 game ticks (D-031); graceful no-op when `systems.db` absent - **#822 (IPC bridge)** — Protocol v20 → v21; `EconStateQuery` PlayerAction variant; `EconomySnapshot`/`EconNodeSnapshot` wire types; `EconQueryBuffer` + `serve_econ_state_query` system; `economy_snapshot` field on `ObserverSnapshot` - **#823 (debug commands)** — `InjectEconEvent` (fires D-180 events from console), `SetEconParam` (runtime α/β tuning — ALPHA/BETA promoted to `pub const` + `Simulation` fields), `GetEconState` (7-signal human-readable dump); `EconDebugEffect` and `EconParamKind` enums ## Test plan - [x] `cargo check` — zero errors, zero warnings - [x] `cargo clippy` — clean - [x] `cargo fmt` — applied - [x] 1147 unit tests pass (`cargo test --lib`) - [x] Integration tests pass (`cargo test --test integration_layer3`) - [x] Pre-push hook: fmt OK, clippy OK, ruff OK - [x] D-179 stability: cold-start ±3.8%, long-run ±1.2%, shock recovery 4.1%, cross-zone ±0.9% - [ ] Live Gauntlet test with `systems.db` present (validates `try_load_economy` hot path) - [ ] Client-side: send `EconStateQuery{system_id: "sol"}` and verify `economy_snapshot` appears 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpmschweitzer added 2 commits 2026-04-10 13:26:03 +02:00
Implements the full D-180/D-181 economics pipeline:

**#810 — Event input port (D-180)**
- Add EconEvent struct with Target/Effect/Duration/Visibility variants
- Implement EventPort as typed input queue for external disruptions
- Apply events in simulation step; D-179 Test 3 now uses real shock injection

**#821 — Integrate econ-sim into server tick loop**
- Extract econ-sim as library crate (lib.rs + sim.rs, Cargo.toml [lib] section)
- Add Simulation stateful runner; step() advances one economy tick
- Add EconSimResource, EconStateResource (7 D-181 signals), tick_economy_simulation
- Economy loads once at startup; graceful no-op when systems.db absent
- Server advances economy 1 tick per 10 game ticks (D-031)

**#822 — Expose economy state over IPC bridge**
- Protocol version 20 → 21
- Add EconomySnapshot, EconNodeSnapshot wire types
- Add EconStateQuery PlayerAction variant; response in economy_snapshot field
- Add EconQueryBuffer resource + serve_econ_state_query system

**#823 — Economics debug commands**
- Add InjectEconEvent, SetEconParam, GetEconState to DebugCommandKind
- Add EconDebugEffect, EconParamKind enums
- SetEconParam mutates α/β at runtime (α/β promoted to pub const + Simulation fields)
- ALPHA and BETA constants threaded through step_inner/trade_step signatures

All 1147 unit tests pass; zero warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- `economy.rs`: fix empty_line_after_doc_comments (section ordering),
  use `is_multiple_of` for ECON_TICK_RATE check
- `debug.rs`, `input.rs`, `mod.rs`: rustfmt import ordering + indentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Author
Owner

Review: sprint-34/server -> main (type: code)

PR #125feat(simulation): economics integration — D-180 event port, D-181 signals, IPC bridge, debug commands (#810 #821 #822 #823)
4 tickets, 19 files, 1465 insertions

Pre-checks: Cargo clippy clean (zero warnings). No runtime smoke test mentioned.


Hoshe (Code Quality): REQUEST_CHANGES

Solid, well-structured integration — clean architecture, graceful degradation throughout, thorough D-180/D-181 spec coverage. Four issues.

# File Issue
1 server/tests/serialization.rs L363 Stale protocol version assertion. Test asserts PROTOCOL_VERSION == 20 but PR bumped to 21. Will fail CI.
2 econ-sim/src/sim.rs ~L107 Silent u64→u32 truncation. self.tick as u32 for activate_scheduled wraps at u32::MAX. Widen EventPort methods to u64 or add overflow handling.
3 econ-sim/src/events.rs L293-314 String allocation in hot-path lookup. demand_for/productivity_for/capacity_for allocate two Strings per call. Guard with is_identity() or restructure.
4 server/src/simulation/mod.rs L171 try_load_economy(0)#TODO without ticket. StartupMessage has world_seed. Create ticket or wire it now.

Tyre (Architecture): REQUEST_CHANGES

Architecturally solid — clean library extraction, D-010 BTreeMap discipline, D-180 lifecycle matches documented sequence. Five issues.

# File Issue
1 econ-sim/src/sim.rs L106 Tick type narrowing u64→u32. (Same as Hoshe #2.) Widen EventPort to u64.
2 economy.rs L221-223 Vec::remove(0) as ring buffer. Change to VecDeque with pop_front().
3 bridge/mod.rs + simulation/mod.rs Missing ordering. handle_debug_commands unordered vs tick_economy_simulation. GetEconState returns stale signals same-tick. Add .after(tick_economy_simulation).
4 economy.rs serve_econ_state_query D-181 visibility not documented. All 7 signals sent including Private/Meta. Correct for Phase 2 per D-181, but needs an explicit scope comment.
5 economy.rs rebuild_signals L231-248 Double lookup for stockpile/demand. Extend snapshot tuple to include them.

Verdict: CHANGES REQUESTED

2/2 reviewers request changes. 8 unique actionable issues (1 shared between reviewers).

## Review: sprint-34/server -> main (type: code) **PR #125** — `feat(simulation): economics integration — D-180 event port, D-181 signals, IPC bridge, debug commands (#810 #821 #822 #823)` 4 tickets, 19 files, 1465 insertions **Pre-checks:** Cargo clippy clean (zero warnings). No runtime smoke test mentioned. --- ### Hoshe (Code Quality): REQUEST_CHANGES Solid, well-structured integration — clean architecture, graceful degradation throughout, thorough D-180/D-181 spec coverage. Four issues. | # | File | Issue | |---|------|-------| | 1 | `server/tests/serialization.rs` L363 | **Stale protocol version assertion.** Test asserts `PROTOCOL_VERSION == 20` but PR bumped to 21. Will fail CI. | | 2 | `econ-sim/src/sim.rs` ~L107 | **Silent `u64→u32` truncation.** `self.tick as u32` for `activate_scheduled` wraps at `u32::MAX`. Widen `EventPort` methods to `u64` or add overflow handling. | | 3 | `econ-sim/src/events.rs` L293-314 | **String allocation in hot-path lookup.** `demand_for`/`productivity_for`/`capacity_for` allocate two Strings per call. Guard with `is_identity()` or restructure. | | 4 | `server/src/simulation/mod.rs` L171 | **`try_load_economy(0)` — `#TODO` without ticket.** `StartupMessage` has `world_seed`. Create ticket or wire it now. | --- ### Tyre (Architecture): REQUEST_CHANGES Architecturally solid — clean library extraction, D-010 BTreeMap discipline, D-180 lifecycle matches documented sequence. Five issues. | # | File | Issue | |---|------|-------| | 1 | `econ-sim/src/sim.rs` L106 | **Tick type narrowing `u64→u32`.** (Same as Hoshe #2.) Widen `EventPort` to `u64`. | | 2 | `economy.rs` L221-223 | **`Vec::remove(0)` as ring buffer.** Change to `VecDeque` with `pop_front()`. | | 3 | `bridge/mod.rs` + `simulation/mod.rs` | **Missing ordering.** `handle_debug_commands` unordered vs `tick_economy_simulation`. `GetEconState` returns stale signals same-tick. Add `.after(tick_economy_simulation)`. | | 4 | `economy.rs` `serve_econ_state_query` | **D-181 visibility not documented.** All 7 signals sent including Private/Meta. Correct for Phase 2 per D-181, but needs an explicit scope comment. | | 5 | `economy.rs` `rebuild_signals` L231-248 | **Double lookup for stockpile/demand.** Extend snapshot tuple to include them. | --- ### Verdict: CHANGES REQUESTED 2/2 reviewers request changes. 8 unique actionable issues (1 shared between reviewers).
jpmschweitzer added 2 commits 2026-04-10 14:07:24 +02:00
- Widen EventPort tick methods from u32 to u64 (prevents overflow)
- Add is_identity() guard on hot-path String allocation in modifiers
- Replace Vec::remove(0) with VecDeque::pop_front() in price history
- Add .after(tick_economy_simulation) ordering for debug commands
- Fix stale PROTOCOL_VERSION assertion (20 → 21) in serialization test
- Add D-181 Phase 2 visibility scope comment on serve_econ_state_query
- Eliminate double lookup in rebuild_signals via single-pass extraction
- Track economy seed TODO with backlog ticket reference

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Author
Owner

Review: sprint-34/server -> main — Round 2

Hoshe (Code Quality): APPROVE

All 8 fixes verified correct. u64 widening consistent, VecDeque correct, is_empty() guards properly placed, protocol assertion updated, ticket reference added.

Tyre (Architecture): APPROVE

All 5 architectural fixes clean. u64 type runs unbroken from sim to wire. No cycle risk in ordering. D-181 comment accurate. No double lookups remain.

Verdict: APPROVED

2/2 reviewers approve. Ready to merge.

## Review: sprint-34/server -> main — Round 2 ### Hoshe (Code Quality): APPROVE All 8 fixes verified correct. u64 widening consistent, VecDeque correct, is_empty() guards properly placed, protocol assertion updated, ticket reference added. ### Tyre (Architecture): APPROVE All 5 architectural fixes clean. u64 type runs unbroken from sim to wire. No cycle risk in ordering. D-181 comment accurate. No double lookups remain. ### Verdict: APPROVED 2/2 reviewers approve. Ready to merge.
jpmschweitzer closed this pull request 2026-04-10 14:19:27 +02:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#125