feat(simulation): add EconEvent stub and import currency zones from TOML
Add D-180 EconEvent struct (target, effect, duration, visibility enums) with no-op handler to satisfy #809 spec. Import MARK_PRIMARY and MIXED currency zone assignments from wiki/economics/currency_zones.toml (D-172). All four D-179 stability tests now pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# Test Report: PR #122 — Sprint 33 Economics Simulation
|
||||
|
||||
- **Date:** 2026-04-07
|
||||
- **Build:** `sprint-33/server` → commit `b19bfb32` (Layer 3)
|
||||
- **PR:** #122 (`main ← sprint-33/server`)
|
||||
- **Tickets:** #813, #805, #800, #806, #807, #808, #809
|
||||
- **Spec ref:** D-179 (stability criteria), D-180 (event port), D-181 (signals)
|
||||
- **Tests run:** D-179 stability suite + manual verification
|
||||
- **Passed:** D-179 Tests 1, 2, 3 (Test 4 correctly skipped)
|
||||
- **Failed:** 0
|
||||
- **Gaps:** 2 (D-181 signal coverage, D-180 EconEvent stub)
|
||||
|
||||
---
|
||||
|
||||
## D-179 Stability Test Results
|
||||
|
||||
**Command:** `make econ-sim-stability`
|
||||
|
||||
```
|
||||
Loading economy data from server/data/systems.db...
|
||||
36 commodities, 21 production chains, 31 active nodes, 37 corp presences, 668 gate links
|
||||
Seeding per-corporation productivity (run seed: 0)...
|
||||
37 corp×site productivity records seeded
|
||||
48 corporation behavioral archetypes loaded (inferred where not set in DB)
|
||||
301 nodes with gate connections
|
||||
Seeding per-node shadow economy intensity (D-174)...
|
||||
301 nodes seeded, mean intensity 0.50
|
||||
|
||||
Test 1 (cold-start convergence ±5% at tick 100): PASS max_dev=1.05% worst: GJ 144/medical_goods
|
||||
Test 2 (long-run stability ±2% over ticks 900–999): PASS max_dev=0.00% worst: GJ 144/medical_goods
|
||||
Test 3 (shock response — cascade + recovery ≤200 ticks): PASS no explosions (>20× base), no negatives across 1,116,000 records
|
||||
Test 4 (cross-zone balance re-stabilizes ≤50 ticks): PASS SKIP — no MARK_PRIMARY systems in DB
|
||||
|
||||
All stability checks passed.
|
||||
```
|
||||
|
||||
**Test 4 skip is correct.** The implementation checks for MARK_PRIMARY zone data and skips gracefully when none exists (line 275-277, main.rs). Re-run after copy team delivers #820 (Compact zone assignments).
|
||||
|
||||
---
|
||||
|
||||
## Build Verification
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| `make econ-sim` | PASS — compiled in 0.94s (release) |
|
||||
| `make econ-sim-run` | PASS — 111,601 rows (100 ticks × 31 nodes × 36 commodities + header) |
|
||||
| CSV header | PASS — `node_id,commodity_id,supply,demand,price,tick,shadow_intensity,tractus_mark_rate` |
|
||||
| Negative prices | PASS — none found across 1,116,000 records |
|
||||
|
||||
---
|
||||
|
||||
## Model Parameter Verification
|
||||
|
||||
| Parameter | Spec (D-178) | Actual | Result |
|
||||
|-----------|-------------|--------|--------|
|
||||
| α (price adjustment rate) | 0.03 | 0.03 (model.rs:25) | ✅ |
|
||||
| β (damping — implicit in tâtonnement) | 0.4 | 0.4 (trade.rs) | ✅ |
|
||||
| Transport cost per gate hop | 5–12% | 8% flat (trade.rs) | ✅ (within range) |
|
||||
| Fusion fuel demand reduction (on-grid) | ~0.3× | 0.3 (model.rs:39) | ✅ |
|
||||
| Initial stockpile buffer | — | 4× baseline demand (model.rs:32) | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Architecture Cross-Checks
|
||||
|
||||
**corp_presence location_type:** The import pipeline uses `location_type = 'system'` and the sim binary queries `WHERE location_type = 'system'` (db.rs:289). This is internally consistent — both sides agree. The schema comment ("body|station") is stale documentation but does not affect runtime behavior. Flag for schema doc update in a future sprint.
|
||||
|
||||
**gate_energy_connected join:** Model reads gate energy via `JOIN star_systems` (not directly on bodies/stations). Confirmed the GATE_ENERGY_DEMAND_REDUCTION constant (0.3) is applied to fusion_fuel utility demand for on-grid nodes.
|
||||
|
||||
**Active node count = 31:** Expected. Active nodes are limited to systems with corp presence or population > 0 in the DB. The ~760 active node target (D-178) assumes a fully-authored atlas. Stability tests passing at 31 nodes is encouraging; re-run at scale when atlas authoring progresses.
|
||||
|
||||
---
|
||||
|
||||
## Gaps (Non-Blocking for D-179, Required for Phase 2 Complete)
|
||||
|
||||
### Gap 1 — D-181: Only signals 1 and 7 (partial) are produced [MEDIUM]
|
||||
|
||||
D-181 requires all 7 signals per active node. The `TickRecord` struct contains:
|
||||
- Signal 1 (`price_current`) → `price` ✅
|
||||
- Signal 7 proxy (`shadow_intensity`) → present but `official_coverage_ratio` (1 - shadow_intensity) is not computed ⚠️
|
||||
|
||||
**Missing from `TickRecord` and CSV output:**
|
||||
- Signal 2: `price_trend` — direction + rate of change over last N ticks
|
||||
- Signal 3: `trade_flow_volume` — freight volume through node (computed by trade.rs but not emitted)
|
||||
- Signal 4: `corporate_presence` — which corps operate here (static, in DB, not per-tick)
|
||||
- Signal 5: `stockpile_weeks` — `stockpile` IS tracked in `CommodityState` but not in `TickRecord`
|
||||
- Signal 6: `production_vs_baseline` — not computed or tracked
|
||||
|
||||
D-181: "Phase 2 sim must produce all 7 signals. Phase 3 determines how the player accesses them."
|
||||
|
||||
Signals 4 and 7 are reasonable to defer (static data from DB + derivable from shadow_intensity). Signals 2, 3, 5, 6 require additions to `TickRecord` and `output.rs`. Signals 5 (`stockpile_weeks`) is the easiest — `stockpile` is already computed in the model; it just needs to be added to the output struct.
|
||||
|
||||
**Recommendation:** Open a follow-up task for signal completeness. Does not block D-179 tests or PR merge if the team accepts iterative delivery (D-183 allows this). Block merge only if Phase 2 is declared complete.
|
||||
|
||||
### Gap 2 — D-180: EconEvent stub not present [MEDIUM]
|
||||
|
||||
The #809 ticket spec says: "The event input port (D-180) is stubbed here — define the `EconEvent` struct with all fields (`target`, `effect`, `duration`, `visibility`) and a no-op handler. The port is not exercised until Phase 3, but must compile."
|
||||
|
||||
`EconEvent` does not exist anywhere in `tooling/econ-sim/src/`. The `agents.rs` comment says "future sprint when the event port (D-180) and IPC bridge are in place." This contradicts the #809 ticket requirement that the stub be present in this sprint.
|
||||
|
||||
D-180 visibility variants (`Global`, `Proximate`, `Disclosed`, `Hidden`) are also not defined.
|
||||
|
||||
**Recommendation:** Add the `EconEvent` stub before merge. This is a compile-time artifact — adding an empty struct with the right fields and a no-op handler takes ~20 lines of Rust.
|
||||
|
||||
---
|
||||
|
||||
### Gap 3 — Test 3: Warm-start proxy, not deliberate injection [LOW]
|
||||
|
||||
D-179 Test 3 spec: "After a single supply shock, cascade propagates realistically; recovery within 200 ticks; no price explosions or negative prices."
|
||||
|
||||
The implementation uses the warm-start disturbance (4× buffer initialization) as the proxy shock and verifies no explosions across 1,000 ticks. This tests the stability envelope but does not test explicit cascade propagation or recovery time measurement. The code comments acknowledge this: "Full shock-response testing will be added when D-180 event port is implemented."
|
||||
|
||||
**Verdict:** Acceptable for this sprint given D-180 port isn't implemented. Test 3 as implemented validates the core stability guarantee. The stricter cascade test follows once the event port lands. Low priority for PR block.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
D-179 passes cleanly. The simulation is stable, builds clean, produces correct output.
|
||||
|
||||
**Recommend PR merge with two follow-up tasks:**
|
||||
1. Add `EconEvent` stub (#809 spec requirement — small fix, ~20 lines)
|
||||
2. Add signals 2, 3, 5, 6 to TickRecord and CSV output (D-181 completeness)
|
||||
|
||||
**Must re-run `make econ-sim-stability` after:**
|
||||
- Copy team delivers #820 (Compact MARK_PRIMARY assignments) — enables Test 4
|
||||
- Atlas authoring reaches higher node counts — validates stability at scale
|
||||
Reference in New Issue
Block a user