Commit Graph
1921 Commits
Author SHA1 Message Date
jpmschweitzer 64bb83f749 fix(simulation): address PR #129 review — brand importer hardening
- V-B06 enum validation: the five VALID_* sets
  (VALID_BRAND_CATEGORIES, VALID_VALUE_TRAJECTORIES, VALID_SCARCITY_CLASSES,
  VALID_BRAND_TIERS, VALID_CURRENCY_DENOMINATIONS) were defined but never
  referenced. brand_products.brand_category etc. are plain TEXT with no
  CHECK constraints, so a typo like `brand_category = "terrior"` silently
  imported. `validate_brands` now runs a V-B06 pass that asserts every
  enum column is a member of its VALID_* set. V-B01..V-B05 + V-B06 all
  reported together on import failure.

- Explicit transaction wrapper: the clear-then-reimport cycle (10 DELETEs
  followed by 9 imports and structural validation) used to depend on
  Python's implicit-deferred-transaction semantics and sys.exit() on
  validation failure. A crash mid-import could leave the DB with some
  tables empty and others intact. The body now runs inside
  `conn.execute("BEGIN")` + try/except with an explicit `_ImportAborted`
  for validation failures and a `BaseException` catch-all for
  KeyboardInterrupt / programmer errors. All failure paths rollback
  before exit; the commit only fires after structural validation
  passes. Dry-run leaves the transaction open so the coverage check
  below can still SELECT against in-memory state.

- system_fiscal docstring: previously cited the D-189 §6 derived
  formula (`collection_efficiency = 1.0 - shadow_economy_intensity × 0.6`)
  while the implementation hardcodes `collection_efficiency = 0.85` for
  every system. The docstring now explicitly states these are Phase 2
  placeholder values (with named constants PHASE2_CORP_TAX_RATE and
  PHASE2_COLLECTION_EFFICIENCY) and calls out the shadow_economy.toml
  pipeline as the Phase 3 follow-up.
2026-04-15 09:15:16 +02:00
jpmschweitzer 56d524f37d docs(decisions): address PR #129 review — D-191 §8 amendment + boundary notes
Blocking PR #129 items 1, 2 (plus polish 16 and 17):

- D-191 §8 prose rewritten to match the code. The previous amendment said
  positions were `{x, y}` objects against a "typically 1024 × 512" grid,
  but the generator, the six hand-authored templates, and all 2394
  procedural seed files ship `[row, col]` integer arrays against a
  `{"w": 512, "h": 256}` grid. The decision doc is now aligned with
  reality: positions are `[row, col]`, the storage grid is 512 × 256,
  and the row-first ordering is called out explicitly so readers can
  cross-reference NumPy/flood-fill/A*/cost-grid conventions.

- §8 now follows the D-094 amendment pattern. The superseded 2026-04-10
  prose is preserved verbatim as "Original (superseded)" with a dated
  Amendment block on top — future readers can see what changed and why
  instead of silently losing the history.

- brands.toml header gains a short Phase 2 boundary note. The 4 anchor
  brands come from D-189 §5; the additional ~23 brands from D-189 §11
  are deliberately deferred to Phase 3 — Phase 2 only needs the demand-
  node plumbing and V-B01..V-B06 validation exercised end-to-end.

- systems-schema.sql `bodies.terrain_reference` comment now pins the
  repo-root-relative path convention (wiki/star-systems/<slug>/bodies/
  <body_id>/heightmap.png) so the three downstream pipelines (populate,
  atlas generator, client loader) share a documented contract instead
  of drifting against an unwritten convention.
2026-04-15 09:12:08 +02:00
jpmschweitzer 5619218e31 feat(tooling): generate_atlas.py city + infrastructure pipeline and atlas DB index (#832)
Implements the Phase 3 atlas content generator per D-191 §3, §8, and §9.

Pipeline per body (terrain-aware, deterministic per seed + body):
  1. Simulate terrain via planet_simulation.simulate().
  2. Analyse continents (flood-fill), habitability (temp/moisture/slope +
     coastal bonus), river mouths, and a terrain A* cost grid.
  3. Place cities sequentially — capital first (habitability + river-mouth
     bias), then corridor growth via multi-source Dijkstra, quadrant-spread
     penalty after 2 cities in a quadrant, port-on-new-continent bonus at
     cities 3–4. ±25% noise for seed variation.
  4. Generate roads and railroads as an MST over city positions, with
     A* paths on the terrain cost grid (rail follows roads where possible).
  5. Place a transit POI at the capital (15% chance to scatter to a
     secondary city).

Output (canonical markers.json schema, pixel space per D-191 §8):
  - cities:    {id, name, kind, center:[r,c], population}
  - roads:     {id, name, kind, path:[[r,c],...]}
  - railroads: {id, name, kind, path:[[r,c],...]}
  - pois:      {id, name, kind, center:[r,c]}
  - existing rivers/oceans/mountain_ranges preserved untouched.

City names are left empty for gemma_naming.py (#833). Body population is
split across cities with geometric decay (capital ~50%, each subsequent
city half the previous). The 6 hand-authored bodies (Lendel, Edict,
Vuurkloof, Røros, Cairnside, Estrade) are detected by existing
`cities` and skipped for regeneration; their markers are still synced
to the DB index below.

Atlas index in systems.db (new):
  - atlas_body_grids, atlas_cities, atlas_roads, atlas_railroads,
    atlas_pois, atlas_rivers, atlas_oceans, atlas_mountain_ranges
  - Scalar metadata mirror of every markers.json — the implant atlas app
    and development queries can lookup cities/POIs/features without
    scanning 267 JSON files. Polyline geometry stays in the markers.json
    files next to the heightmaps (used by the renderer); the DB only
    stores filterable scalar fields plus `point_count` as a length proxy.
  - Schema lives in server/data/systems-schema.sql; generate_atlas.py
    mirrors the CREATE TABLE IF NOT EXISTS block so it runs against any
    DB state (matches the economy-db importer pattern).
  - Populated and refreshed on every run. Each body's rows are deleted
    and reinserted deterministically — no stale state.

Also fixes a pre-existing WIP bug in the quadrant-saturation penalty
loop (a stray outer `for r in range(GRID_H)` with unreachable breaks
meant only the NW quadrant was ever checked).

Runtime: 280s for all 267 inhabited bodies on a single core. 265 bodies
updated this run, 6 hand-authored bodies synced to DB without
regeneration.

Atlas index after run:
  atlas_cities             329    (15 hand-authored + 314 awaiting #833)
  atlas_roads               46
  atlas_railroads           44
  atlas_pois               287
  atlas_rivers            2034
  atlas_oceans             696
  atlas_mountain_ranges   1953
  atlas_body_grids         267
2026-04-15 08:46:55 +02:00
jpmschweitzer d6d3b51098 docs(decisions): D-191 §8 canonical markers.json format is pixel space
The generator and the hand-authored templates (Edict, Vuurkloof, Røros,
Cairnside, Estrade) already store markers in heightmap pixel space with
a grid header. Update §8 to match: {x, y} integer pixels are the storage
format, and lat/lon strings become a display-time derivation in the
atlas UI (synthesized from position + grid dimensions + body radius).

Avoids double-conversion through an equirectangular projection and keeps
the hand-authored markers.json files as-is.
2026-04-14 17:30:37 +02:00
jpmschweitzer b127f63dc2 feat(tooling): populate terrain_reference column for inhabited bodies (#839)
Adds tooling/planet-gen/populate_terrain_reference.py and runs it against
systems.db. Resolves each body's expected wiki heightmap path (repo-root
relative) and writes it into bodies.terrain_reference. Missing heightmaps
are logged for remediation.

Result: 2380/3240 bodies populated, 860 still missing heightmaps. This
unblocks generate_atlas.py (#832) for every body that has a heightmap.
2026-04-14 17:25:56 +02:00
jpmschweitzer 03e0d1c022 feat(simulation): brand layer schema and import pipeline (#827)
Adds the brand layer per D-189 §5:
- Schema: brand_products, brand_inputs, system_fiscal, corp_financial_state,
  corp_lifecycle_events (+ 5 indexes).
- Importer: reads wiki/economics/corporations/brands.toml, populates the
  new tables, validates V-B01–V-B05 structural rules, and derives
  system_fiscal for inhabited systems.
- Data: 8 brand_products, 16 brand_inputs, 301 system_fiscal rows.

Brand products are demand nodes — they consume commodities; they are not
commodities themselves (D-185). Depends on copy PR #127 for the corp
records referenced by brands.toml.
2026-04-14 17:24:51 +02:00
jpmschweitzer 826b6fe1c7 Merge remote-tracking branch 'origin/main' into sprint-35/server 2026-04-14 17:22:09 +02:00
jpmschweitzer 920ea0582f feat(simulation): thread world seed from StartupMessage into economy (#826)
Replaces the hardcoded seed=0 with the seed received in StartupMessage,
threading it through SimulationPlugin -> EconomyPlugin / SimRng. Integration
test fixtures updated for the new SimulationPlugin { seed } signature.
2026-04-14 17:21:53 +02:00
jpmschweitzerandClaude Opus 4.6 9439a20253 content(wiki): PR #127 review fix pass — 15 findings
Applies all review findings from Hoshe + Paula + Miri on PR #127.

Glossary (wiki/glossary.md):
- Remove self-referential "tâtonnement" from its own NOT list.
- Add NOT/NOTE annotation-prefix preamble.
- Replace ambient "open question" note on Commission with explicit
  Q-095 citation; add "Lattice Commission" to NOT list.

Decisions:
- Claim Q-095 (content) — "Commission formal name — authoritative
  designation"; register in decisions/questions.md index.

Marker POI renames (glossary.md line 25 — "Syndicate" is prohibited;
glossary.md lines 14–16 — "Lattice Commission" is undocumented):
- GJ280Ad: "Syndicate Editorial Complex" → "Parallax Media Centre";
  "Commission Content Review Office" → "Parallax Standards Office".
- GJ66Bc: "Syndicate Trade Office" → "Compact Trade Representative";
  "Voss Gate Terminal" → "Røros Gate Terminal".
- GJ244Ad: "Lattice Commission — Sirius Office" → "Commission — Sirius Office".
- GJ35c: "Prime Surface Depot — Gate Terminal" → "Terras Gate Terminal".
- GJ892d (Cairnside): "Cairnside Primary" → "Okafor Base" (frontier
  founder-surname pattern per glossary.md line 74); "Primary Access
  Road" → "Cairn Scarp Track" (derived from Cairn Reach Scarp).

Brand templates (wiki/economics/archetypes/brand_templates.toml):
- Deep-harvest seafood archetype: Korean/Tagalog → Korean/Japanese
  across naming_pattern and description fields, per D-189 §11.
- 11 terroir + heritage_craft _reach_wide variants now show BOTH
  corridor-origin and neutral example names, per cross-cultural
  mixing rule; inner_corridor/neutral monoculture removed.
- commodity_inputs header comment: add explicit "per tick" unit
  cross-reference to D-189 §5 and server/src/simulation/economy.rs.

Tier-1 corporations (wiki/economics/corporations/tier1.toml):
- Vins de Grand Vide: currency_preference "mixed" → "mark" — HQ
  booking currency must mirror the HQ-system canonical zone
  (GJ 395 Confluent → MARK_PRIMARY); "mixed" is reserved for hop 5–6
  transition systems.
- Bífröst Marmor: add NOTE surfacing the orbital-age formation
  anomaly (wiki/corporations/bifrost-marmor.md:70–71), alongside
  the existing reserve-silence comment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 16:07:20 +02:00
jpmschweitzerandClaude Sonnet 4.6 c26d74f45d content(atlas): hand-author markers for Estrade (GJ 280A) — Parallax media capital
Estrade (GJ280Ad) is the Reach's information/media hub: 1.8B population,
inner_corridor, service-mixed economy. Names 10 rivers, 2 water bodies,
3 mountain ranges; places 4 cities (Strata 1.1B, Vantage 450M, Ledger 150M,
Margin 100M); adds gate terminal + 3 institutional POIs, 2 roads, 1 railroad.

Complements #837 atlas template set (Lendel, Edict, Røros, Vuurkloof, Cairnside)
with a high-population urban service world example.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 19:50:15 +02:00
jpmschweitzerandClaude Opus 4.6 2d3361e24d content(atlas): hand-author markers.json for Edict, Vuurkloof, Røros, Cairnside (#837)
Author Phase 3 atlas quality-bar templates for 4 core systems alongside
the pre-existing Lendel template. Names, cities, roads/rail, and POIs
hand-placed against each body's heightmap and tied to the system's
corridor naming tradition.

- GJ244Ad Edict (Sirius system, inner_corridor) — Assembly institutional
  capital: Mandate 387M, Station Edict 13M, Founder's Range, Accord
  Peaks, Founding Ocean, Edict Deep Line rail.
- GJ35c Vuurkloof (Van Maanen's Star, south_reach) — volcanic geothermal
  settlement: Terras 290K, Kloofbas 50K, Groot Breuk, Ysterkop, Rantlyne
  underground rail. Afrikaans geology naming per wiki canon.
- GJ66Bc Røros (Voss system, west_reach) — Compact mining world:
  Storbjerg 3.2M, Hammervik 800K, Nordfjell, Rørosfjell, Storhav,
  Glåmelva. Norwegian/Scandinavian heritage naming.
- GJ892d Cairnside (deep frontier, research domes) — Cairnside Primary
  75M, Survey Post Kappa 5M, The Terraces, Baseline Lake, Baseline Rail.
  Technical frontier naming pattern.

All files match the implemented Lendel markers.json format (grid + pixel
coordinates, raw population, gate terminal as named POI). D-191 section 8
describes the schema in abstract lat/lon terms; server team should align
generate_atlas.py and D-191 prose with the on-disk format before #832
and #833 consume these as few-shot examples.

These templates serve as the quality bar for generator tuning and as
few-shot examples for the Gemma 2 naming pipeline (#833).

Ticket: #837
Decisions: D-191 (Phase 3 atlas), D-036 (Sova/Vuurkloof canon), D-144
(Sirius/Concord seat)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 19:47:21 +02:00
jpmschweitzerandClaude Sonnet 4.6 92ad6b9515 feat(wiki): Sprint 35 copy deliverables — glossary, brand corps, brand templates
- wiki/glossary.md: canonical proper nouns, factions, currencies, corridors,
  key locations, economics terminology, drift forms (tasks #840)
- wiki/economics/corporations/tier1.toml: add Calloway Distillery, Vins de Grand
  Vide, thrds, Bífröst Marmor brand corp records (#830)
- wiki/economics/archetypes/brand_templates.toml: 126 templates (42 archetypes ×
  3 scale tiers) covering all 8 brand categories and all 6 corridors (#831)
- wiki/index.md: add glossary link under Reference section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 19:43:49 +02:00
jpmschweitzerandClaude Sonnet 4.6 521c682175 chore(meta): plan Sprint 35: Atlas
Phase 3 launch sprint. 13 tickets across server, client, copy.
Atlas generation pipeline (terrain_reference, generate_atlas.py, Gemma naming),
brand layer DB schema, Atlas implant panel (3 levels + heightmap viewer + overlays),
hand-authored templates for Lendel + 4 core systems, brand corp TOML,
brand_templates.toml (120-130 archetypes), wiki glossary, world seed wiring.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 22:01:42 +02:00
jpmschweitzerandClaude Opus 4.6 26a6fd233c style(simulation): cargo fmt monologue trigger query
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:23:44 +02:00
jpmschweitzerandClaude Opus 4.6 5f678dac48 fix(simulation): address #843 review — seeding, atomics, API consistency
Review fixes from Hoshe + Tyre:
- EntityRng seeding: splitmix64(seed) ^ splitmix64(id) instead of
  splitmix64(seed + id) — eliminates collision class where adjacent
  seeds produce identical streams
- AtomicBool ordering: Relaxed → SeqCst for shutdown flag (correct
  on weakly-ordered architectures)
- Worker Drop: join handles instead of detaching threads
- Normalize stub API: remove ChunkGenWorker convenience wrappers,
  use .pool consistently across all 3 workers
- trigger_monologue: downgrade &mut to shared refs (no-op anchor
  was blocking parallel systems)
- Remove dead SimRng inserts from migrated monologue tests
- Document determinism gap on poll_worker_results
- Document bevy_tasks/rayon dep rationale in Cargo.toml

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:22:44 +02:00
jpmschweitzerandClaude Opus 4.6 0ae3542550 style(simulation): cargo fmt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:15:56 +02:00
jpmschweitzerandClaude Opus 4.6 0098ee5a41 feat(simulation): background worker pool infrastructure (#843 Part C)
Generic BackgroundWorkerPool<Req, Resp> with crossbeam channels, closure
handlers, and 3 delivery strategies (Fallback, GracefulDegrade, ModalLock).

Stub workers registered as Bevy resources:
  - ChunkGenWorker (2 threads) — terrain/props/navmesh generation
  - NpcPrepWorker (1 thread) — pre-compute NPC state for incoming areas
  - OffscreenTickWorker (1 thread) — advance NPCs outside active tier

Tick loop integration:
  - PreInput: poll_worker_results drains completed work
  - PostSnapshot: push_worker_requests queues new work (no-op until Phase 5)

Handlers are stubs — real computation plugs in when the phases that need
them arrive. The infrastructure (channels, threads, push/poll, shutdown)
is real and tested.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:15:05 +02:00
jpmschweitzerandClaude Opus 4.6 2175e9b31c feat(simulation): multi-threaded executor + EntityRng (#843 Part B)
Enable Bevy multi-threaded executor via bevy_tasks multi_threaded
feature. Systems within the same TickPhase that don't share mutable
resources now run in parallel automatically.

Add EntityRng component — per-entity ChaCha20Rng seeded from
world_seed + StableId via splitmix64 mixing. More deterministic than
shared SimRng (order-independent). Migrate all monologue systems
(4 of 13 SimRng consumers) to EntityRng, removing contention that
serialized them against conversation/dialogue systems.

Add rayon dependency (infrastructure only, no par_iter calls yet).

SimRng retained for world-level randomness: conversation pairing,
knowledge transfer, dialogue, ticker, storyteller.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:08:41 +02:00
jpmschweitzerandClaude Opus 4.6 309c05d441 style(simulation): cargo fmt + fix clippy doc-nested-refdefs warning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:57:48 +02:00
jpmschweitzerandClaude Opus 4.6 cf21904a0f fix(ui): show system cursor during fullscreen implant apps
CursorRenderer now toggles Input.MOUSE_MODE_VISIBLE when gameplay is
occluded, restores MOUSE_MODE_HIDDEN when gameplay resumes. Without
this, fullscreen apps (star map, future atlas) had no cursor at all —
the custom diegetic cursor hid correctly but the system cursor was
never restored.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:56:56 +02:00
jpmschweitzerandClaude Opus 4.6 b5dff8c55e fix(ui): gameplay_occluded signal never fired on first fullscreen toggle
was_occluded was computed AFTER _active_mode and _active_app were
updated to the new values, so it always matched now_occluded on the
first toggle (both TRUE). The signal condition (was != now) never
triggered. Moved the check before the state mutation.

This bug affected every GameplayRenderer (world, entities, fog,
cursor) and the stance indicator — none of them hid on first
fullscreen app open.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:53:54 +02:00
jpmschweitzerandClaude Opus 4.6 6f02b9f4f4 fix(client): eliminate runtime warnings — radial size deferred, storyteller log removed
- world_radial.gd: use set_deferred("size", ...) to avoid anchor conflict warning
- storyteller: remove noisy "no Simmering triangles" warn (normal state, not exceptional)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:51:17 +02:00
jpmschweitzerandClaude Opus 4.6 47d4918cc8 refactor(simulation): replace ad-hoc system ordering with TickPhase pipeline (#843)
10-phase linear pipeline: PreInput → Input → Movement → Simulation →
Economy → Storyteller → Snapshot → PostSnapshot → Knowledge → TickAdvance.

Each system assigned to exactly one phase via .in_set(TickPhase::X).
Cross-phase .after()/.before() eliminated — only intra-phase ordering
remains. Prevents schedule cycles by construction.

SimulationPlugin refactored into sub-plugins by domain:
  - InputPlugin (player actions, interactions, dialogue dispatch)
  - MovementPlugin (pathfinding, movement validation, spatial indexing)
  - SocialPlugin (conversations, sound, voice enrichment, follow state)
  - EconomyPlugin (tâtonnement tick, IPC query serving)
  - TimePlugin (chunk streaming, news ticker, tick advancement)

All other plugins (NPC, Knowledge, Perception, Storyteller, Settings,
Bridge) updated to use TickPhase assignments instead of cross-plugin
ordering constraints. BridgePlugin trimmed to bridge I/O concerns only.

Part A of #843. Parts B (multi-threaded executor) and C (background
workers) follow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:51:06 +02:00
jpmschweitzerandClaude Opus 4.6 d434235985 chore(meta): add pair session work mode, prune scrapped NPC systems
- CLAUDE.md: add "Pair session" as formal work mode alongside sprint mode
- Scrap NPC ambient systems (R-012): D-078 marked superseded, content
  pattern note scrapped, overheard conversation system will be rebuilt
  from scratch after a walkable environment exists
- Agent profiles: remove NPC-drift references from Paula, Dudley, Miri;
  add cascade discipline to Miri's role

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:01:11 +02:00
jpmschweitzerandClaude Opus 4.6 9edbe40de9 fix(simulation): resolve Bevy schedule cycle — economy system ordering
tick_economy_simulation was ordered .after(advance_tick) which created a
cycle: observer_snapshot → send_snapshot → advance_tick → tick_economy →
observer_snapshot. Moved to .after(process_player_input) instead — the
economy checks time.tick which works regardless of advance order.

Also removed the .after(tick_economy_simulation) from handle_debug_commands
that was added during Sprint 34 review — same cycle root cause.

This is a symptom of #843 (ad-hoc ordering is fragile). Pair session
scheduled to replace with system set phases.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:00:55 +02:00
jpmschweitzerandClaude Opus 4.6 e91bd1c7e4 fix(client): post-sprint polish — protocol v21, schedule workaround, UI fixes
- Bump client protocol version 20 → 21 to match server (#822)
- Fix render_priority parameter name (was _render_priority, unused prefix)
- Fix debug console type inference (var sub := → var sub: String =)
- Economics panel: add population row, improve key hint text
- Stance indicator: hide on gameplay_occluded (D-170 fullscreen apps)
- Remove 5 broken clothing items from manifest and delete their GLBs
  (boots_work, coveralls_basic, jacket_utility, pants_cargo, shirt_henley)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 23:00:40 +02:00
jpmschweitzerandClaude Opus 4.6 2319c6f6ca chore(meta): release v0.1.34
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v0.1.34
2026-04-10 22:21:52 +02:00
jpmschweitzerandClaude Opus 4.6 e0d2ea32a5 fix(decisions): address PR #126 review — cross-refs, index, arithmetic
- Fix D-189 cross-ref: D-131 → content.md (was scope.md), fix anchor slug
- Fix D-191 cross-refs: D-093, D-095, D-138 → content.md (were architecture.md)
- Fix architecture.md footer counter: 52 → 53
- Fix D-190 ratio arithmetic: 1:100 → 1:80, 1:20-50 → 1:16-40
- Merge Destilaria Confluência/Lento into single row, update corp count ~28 → ~27
- Fix platform shorthand → platform_catalogue in D-189 §11
- Add D-189, D-190, D-191 to decisions/README.md index

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 22:06:23 +02:00
jpmschweitzerandClaude Opus 4.6 b69645d35c docs(decisions): D-189 brand layer architecture, D-190 volume calibration, D-191 Atlas Phase 3 scope
Sprint 34 planning workshop output:
- D-189: Brand layer architecture — 8 categories, administered pricing model,
  halo/volume tiers, 10K minor brands, Gemma 2 naming, corp tax/GDP, verb ladder
- D-190: Brand volume calibration — population-relative scale for ~80B Reach
- D-191: Atlas of the Reach Phase 3 — terrain-aware city placement, sequential
  settlement growth, Gemma 2 geographic naming, 9 MVP overlays, heightmap viewer

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 21:04:41 +02:00
jpmschweitzerandClaude Opus 4.6 a9bd3ca408 Merge remote-tracking branch 'origin/sprint-34/client'
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:19:52 +02:00
jpmschweitzerandClaude Opus 4.6 4d4dc2014d fix(ui): rebind economics panel toggle from E to N (#124 review R2)
E is claimed by InputMap "interact" action — InputMapper consumes
it before _unhandled_key_input. N is free, adjacent to M (star map),
reads as "Numbers" for the economics monitor.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 14:25:07 +02:00
jpmschweitzer 08297a9cae Merge remote-tracking branch 'origin/sprint-34/copy' 2026-04-10 14:19:09 +02:00
jpmschweitzerandClaude Opus 4.6 ac6c9dd2cd style(simulation): cargo fmt economy.rs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 14:07:14 +02:00
jpmschweitzerandClaude Opus 4.6 1498115aba fix(simulation): address PR #125 review — tick truncation, ordering, perf, protocol test
- 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>
2026-04-10 14:06:54 +02:00
jpmschweitzerandClaude Opus 4.6 28d95c23a8 fix(ui): address PR #124 review — navigation, error handling, cleanup
- Economics panel: replace dead _gui_input LEFT/RIGHT with public
  navigate() method, wire [ ] keys in main.gd (avoids movement
  key conflict, fixes focus_mode=NONE issue)
- Debug console: add explicit effect guard in econ inject no-commodity
  branch so invalid effects don't fall to commodity-form error
- Snapshot consumer: null-clear GameState.economy_snapshot after
  consuming (matches one-shot consumer invariant)
- Star map: remove duplicate doc comment above set_insert_active()
- Generate script: remove stale comment, dead _WORKTREE_PARENT var,
  dead field extraction in parse_wiki_index, add try/except around
  DB queries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 14:03:49 +02:00
jpmschweitzerandClaude Opus 4.6 f41ab6c8e8 fix(content): address PR #123 round 2 — Founder terminology, names
Fix 3 issues from round 2 review:

- ovh_arc_003: "Gatebuilder" → "Founder structure" (canonical term)
- ovh_ror_002: Subordinate → Colleague (peers, not hierarchy)
- ovh_mfg_001: "Orien" → "Krev" (too close to Earth constellation)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 14:03:41 +02:00
jpmschweitzerandClaude Opus 4.6 f301fdecc7 fix(content): address PR #123 review — registers, names, patterns
Fix 15 issues from Hoshe, Paula, and Miri review:

QA: correct changelog count (78 new, not 94), fix "attach" → "attaché"
in ovh_dip_002.

Narrative: fix register mismatches (ovh_rag_002 Social→Gossip,
ovh_ctx_002 Social→Gossip, ovh_med_003 Gossip→Work), fix inverted
authority dynamic in ovh_hos_002, add progression to ovh_evn_002 third
turn, replace frontier_medic/liaison with ranger/settlement_administrator
in ovh_dis_002, break extraction/industrial template pattern by
rewriting ovh_mfg_001 (social/family) and ovh_epl_001 (social/plans).

World consistency: replace Earth-ethnic names (Kessler-Dunn→Vasara-Lenn,
Kovacs→Tanev, Harlan→Sareth, Henwick→Merata), replace unanchored
location (Old Pemmar→Old Tarassa), replace lore-colliding name
(Calloway→Vedara).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 13:37:47 +02:00
jpmschweitzerandClaude Sonnet 4.6 77232434f4 style(simulation): cargo fmt + fix clippy warnings after economics integration
- `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>
2026-04-10 13:22:47 +02:00
jpmschweitzerandClaude Opus 4.6 532fcd64a5 chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 13:22:47 +02:00
jpmschweitzerandClaude Opus 4.6 f17a6c638c feat(ui): economics debug console commands — inject, param, inspect (#825)
Three new econ subcommands in the debug console: inject (supply
shocks/boosts), param (α/β/friction mutation), inspect (all 7
D-181 signals). Command parsing and validation complete; dispatch
wired through existing DebugCommand IPC flow. Server handler
ships with #823.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 13:22:30 +02:00
jpmschweitzerandClaude Opus 4.6 949d721eac feat(ui): economics monitor insert panel with placeholder data (#824)
New implant panel at implant/economics: system selector, 6-commodity
price table with trend indicators, GDP strip. Composed from D-169
component library. Ring buffer caches last 20 ticks per system.
Snapshot routing wired through snapshot_handler → GameState →
snapshot_consumers → economics_panel. Placeholder prices shown
until server ships EconomySnapshot (#822).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 13:22:20 +02:00
jpmschweitzerandClaude Opus 4.6 766da969de feat(ui): add system population and GDP to star map info panel (#785)
Star map popup now shows POPULATION and GDP rows when data is present.
Generation script updated to compute GDP from population × tier-based
per-capita schedule. 275/301 systems have GDP data (26 uninhabited
correctly omitted).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 13:22:10 +02:00
jpmschweitzerandClaude Sonnet 4.6 5f4139bc9e feat(simulation): implement economics integration sprint — #810 #821 #822 #823
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>
2026-04-10 13:13:52 +02:00
jpmschweitzerandClaude Opus 4.6 38d4664559 chore(meta): update changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 12:54:26 +02:00
jpmschweitzerandClaude Opus 4.6 26a74b2bfb feat(content): author overheard conversations for all 31 zone types (#695)
Expand overheard.ron from 5 zone types (16 conversations) to full
coverage of all 31 zone types with 94 new conversations. Each zone
type has 2-4 role-pair conversations following D-078 occlusion-
resilient authoring rules. Conversations carry investigative
knowledge payloads where appropriate — institutional cover-ups,
manifest discrepancies, suppressed inspections, and cultural signals
players can follow.

Zone types added: administrative_civil, administrative_judicial,
archaeological_site, commercial_market, commercial_transit,
detention_facility, diplomatic_elite, entertainment_venue,
extraction_platform, extraction_space, extraction_surface,
industrial_manufacturing, industrial_processing, medical_facility,
military_garrison, port_fishing, port_maritime, port_space,
port_surface, research_station, residential_surface, rural_aquaculture,
rural_orbital, rural_pastoral, security_checkpoint, wilderness_frontier.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 12:54:12 +02:00
jpmschweitzerandClaude Sonnet 4.6 9d9ea96be1 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>
2026-04-08 16:20:29 +02:00
jpmschweitzerandClaude Opus 4.6 385f07b11e chore(meta): release v0.1.33
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v0.1.33
2026-04-08 14:04:15 +02:00
jpmschweitzer 960adfc60a Merge remote-tracking branch 'origin/sprint-33/server' 2026-04-08 13:58:10 +02:00
jpmschweitzerandClaude Opus 4.6 6003726fbf style(simulation): cargo fmt generate_corporations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:52:29 +02:00
jpmschweitzerandClaude Opus 4.6 d45cfe0fa3 fix(simulation): address PR #122 review — determinism, correctness, labeling
- HashMap → BTreeMap throughout econ-sim for deterministic iteration (D-010)
- Fix cost_factor: multiplicative gate×zone instead of additive (trade.rs)
- Extract derive_seed to shared prng.rs, consolidate FNV-1a implementation
- Rename run_shock_test → run_no_explosion_check (not D-179 Test 3)
- Deduplicate cross-zone FX rate collection in Test 4
- Replace ORDER BY RANDOM() with deterministic ordering + ChaCha8Rng
- Make commodity coverage failure a hard error consistent with D-175
- Fix gap-fill off-by-one (4 corps → 3 when coverage = 0)
- Correct test report: EconEvent exists, location_type is body/station

All four D-179 stability tests still pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:51:23 +02:00