Economics simulation sprint — skeleton binary through corporate agents. 13 tickets across server/copy/client/ci. Stability tests (D-179) are the sprint exit condition. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
9.9 KiB
Sprint 33: Pecunia — Server Tasks
Goal: Full economics simulation running — Leontief production, spatial price equilibrium, currency zones, corporate behavioral agents across all three corporation tiers, stability tests passing.
Branch: sprint-33/server
Agents: Dudley (simulation dev), Tyre (architecture), Hoshe (QA)
New Tickets
| # | Title | Blocked by |
|---|---|---|
| #813 | Energy-over-gate schema extension | — |
| #805 | Extend economy-db with corporation pipeline and validation | #804 (DONE) |
| #806 | Build skeleton economy_sim binary | #805 |
| #807 | Add trade flows and stability testing | #806 |
| #808 | Add currency zones and exchange rates | #807 |
| #809 | Add corporate agent behavior | #808, #799, #800 |
Use tooling/db/ticket show <id> for full ticket details.
Key Decisions
decisions/economics.md— D-171 (three-currency system), D-172 (currency zone initialization), D-173 (commodity taxonomy), D-174 (shadow economy layer), D-175 (corporation taxonomy), D-176 (productivity seeding), D-177 (productivity constraints), D-178 (economic model architecture), D-179 (stability acceptance criteria), D-180 (event input port), D-181 (signal vocabulary), D-182 (TOML source of truth), D-183 (iterative development cycle), D-184 (commodity catalog 36 types), D-185 (brands not commodities), D-186 (gate transmission levels), D-187 (fusion fuel as intermediate)decisions/architecture.md— D-166 (development cascade: Phase 2 deliverable = economics spreadsheets/graphs with runtime-tweakable simulation)
Notes
#813 — Energy-over-gate schema extension
currency_zonecolumn already exists onstar_systems(server/data/systems-schema.sql). Need to addgate_energy_connectedboolean column to the appropriate node table.- Per D-186:
MARK_PRIMARYzones default togate_energy_connected = false(Compact refused Gate Corp dependency deliberately). All other zones default totrue. - Demand reduction: nodes with
gate_energy_connected = trueget ~0.3×fusion_fuelutility demand. The reduction applies only to utility/habitation consumption — industrial chain inputs (smelt_ore0.3,alloy_fabrication0.2,electronics_fabrication0.2) are unaffected. - This is a schema + migration ticket. No simulation logic yet — that is consumed by #806.
- The
gate_energy_connectedfield will be read by the sim binary when it computes per-node utility demand.
#805 — Extend economy-db with corporation pipeline and validation
- The existing import pipeline (
tooling/economy-db/import_economics.py) already handles: gate_links, commodities, production_chains, currency_zone on star_systems. Thecorp_presencetable exists in schema but the comment at line 12 reads "Does NOT populate corp_presence — that's a future pipeline step." This is that step. - Extend the pipeline to: read
wiki/corporations/*.mdand/or the DBcorporationstable, populatecorp_presencerows from authored location data, validate that wiki corporation names match DBcorporations.proper_namerecords (sync constraint from D-182), enforce coverage rules: 3+ corporations per major commodity type, 1+ per inhabited system with population > 100K. - Add chain completeness validation: every intermediate commodity must have at least one production chain that produces it.
- Coverage validation failures must be hard errors (non-zero exit), not warnings. The Phase 2 prerequisite from D-175 requires this gate.
- Input:
wiki/corporations/markdown files,server/data/systems.db(corporations and system_economy tables). Output: populatedcorp_presencetable.
#806 — Build skeleton economy_sim binary
- New Rust binary at
tooling/econ-sim/. Follow patterns fromserver/src/bin/atlas/for CLI structure (argparse via clap, SQLite reads via rusqlite). - Loads transport graph from
systems.db(gate_linkstable, bidirectional). Reads economy config from the built.db(commodities, production_chains, chain_inputs, corp_presence). - Seeds per-corporation productivity from PRNG seed (D-176): five dimensions (
extraction_rate,processing_throughput,transit_capacity,service_throughput,service_capacity). Log-normal distribution, 0.4–1.8× multiplier for standard nodes, 0.7–1.4× for monopoly-source nodes. Corridor correlation ~0.6 — nearby sites should draw correlated samples. - Initial scope: Leontief production + consumption + price adjustment (Layer 1 only, per D-178). No inter-system trade flows, no currency zones, no corporate behavior.
- Outputs per-node CSV with: node_id, commodity_id, supply, demand, price, tick.
- The
--stability-checkflag is scaffolded here but not yet meaningful — it will be exercised in #807. - Lore-derived constraints from D-177 must be respected: do not seed location of production, biological monopoly ceilings, aging pipeline contents, or gate topology.
#807 — Add trade flows and stability testing
- Extends the binary from #806 with Layer 2 (spatial price equilibrium via damped tâtonnement, α=0.03, β=0.4, per D-178).
- Prices propagate through the gate transport graph. Lagged adjustment — not instant equilibrium. Transport costs: 5–12%/hop on gate edges, 1–3% on orbital edges.
- Market node tiering (D-178): ~760 active market nodes (inhabited bodies + all stations), ~240 passive producers (feed output to nearest active node), ~2,700 inert. Floyd-Warshall over active subgraph at startup (~0.5s expected, one-time cost).
- Stockpile buffers per node: prevents instantaneous price explosions on single-tick supply disruptions.
--stability-checkmode must now pass Tests 1 and 2 from D-179:- Test 1: Cold-start convergence — prices settle within ±5% of equilibrium within 100 game-days.
- Test 2: Long-run stability — zero drift > ±2% over 1,000 game-days with zero external events.
- If the model oscillates or diverges under no external input, that is a broken model, not a feature. Tune α/β first before concluding the model is wrong.
#808 — Add currency zones and exchange rates
- Extends the binary with Layer 2 currency dynamics (per D-171, D-172).
- Three currencies: Tractus (numeraire), Mark (Compact zone), Sol (shadow only — no formal exchange rate, modeled as shadow economy commodity per D-174).
- Cross-zone conversion friction: ~3% cost on Tractus↔Mark trade. Zero internal friction within
MARK_PRIMARYzones (Compact "no internal tariffs" principle). - Exchange rate float driven by trade balance — Tractus/Mark rate adjusts over time based on cross-zone import/export imbalances.
- Shadow economy modifier: apply per-node
shadow_economy_intensity(0.0–1.0, from authoredwiki/economics/shadow_economy.toml— authored by copy team in #803) to adjust shadow pricing signals. Theofficial_coverage_ratiosignal (D-181 signal 7) is derived from this. --stability-checkmust now also pass Tests 3 and 4 from D-179:- Test 3: Shock response — after single supply shock, cascade propagates realistically, recovery within 200 ticks, no price explosions or negative prices.
- Test 4: Cross-zone trade balance — after cross-zone trade volume change, exchange rate adjusts and re-stabilizes within 50 ticks.
- Compact zone connectivity:
gate_energy_connected = falsenodes (from #813) should show elevatedfusion_fuelutility demand in their signals.
#809 — Add corporate agent behavior
- Extends the binary with Layer 3 (corporate behavioral agents, per D-178).
- Six behavioral archetypes (D-175): Monopolist, Distributor, Producer, Specialist, Cooperative, Intermediary. Parameters are template-instantiated — read archetype templates from
wiki/economics/archetypes/behavioral.toml, then instantiate per corporation from the populatedcorp_presencetable. - Corporations must be loaded from the DB (populated by #805 and seeded by copy team work in #799/#800). Do not hardcode corporation data.
- Each archetype has distinct price-setting behavior, trade routing preferences, and response to competitor presence. Details in
decisions/economics.mdD-175 andwiki/economics/archetypes/behavioral.toml. - The event input port (D-180) is stubbed here — define the
EconEventstruct with all fields (target,effect,duration,visibility) and a no-op handler. The port is not exercised until Phase 3, but must compile. - All 7 signals from D-181 must be produced per active node:
price_current,price_trend,trade_flow_volume,corporate_presence,stockpile_weeks,production_vs_baseline,official_coverage_ratio. - This ticket closes the sprint: when all four stability tests pass with corporate agents active, the Phase 2 economics simulation is functionally complete.
- Blocked by #808 (currency layer must be in place) and #799/#800 (copy team corporation corpus must be available in DB).
Dependency Chain
#813 (energy-over-gate schema) → consumed by #806, #808
#805 (corp pipeline + validation) → #806 (skeleton sim)
→ #807 (trade flows + stability)
→ #808 (currency zones)
→ #809 (corporate agents)
#799 (Tier-2 corps, copy) ─────────────────────────────────┐
#800 (Tier-3 pipeline, server) ────────────────────────────→ #809 (corporate agents)
Note: #800 (Tier-3 generation pipeline) is assigned to the server team (it is a Rust binary), but its output depends on archetype taxonomy (#798, DONE) from copy. Coordinate with copy team on wiki/economics/archetypes/ TOML format before starting #800.
PR Workflow
When ready to submit, create a PR with tea CLI. All flags are required to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(simulation): description" --description "body" --base main --head sprint-33/server