docs(governance): Atlas-viewer batch refinement — D-226/D-191/D-236 amendments + ticket rescopes

Si audit rulings (Jeroen, 2026-07-13): D-226 amended (shipped always-toggleable overlay pattern ratified, gen_l0 dropped, legend stands, no tile-level Atlas map); D-191 + CLAUDE.md Phase-4 wording aligned; D-236 amended (Oort-cloud gateway station = concrete player-access cap; Sol never in deterministic runs). T-960 rescoped (L2 roads + L3 settlements + legend in; L4/climate/L5 out), T-949 scoped non-Sol + D-010 citation fix, T-970 refined (Paused gates only advance_tick; economy split; Option A manual-pause reconciliation). New: T-1112 (L4 coarse-footprint design), T-1113 (climate cascade wiring). D-254 claim unused (D-236 already covered Sol).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 23:53:59 +02:00
co-authored by Claude Fable 5
parent 81e4cb25d0
commit 672a583e64
6 changed files with 175 additions and 2 deletions
+89
View File
@@ -1182,3 +1182,92 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FN2TXSWVJGQWV6Q2RF5EF35W', 'status', 'review', 'done', NULL, '2026-07-13 20:52:24', '2026-07-13 20:52:24.193', '2026-07-13 20:52:24.193', NULL, 'a22fb2d151630b93cece5577c18bb13e', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FN2TX5V43575PG96F14AH0N0', 'status', 'review', 'done', NULL, '2026-07-13 20:52:24', '2026-07-13 20:52:24.193', '2026-07-13 20:52:24.193', NULL, 'b62d57f8d12b7a1748ecf05b506e60dd', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FN2TV9HWGK5P7MJ9REHFKVFC', 'status', 'backlog', 'done', NULL, '2026-07-13 20:52:30', '2026-07-13 20:52:30.115', '2026-07-13 20:52:30.115', NULL, 'f4a4c68f4063a550a6ca58cf7a0e660a', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRZ8BFVNWDH17CMH1YM', 'description', 'Render each cascade layer as a MAP in the implant Atlas (D-191, the Phase 3 viewer — D-166 amendment): terrain → water → biome → settlements → political zones → quarter/block skeleton → tiles. This is the progress-viewer deliverable; NO in-world rendering. Grows as each layer lands.
---
Refinement (2026-05-23, /whats-next):
- DATA TRANSPORT (resolves Q-098): NO bake baking derived layer data makes mods second-class. A server-side FILE STREAM PROXY: resolves a body source files across base + mod paths, runs the deterministic cascade on demand (run_cascade, LRU-cached per D-203, ~45ms), and streams serialized layer data to the Godot client over IPC. First-party and mod bodies use the identical path; no pre-baked derived artifacts. Protocol/stream spec designed with Tyre and recorded in a D-record resolving Q-098.
- UI: layer selector in the existing regional Atlas view; layers are ADDITIVE overlays (toggle heightmap + rivers + attractors + sub-biome together and composite), not one-at-a-time matching the existing overlay-bar model (D-191).
- SCOPE NOW: only Layer 0 (heightmap) + Layer 1 (rivers/basins/attractors/sub-biome) exist; the viewer grows as layers land (D-166). Acceptance: Layer 0 + Layer 1 render as additive, toggleable overlays for a body, fed by the proxy.
---
Design (D-226, Araminta, 2026-05-24) human-visual layer of the inspection harness. Extend OVERLAY_DEFS / AtlasOverlayBar with a generation overlay group (second row) + a left-side legend panel; do NOT build a separate viewer. Encoding: relief base; rivers as blue polylines (mouths = double-circle markers, confluences where in-degree >= 3); basin fills very translucent + thin boundary polylines; attractors as markers where SHAPE encodes the 7 AttractorTypes (circle/half-circle/diamond/down-tri/up-tri/hollow-circle/square) and COLOR encodes sub-biome (shape carries identity in headless/monochrome; color is additive); size scales with strength, skip strength < 0.15. Stable button ids gen_l0_heightmap / gen_l1_rivers / gen_l1_basins / gen_l1_attractors; start pending/locked, unlock+activate via notify_gen_layer_ready(id) as data arrives (grows as layers land, D-166). Consumes the live proxy (#969); the agent channel (#971) drives this same UI.
Remaining to close (Si sweep 2026-06-07): add the gen_l0_heightmap overlay to OVERLAY_DEFS + render path in atlas_viewer.gd / atlas_marker_overlay.gd required by the D-226/T-960 acceptance criteria but currently absent. Layer-1 overlays (rivers/basins/attractors) + proxy wire + pending indicator are already implemented; this Layer-0 overlay is the sole remaining piece.', 'Render each cascade layer as a MAP in the implant Atlas (D-191, the Phase 3 viewer D-166 amendment): terrain water biome settlements political zones quarter/block skeleton tiles. This is the progress-viewer deliverable; NO in-world rendering. Grows as each layer lands.
---
Refinement (2026-05-23, /whats-next):
- DATA TRANSPORT (resolves Q-098): NO bake baking derived layer data makes mods second-class. A server-side FILE STREAM PROXY: resolves a body source files across base + mod paths, runs the deterministic cascade on demand (run_cascade, LRU-cached per D-203, ~45ms), and streams serialized layer data to the Godot client over IPC. First-party and mod bodies use the identical path; no pre-baked derived artifacts. Protocol/stream spec designed with Tyre and recorded in a D-record resolving Q-098.
- UI: layer selector in the existing regional Atlas view; layers are ADDITIVE overlays (toggle heightmap + rivers + attractors + sub-biome together and composite), not one-at-a-time matching the existing overlay-bar model (D-191).
- SCOPE NOW: only Layer 0 (heightmap) + Layer 1 (rivers/basins/attractors/sub-biome) exist; the viewer grows as layers land (D-166). Acceptance: Layer 0 + Layer 1 render as additive, toggleable overlays for a body, fed by the proxy.
---
Design (D-226, Araminta, 2026-05-24) human-visual layer of the inspection harness. Extend OVERLAY_DEFS / AtlasOverlayBar with a generation overlay group (second row) + a left-side legend panel; do NOT build a separate viewer. Encoding: relief base; rivers as blue polylines (mouths = double-circle markers, confluences where in-degree >= 3); basin fills very translucent + thin boundary polylines; attractors as markers where SHAPE encodes the 7 AttractorTypes (circle/half-circle/diamond/down-tri/up-tri/hollow-circle/square) and COLOR encodes sub-biome (shape carries identity in headless/monochrome; color is additive); size scales with strength, skip strength < 0.15. Stable button ids gen_l0_heightmap / gen_l1_rivers / gen_l1_basins / gen_l1_attractors; start pending/locked, unlock+activate via notify_gen_layer_ready(id) as data arrives (grows as layers land, D-166). Consumes the live proxy (#969); the agent channel (#971) drives this same UI.
Remaining to close (Si sweep 2026-06-07): add the gen_l0_heightmap overlay to OVERLAY_DEFS + render path in atlas_viewer.gd / atlas_marker_overlay.gd required by the D-226/T-960 acceptance criteria but currently absent. Layer-1 overlays (rivers/basins/attractors) + proxy wire + pending indicator are already implemented; this Layer-0 overlay is the sole remaining piece.
---
Refinement (2026-07-13, /whats-next Si audit + Jeroen rulings) RESCOPE. The 2026-06-07 scope note is obsolete in both directions:
DONE ALREADY (record, don''t rebuild):
- L1 overlays (gen_l1_rivers/basins/attractors) + proxy wire + pending indicator: shipped.
- District-morphology overlay (gen_district "MRPH"): shipped under T-1046 via AtlasLayerResponse.district_grid the wiring precedent for everything below.
- gen_l0_heightmap: DROPPED relief already renders via the always-on terrain overlay (D-191 §7). D-226 amended (2026-07-13) accordingly.
IN SCOPE NOW (this ticket):
1. gen_l2_roads overlay L2 road/rail graph (T-1038) is computed on every AnalyzeBody (gen_queue.rs runs up_to=RoadGraph) but never serialized: add RoadGraphLayer field to AtlasLayerResponse (layer_proxy.rs), protocol.gd decode, overlay rendering (edges colored by MaintenanceAuthority, junction markers).
2. gen_l3_settlements overlay wire T-955''s computed CityPlacement positions through the proxy (new SettlementLayer field, exact T-1046 precedent) so cities render on generated bodies for the first time (Jeroen ruling: wire positions now; T-949 stays boundary-cleanup).
3. Left-side legend panel D-226 item (3) deliverable, never built (shape/color key for attractor types + sub-biomes + the new overlays).
4. Doc-comment fix: layer_proxy.rs:31-34 claims cascade runs "through CascadeLayer::Settlement" actually RoadGraph (gen_queue.rs:416); client''s up_to field is ignored by the server. One-line correction.
OUT OF SCOPE (explicitly, per 2026-07-13 rulings):
- L4 quarter footprints design ticket T-1112 (needs coarse-shape design first).
- Region climate prerequisite wiring ticket T-1113 (not in cascade at all yet).
- L5 chunk/tile fill NEVER an Atlas map layer (D-191/D-226 amendments 2026-07-13; harness-verified, Phase-5 in-world).
- markers.json migration / Sol T-949 / T-1073 (D-236: Sol excluded from deterministic runs, access capped at Oort gateway).
Overlay mechanism: follow the shipped always-toggleable pattern (D-226 as amended), NOT the old lock/notify spec.', NULL, '2026-07-13 21:53:23', '2026-07-13 21:53:23.042', '2026-07-13 21:53:23.042', NULL, '3ae0281c74dafba38b3d19b4787b0a84', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRW2ZSPJ3D9NEZ6JBW8', 'description', 'The client currently reads markers.json and star_map_data.json directly from the filesystem. This bypasses the server layer entirely — the client should request all game data through IPC calls to the Rust backend.
Implementation can be simple: the server exposes a query/proxy endpoint that reads the JSON file or runs a DB query and returns the result. The client asks, the server responds. No complex protocol needed just the boundary enforcement that the client never reads files or DB directly.
Affects: atlas app (reach, system, planet, regional screens), economics monitor. The server-side handler can start as a thin proxy (read file, return contents) and evolve into perception-filtered queries (D-012) later.
Re-parented under Phase 4 epic per cascade refocus 2026-06-12 atlas data delivery underpins viewing cascade layers through the implant Atlas.', 'The client currently reads markers.json and star_map_data.json directly from the filesystem. This bypasses the server layer entirely the client should request all game data through IPC calls to the Rust backend.
Implementation can be simple: the server exposes a query/proxy endpoint that reads the JSON file or runs a DB query and returns the result. The client asks, the server responds. No complex protocol needed just the boundary enforcement that the client never reads files or DB directly.
Affects: atlas app (reach, system, planet, regional screens), economics monitor. The server-side handler can start as a thin proxy (read file, return contents) and evolve into perception-filtered queries (D-012) later.
Re-parented under Phase 4 epic per cascade refocus 2026-06-12 atlas data delivery underpins viewing cascade layers through the implant Atlas.
---
Refinement (2026-07-13, /whats-next Si audit + Jeroen rulings):
SCOPE: the ~2,398 generated (non-Sol) bodies + star_map_data.json only.
- SOL EXCLUDED (Jeroen): Sol stays out of all deterministic runs; player access is lore-capped at the Oort-cloud gateway station see D-236 as amended 2026-07-13. Sol''s client-side legacy markers.json read (atlas_viewer.gd::_load_markers) STAYS as the documented D-223/D-236 exception until T-1073 (gated on Q-107). Do not repeat T-1073''s implementbreakrevert cycle.
- CITATION FIX: the description''s "perception-filtered queries (D-012)" should read D-010 (information boundaries). D-012 is chunk-based map architecture unrelated.
CURRENT READ INVENTORY (verified 2026-07-13):
1. atlas_viewer.gd::_load_markers (~436-467) markers.json via FileAccess. For non-Sol bodies this is names-only data (D-223); replace with a names request over the bridge (server already reads atlas_city_names via CityContextReader). Positions come from T-960''s SettlementLayer work (separate ticket, same branch).
2. system_index.gd::get_sorted_systems star_map_data.json, consumed by atlas_app.gd:150 (Reach screen) + overview_screen.gd:114 (economics monitor selector; its only direct read). star_map_data.json is a build-time bake (tooling/generate-star-map-data.py); the server has NO existing reader a thin proxy (server reads the same JSON, returns it) is acceptable per the ticket.
3. OUT OF SCOPE (deliberate, D-225): reliefmap.png / wiki globe image loads stay client-side.
PROTOCOL PATTERN: structural disambiguation on the existing IPC stream (Inbound enum: Inputs vs AtlasRequest). Reach-level star-map data is not per-body/cascade-shaped add NEW request/response types (e.g. StarMapRequest StarMapResponse), do not shoehorn into AtlasLayerResponse. Per-body names ride the atlas path.', NULL, '2026-07-13 21:53:24', '2026-07-13 21:53:24.830', '2026-07-13 21:53:24.830', NULL, 'ecef2b6cccdc0ad213d3ac4f86a7d0ad', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRYEJ0G4F0SBHG379YR', 'description', 'D-226 layer 1 (substrate). Auto-pause the sim when the client enters a fullscreen implant app (the Atlas). Freeze the world-advancing tick phases (Movement/Simulation/Economy/Storyteller/Knowledge/TickAdvance) via run-conditions keyed to a pause command, but KEEP PreInput (gen-drain), Input (receive resume), Snapshot, PostSnapshot (bridge) alive so the UI keeps fetching data while frozen. Reuse the existing TickRate::Paused + the input.rs paused-allowlist seam; trigger from HudGroups::gameplay_occluded (D-170) -> a pause/resume command over the bridge. For static geography pause is a compute-saver; for dynamic state (economics, later) it is essential. Confirm exactly what TickRate::Paused currently gates (whole loop vs sim-advance) and gate at the phase level.', 'D-226 layer 1 (substrate). Auto-pause the sim when the client enters a fullscreen implant app (the Atlas). Freeze the world-advancing tick phases (Movement/Simulation/Economy/Storyteller/Knowledge/TickAdvance) via run-conditions keyed to a pause command, but KEEP PreInput (gen-drain), Input (receive resume), Snapshot, PostSnapshot (bridge) alive so the UI keeps fetching data while frozen. Reuse the existing TickRate::Paused + the input.rs paused-allowlist seam; trigger from HudGroups::gameplay_occluded (D-170) -> a pause/resume command over the bridge. For static geography pause is a compute-saver; for dynamic state (economics, later) it is essential. Confirm exactly what TickRate::Paused currently gates (whole loop vs sim-advance) and gate at the phase level.
---
Refinement (2026-07-13, /whats-next Si audit + lead ruling):
CONFIRMED (the ticket''s own open question): TickRate::Paused today gates ONLY the clock advance_tick (simulation/time.rs:100-110, in TickPhase::TickAdvance) no-ops when Paused. There are ZERO run_if/run-conditions anywhere in the server schedule; tick_phases.rs::configure() only chains ordering. input.rs''s paused-allowlist (input.rs:128,134-155) is an in-system dispatch filter, not a phase gate. So "gate at the phase level" is new plumbing: add .run_if(not paused) to the SystemSet configs for Movement/Simulation/Storyteller/Knowledge/TickAdvance in tick_phases.rs::configure().
ECONOMY SPLIT (must not miss): serve_econ_state_query which services the paused-ALLOWED EconStateQuery is registered in the same TickPhase::Economy set, .after(tick_economy_simulation) (economy_plugin.rs:27-35). A blanket set-level gate on Economy would break that paused guarantee. Gate tick_economy_simulation individually; leave serve_econ_state_query unconditioned (.after() ordering holds when the upstream system is skipped). All other allowlist entries verified to land on keep-alive phases.
BRIDGE: no new protocol needed PlayerAction::Pause/Unpause work end-to-end (D-088 manual pause; input_mapper.gd:137-139 sim_bridge.gd action_enum_to_wire:528-531 receive_bridge_inputs process_player_input). The ONLY missing piece is client wiring: connect HudGroups.gameplay_occluded (hud_groups.gd:33,63-88) to sending Pause/Unpause via sim_bridge.gd''s outbound queue. Today only implant/map (Atlas, default_mode=fullscreen) triggers occlusion.
GEN-DRAIN: confirmed still correct post-T-1046 GenerationPlugin registers drain_generation_completions + serve_atlas_requests in TickPhase::PreInput (atlas/plugin.rs:52-62); cascade compute is on an independent Rayon pool, so generation keeps flowing while paused. PreInput/Input/Snapshot/PostSnapshot stay alive per the ticket.
MANUAL-vs-AUTO PAUSE (the one gap lead ruling: Option A): track WHETHER THE AUTO-PAUSE CAUSED the pause (a flag distinct from TickRate itself, e.g. auto_pause_active). Auto-resume on implant-close fires Unpause ONLY if auto-pause was the trigger a prior manual pause (or D-088 Half rate) survives implant close untouched. No previous-rate stack (that''s Option C, deferred).', NULL, '2026-07-13 21:53:25', '2026-07-13 21:53:25.085', '2026-07-13 21:53:25.085', NULL, 'b9d4170174c71d85a36bd62c8be00c73', 2) ON CONFLICT(hash) DO NOTHING;
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBRCMEKT72S0Q6NE68JH7EXC', 'description', 'Split from T-1071 (2026-06-12): converting the 4 legacy geometry-bearing GJ-0 markers.json (GJ0d, GJ0d-1, GJ0e, GJ0f-2) to the D-223 names-only schema is SAFE for generation (import_economics.py:1452 skips GJ 0 explicitly; all authored coordinates/populations verified present name-by-name in tooling/planet-gen/sol_markers/*.json + sol_name_fixes.py FIXES) but REGRESSES the client: atlas_viewer.gd:433 still loads markers.json per the legacy D-191 §8 geometry schema, so Sol bodies lose their city/river/mountain Atlas overlays. The conversion was implemented, verified, and then deliberately reverted to preserve working overlays. Land both halves together: (1) point the Sol overlay read at the proper Sol home (sol_markers/ or a baked path — Q-107 consolidation may decide this), (2) convert the 4 files, (3) also fix the residual debt: sol_import.py still WRITES legacy-schema markers and an unconditional heightmap link in its own _write_index_md, and import_economics.py:1485 carries a now-misleading comment about preserved geometry markers (editing it stales the systems.db stamp — bundle with a regen).', 'Split from T-1071 (2026-06-12): converting the 4 legacy geometry-bearing GJ-0 markers.json (GJ0d, GJ0d-1, GJ0e, GJ0f-2) to the D-223 names-only schema is SAFE for generation (import_economics.py:1452 skips GJ 0 explicitly; all authored coordinates/populations verified present name-by-name in tooling/planet-gen/sol_markers/*.json + sol_name_fixes.py FIXES) but REGRESSES the client: atlas_viewer.gd:433 still loads markers.json per the legacy D-191 §8 geometry schema, so Sol bodies lose their city/river/mountain Atlas overlays. The conversion was implemented, verified, and then deliberately reverted to preserve working overlays. Land both halves together: (1) point the Sol overlay read at the proper Sol home (sol_markers/ or a baked path — Q-107 consolidation may decide this), (2) convert the 4 files, (3) also fix the residual debt: sol_import.py still WRITES legacy-schema markers and an unconditional heightmap link in its own _write_index_md, and import_economics.py:1485 carries a now-misleading comment about preserved geometry markers (editing it stales the systems.db stamp — bundle with a regen).
D-236 amended 2026-07-13: player access lore-capped at the Oort-cloud gateway station; Sol permanently excluded from deterministic runs. T-949 (2026-07-13 scoping) explicitly excludes Sol and leaves the legacy markers read in place for this ticket to migrate once Q-107 resolves Sol''s geometry needs a server-side AUTHORED home, never a cascade path.', NULL, '2026-07-13 21:53:26', '2026-07-13 21:53:26.940', '2026-07-13 21:53:26.940', NULL, '814a6aa15196b19ecc10be00c2b28c60', 2) ON CONFLICT(hash) DO NOTHING;
+2
View File
@@ -25,3 +25,5 @@ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNR3FN8D0GVXPSPV9SY7PEY0', 'T-1109', '2026-07-13 15:17:26.468', '2026-07-13 15:17:26.468', NULL, '2d265d9022b5c1b1d6329157aeea1373', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNR3GM4RPPCJFH8VS3CDN6SG', 'T-1110', '2026-07-13 15:17:34.374', '2026-07-13 15:17:34.374', NULL, '73ce46866d1175b33d0e484f19ace774', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNR3GYTN814QG6WWYNJH7QAR', 'T-1111', '2026-07-13 15:17:37.109', '2026-07-13 15:17:37.109', NULL, 'f15dfa7968abd2a39e12cbd319f8c716', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNTXEM9NM5M5SX9WQAAA40SC', 'T-1112', '2026-07-13 21:50:30.995', '2026-07-13 21:50:30.995', NULL, '10e2ac50b65fb7feb93b6da87fae19d1', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNTXF0JB8E6PDQRASQ18E9ER', 'T-1113', '2026-07-13 21:50:34.135', '2026-07-13 21:50:34.135', NULL, 'be82a59d9e38c465f41936e6ecb7e791', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
+74
View File
@@ -1228,3 +1228,77 @@ INSERT INTO tickets (record_id, type, parent_record_id, title, description, stat
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FN2TX5V43575PG96F14AH0N0', 'epic', '06FN2TV9HWGK5P7MJ9REHFKVFC', 'Workflow-skill correctness (CLAUDE-CLEANUP §3-7)', '§3 whats-next pql-durability + --status footgun ports; §4 git-commit stale attribution trailer; §5 workshop-start (Task→Agent, write-req, SI role); §6 pr-review (sprint narrative, main-path guard, Write grant); §7 pr-process (dead /pr-push refs, orphan-check regex, stale watch-list, bash hygiene).', 'done', 'high', NULL, 'server', NULL, '2026-07-11 13:43:57.145', '2026-07-13 20:52:24.193', NULL, '6ab665eeecfcd3e883e269eb8fea5295', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FN2TXFEDCYPSARF3DYRN9VAG', 'epic', '06FN2TV9HWGK5P7MJ9REHFKVFC', 'Asset & tooling-skill accuracy (CLAUDE-CLEANUP §8-14)', '§8 atlas (removed populate, body-ID naming); §9 glb-gen; §10 image-gen (indent crash both copies — real bug); §11 audio-gen; §12 sprite-gen; §13 bug-report; §14 ticket. Doc accuracy + a few genuine script bugs.', 'done', 'medium', NULL, 'server', NULL, '2026-07-11 13:43:59.603', '2026-07-13 20:52:24.193', NULL, '7632ec25c23fd0117a631739ce8e09fd', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FN2TV9HWGK5P7MJ9REHFKVFC', 'initiative', '06FBPPMZNNEV052DBYYY3A897C', 'Claude estate cleanup — 2026-07-02 .claude review', 'Execution of CLAUDE-CLEANUP.md (repo-root brief, adversarially verified 2026-07-02): ~60 findings across settings, skills, tooling scripts, and the agent roster. Each finding re-verified against the current tree before edit (repo moved since 2026-07-02). Security item (GEMINI_API_KEY) done first — key invalidated by user + replaced with KEY_GOES_HERE placeholder in the untracked settings.local.json. Shipped on branch claude-estate-cleanup via /pr-process.', 'done', 'medium', NULL, 'server', NULL, '2026-07-11 13:43:41.711', '2026-07-13 20:52:30.115', NULL, '73d885d748f00c844c1318a2f7bff504', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNTXEM9NM5M5SX9WQAAA40SC', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Design: coarse quarter-footprint Atlas layer (L4 skeleton on the planetary map)', 'Si audit of T-960 (2026-07-13): L4 quarter/block skeletons (T-957/T-976) auto-generate server-side into BodyWorldState.quarters, but carry full per-block zoning/street/tag detail — too fine for a planetary map, and unlike the district grid there is no existing coarse shape to reuse. DESIGN ticket (Araminta encoding + Tyre data shape) before any wiring: define a QuarterFootprintLayer (city outline + aggregate stats?) for AtlasLayerResponse and its overlay encoding per the D-226 amended (2026-07-13) overlay pattern. Wiring is a follow-up once the design is recorded.', 'backlog', 'medium', NULL, 'client', 'D-226', '2026-07-13 21:50:30.989', '2026-07-13 21:50:30.989', NULL, '99f810ab70d0f9d81eea341aadba9729', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FNTXF0JB8E6PDQRASQ18E9ER', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Wire region climate stack into the cascade (CascadeLayer::Region + proxy exposure)', 'Si audit of T-960 (2026-07-13): region_profile.rs (T-1078 — RegionProfile, derive_regions_for_body, region_baseline_at_district) is implemented and unit-tested but never called from cascade.rs: no CascadeLayer::Region variant, nothing on BodyWorldState, nothing in the layer proxy. Prerequisite for any climate Atlas overlay (explicitly out of T-960 scope per 2026-07-13 ruling): add the cascade layer, populate BodyWorldState, expose via AtlasLayerResponse following the T-1046 district-grid precedent. The climate OVERLAY itself is a small follow-up once this serves data.', 'backlog', 'medium', NULL, 'server', 'D-243', '2026-07-13 21:50:34.130', '2026-07-13 21:50:34.130', NULL, 'a4acf7e00688756a60312d3c6ef4f4e3', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRZ8BFVNWDH17CMH1YM', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Per-layer Atlas map viewer (generation progress viewer)', 'Render each cascade layer as a MAP in the implant Atlas (D-191, the Phase 3 viewer — D-166 amendment): terrain → water → biome → settlements → political zones → quarter/block skeleton → tiles. This is the progress-viewer deliverable; NO in-world rendering. Grows as each layer lands.
---
Refinement (2026-05-23, /whats-next):
- DATA TRANSPORT (resolves Q-098): NO bake baking derived layer data makes mods second-class. A server-side FILE STREAM PROXY: resolves a body source files across base + mod paths, runs the deterministic cascade on demand (run_cascade, LRU-cached per D-203, ~45ms), and streams serialized layer data to the Godot client over IPC. First-party and mod bodies use the identical path; no pre-baked derived artifacts. Protocol/stream spec designed with Tyre and recorded in a D-record resolving Q-098.
- UI: layer selector in the existing regional Atlas view; layers are ADDITIVE overlays (toggle heightmap + rivers + attractors + sub-biome together and composite), not one-at-a-time matching the existing overlay-bar model (D-191).
- SCOPE NOW: only Layer 0 (heightmap) + Layer 1 (rivers/basins/attractors/sub-biome) exist; the viewer grows as layers land (D-166). Acceptance: Layer 0 + Layer 1 render as additive, toggleable overlays for a body, fed by the proxy.
---
Design (D-226, Araminta, 2026-05-24) human-visual layer of the inspection harness. Extend OVERLAY_DEFS / AtlasOverlayBar with a generation overlay group (second row) + a left-side legend panel; do NOT build a separate viewer. Encoding: relief base; rivers as blue polylines (mouths = double-circle markers, confluences where in-degree >= 3); basin fills very translucent + thin boundary polylines; attractors as markers where SHAPE encodes the 7 AttractorTypes (circle/half-circle/diamond/down-tri/up-tri/hollow-circle/square) and COLOR encodes sub-biome (shape carries identity in headless/monochrome; color is additive); size scales with strength, skip strength < 0.15. Stable button ids gen_l0_heightmap / gen_l1_rivers / gen_l1_basins / gen_l1_attractors; start pending/locked, unlock+activate via notify_gen_layer_ready(id) as data arrives (grows as layers land, D-166). Consumes the live proxy (#969); the agent channel (#971) drives this same UI.
Remaining to close (Si sweep 2026-06-07): add the gen_l0_heightmap overlay to OVERLAY_DEFS + render path in atlas_viewer.gd / atlas_marker_overlay.gd required by the D-226/T-960 acceptance criteria but currently absent. Layer-1 overlays (rivers/basins/attractors) + proxy wire + pending indicator are already implemented; this Layer-0 overlay is the sole remaining piece.
---
Refinement (2026-07-13, /whats-next Si audit + Jeroen rulings) RESCOPE. The 2026-06-07 scope note is obsolete in both directions:
DONE ALREADY (record, don''t rebuild):
- L1 overlays (gen_l1_rivers/basins/attractors) + proxy wire + pending indicator: shipped.
- District-morphology overlay (gen_district "MRPH"): shipped under T-1046 via AtlasLayerResponse.district_grid the wiring precedent for everything below.
- gen_l0_heightmap: DROPPED relief already renders via the always-on terrain overlay (D-191 §7). D-226 amended (2026-07-13) accordingly.
IN SCOPE NOW (this ticket):
1. gen_l2_roads overlay L2 road/rail graph (T-1038) is computed on every AnalyzeBody (gen_queue.rs runs up_to=RoadGraph) but never serialized: add RoadGraphLayer field to AtlasLayerResponse (layer_proxy.rs), protocol.gd decode, overlay rendering (edges colored by MaintenanceAuthority, junction markers).
2. gen_l3_settlements overlay wire T-955''s computed CityPlacement positions through the proxy (new SettlementLayer field, exact T-1046 precedent) so cities render on generated bodies for the first time (Jeroen ruling: wire positions now; T-949 stays boundary-cleanup).
3. Left-side legend panel D-226 item (3) deliverable, never built (shape/color key for attractor types + sub-biomes + the new overlays).
4. Doc-comment fix: layer_proxy.rs:31-34 claims cascade runs "through CascadeLayer::Settlement" actually RoadGraph (gen_queue.rs:416); client''s up_to field is ignored by the server. One-line correction.
OUT OF SCOPE (explicitly, per 2026-07-13 rulings):
- L4 quarter footprints design ticket T-1112 (needs coarse-shape design first).
- Region climate prerequisite wiring ticket T-1113 (not in cascade at all yet).
- L5 chunk/tile fill NEVER an Atlas map layer (D-191/D-226 amendments 2026-07-13; harness-verified, Phase-5 in-world).
- markers.json migration / Sol T-949 / T-1073 (D-236: Sol excluded from deterministic runs, access capped at Oort gateway).
Overlay mechanism: follow the shipped always-toggleable pattern (D-226 as amended), NOT the old lock/notify spec.', 'backlog', 'high', NULL, 'client', 'D-191', '2026-05-22 17:42:34', '2026-07-13 21:53:23.042', NULL, 'c18ab622ab35c728633f8b1126ee8fa1', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRW2ZSPJ3D9NEZ6JBW8', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Atlas data delivery — replace client-side file reads with server API calls', 'The client currently reads markers.json and star_map_data.json directly from the filesystem. This bypasses the server layer entirely — the client should request all game data through IPC calls to the Rust backend.
Implementation can be simple: the server exposes a query/proxy endpoint that reads the JSON file or runs a DB query and returns the result. The client asks, the server responds. No complex protocol needed just the boundary enforcement that the client never reads files or DB directly.
Affects: atlas app (reach, system, planet, regional screens), economics monitor. The server-side handler can start as a thin proxy (read file, return contents) and evolve into perception-filtered queries (D-012) later.
Re-parented under Phase 4 epic per cascade refocus 2026-06-12 atlas data delivery underpins viewing cascade layers through the implant Atlas.
---
Refinement (2026-07-13, /whats-next Si audit + Jeroen rulings):
SCOPE: the ~2,398 generated (non-Sol) bodies + star_map_data.json only.
- SOL EXCLUDED (Jeroen): Sol stays out of all deterministic runs; player access is lore-capped at the Oort-cloud gateway station see D-236 as amended 2026-07-13. Sol''s client-side legacy markers.json read (atlas_viewer.gd::_load_markers) STAYS as the documented D-223/D-236 exception until T-1073 (gated on Q-107). Do not repeat T-1073''s implementbreakrevert cycle.
- CITATION FIX: the description''s "perception-filtered queries (D-012)" should read D-010 (information boundaries). D-012 is chunk-based map architecture unrelated.
CURRENT READ INVENTORY (verified 2026-07-13):
1. atlas_viewer.gd::_load_markers (~436-467) markers.json via FileAccess. For non-Sol bodies this is names-only data (D-223); replace with a names request over the bridge (server already reads atlas_city_names via CityContextReader). Positions come from T-960''s SettlementLayer work (separate ticket, same branch).
2. system_index.gd::get_sorted_systems star_map_data.json, consumed by atlas_app.gd:150 (Reach screen) + overview_screen.gd:114 (economics monitor selector; its only direct read). star_map_data.json is a build-time bake (tooling/generate-star-map-data.py); the server has NO existing reader a thin proxy (server reads the same JSON, returns it) is acceptable per the ticket.
3. OUT OF SCOPE (deliberate, D-225): reliefmap.png / wiki globe image loads stay client-side.
PROTOCOL PATTERN: structural disambiguation on the existing IPC stream (Inbound enum: Inputs vs AtlasRequest). Reach-level star-map data is not per-body/cascade-shaped add NEW request/response types (e.g. StarMapRequest StarMapResponse), do not shoehorn into AtlasLayerResponse. Per-body names ride the atlas path.', 'backlog', 'medium', NULL, 'client', NULL, '2026-05-03 14:14:23', '2026-07-13 21:53:24.830', NULL, 'f892a5bfa7ef8f48a0a94defb9745ef5', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRYEJ0G4F0SBHG379YR', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Auto-pause sim on implant-fullscreen (inspection substrate)', 'D-226 layer 1 (substrate). Auto-pause the sim when the client enters a fullscreen implant app (the Atlas). Freeze the world-advancing tick phases (Movement/Simulation/Economy/Storyteller/Knowledge/TickAdvance) via run-conditions keyed to a pause command, but KEEP PreInput (gen-drain), Input (receive resume), Snapshot, PostSnapshot (bridge) alive so the UI keeps fetching data while frozen. Reuse the existing TickRate::Paused + the input.rs paused-allowlist seam; trigger from HudGroups::gameplay_occluded (D-170) -> a pause/resume command over the bridge. For static geography pause is a compute-saver; for dynamic state (economics, later) it is essential. Confirm exactly what TickRate::Paused currently gates (whole loop vs sim-advance) and gate at the phase level.
---
Refinement (2026-07-13, /whats-next Si audit + lead ruling):
CONFIRMED (the ticket''s own open question): TickRate::Paused today gates ONLY the clock advance_tick (simulation/time.rs:100-110, in TickPhase::TickAdvance) no-ops when Paused. There are ZERO run_if/run-conditions anywhere in the server schedule; tick_phases.rs::configure() only chains ordering. input.rs''s paused-allowlist (input.rs:128,134-155) is an in-system dispatch filter, not a phase gate. So "gate at the phase level" is new plumbing: add .run_if(not paused) to the SystemSet configs for Movement/Simulation/Storyteller/Knowledge/TickAdvance in tick_phases.rs::configure().
ECONOMY SPLIT (must not miss): serve_econ_state_query which services the paused-ALLOWED EconStateQuery is registered in the same TickPhase::Economy set, .after(tick_economy_simulation) (economy_plugin.rs:27-35). A blanket set-level gate on Economy would break that paused guarantee. Gate tick_economy_simulation individually; leave serve_econ_state_query unconditioned (.after() ordering holds when the upstream system is skipped). All other allowlist entries verified to land on keep-alive phases.
BRIDGE: no new protocol needed PlayerAction::Pause/Unpause work end-to-end (D-088 manual pause; input_mapper.gd:137-139 sim_bridge.gd action_enum_to_wire:528-531 receive_bridge_inputs process_player_input). The ONLY missing piece is client wiring: connect HudGroups.gameplay_occluded (hud_groups.gd:33,63-88) to sending Pause/Unpause via sim_bridge.gd''s outbound queue. Today only implant/map (Atlas, default_mode=fullscreen) triggers occlusion.
GEN-DRAIN: confirmed still correct post-T-1046 GenerationPlugin registers drain_generation_completions + serve_atlas_requests in TickPhase::PreInput (atlas/plugin.rs:52-62); cascade compute is on an independent Rayon pool, so generation keeps flowing while paused. PreInput/Input/Snapshot/PostSnapshot stay alive per the ticket.
MANUAL-vs-AUTO PAUSE (the one gap lead ruling: Option A): track WHETHER THE AUTO-PAUSE CAUSED the pause (a flag distinct from TickRate itself, e.g. auto_pause_active). Auto-resume on implant-close fires Unpause ONLY if auto-pause was the trigger a prior manual pause (or D-088 Half rate) survives implant close untouched. No previous-rate stack (that''s Option C, deferred).', 'backlog', 'high', NULL, 'server', 'D-226', '2026-05-24 09:22:33', '2026-07-13 21:53:25.085', NULL, '5fe338d15b93a3392aa9d300932eaef8', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBRCMEKT72S0Q6NE68JH7EXC', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Sol markers → D-223 names-only, migrated together with the Atlas legacy-geometry read path', 'Split from T-1071 (2026-06-12): converting the 4 legacy geometry-bearing GJ-0 markers.json (GJ0d, GJ0d-1, GJ0e, GJ0f-2) to the D-223 names-only schema is SAFE for generation (import_economics.py:1452 skips GJ 0 explicitly; all authored coordinates/populations verified present name-by-name in tooling/planet-gen/sol_markers/*.json + sol_name_fixes.py FIXES) but REGRESSES the client: atlas_viewer.gd:433 still loads markers.json per the legacy D-191 §8 geometry schema, so Sol bodies lose their city/river/mountain Atlas overlays. The conversion was implemented, verified, and then deliberately reverted to preserve working overlays. Land both halves together: (1) point the Sol overlay read at the proper Sol home (sol_markers/ or a baked path — Q-107 consolidation may decide this), (2) convert the 4 files, (3) also fix the residual debt: sol_import.py still WRITES legacy-schema markers and an unconditional heightmap link in its own _write_index_md, and import_economics.py:1485 carries a now-misleading comment about preserved geometry markers (editing it stales the systems.db stamp — bundle with a regen).
D-236 amended 2026-07-13: player access lore-capped at the Oort-cloud gateway station; Sol permanently excluded from deterministic runs. T-949 (2026-07-13 scoping) explicitly excludes Sol and leaves the legacy markers read in place for this ticket to migrate once Q-107 resolves Sol''s geometry needs a server-side AUTHORED home, never a cascade path.', 'backlog', 'low', NULL, 'client', NULL, '2026-06-12 14:18:10', '2026-07-13 21:53:26.940', NULL, 'c37ad072071989493bfd216ffbb66891', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
+1 -1
View File
@@ -41,7 +41,7 @@ Development follows a strict cascade. Each phase has a concrete deliverable. **D
| 1 | Wiki content complete — all planets, moons, stations, heightmaps, artwork | Implant-ready Godot map of the Reach with click-throughs + wiki/GTTR popups |
| 2 | Economics layer — supply/demand, transport, political/social pressure, corporations, supply chains | Economics spreadsheets/graphs with runtime-tweakable simulation |
| 3 | Planetary/moon maps & station layouts — cities, rivers, mountains, roads, biomes, rail | Atlas of the Reach (implant app) |
| 4 | World generation (tile/chunk/block) — deterministic multilayer seed→tile cascade; each layer viewed as a **map in the implant Atlas** (no in-world rendering) | Deterministic walkable-world data + per-layer Atlas maps + asset catalog |
| 4 | World generation (tile/chunk/block) — deterministic multilayer seed→tile cascade; each layer above the tile fill viewed as a **map in the implant Atlas** (no in-world rendering; chunk/tile/voxel output is harness-verified, never Atlas-mapped — D-226 amendment 2026-07-13) | Deterministic walkable-world data + per-layer Atlas maps + asset catalog |
| 5 | Player control & in-world rendering — character, walls/stairs/doors, lighting, drawn on **generated** tiles (no test map) | Player viewport with final-version assets on the generated world |
| 6 | Detail coloring — room-level NPC population, cultural room grammar | Only when the world is walkable |
+7
View File
@@ -671,6 +671,7 @@ Technical foundation decisions that constrain implementation: engine, client-ser
- 4 levels: Reach map (Phase 1, exists) → System view (orbital diagram, new) → Planetary view (hemisphere, new) → Regional view (hundreds-of-km, new — core Phase 3 deliverable)
- Atlas is the star map extended downward, not a separate app. `implant/map` at different zoom levels.
- Station maps and underground/cave city maps are DEFERRED to a later sprint (similar bounded generation pattern).
- **Amended 2026-07-13:** generation-layer maps (D-226/T-960) bottom out at settlement/quarter-skeleton granularity — chunk/tile/voxel fill is never a planetary map layer; it is harness-verified and inspected in-world in Phase 5 (see the D-226 amendment of the same date).
**2. Existing Foundation**
- 2,394 heightmap PNGs (1024×512 equirectangular, production quality)
@@ -1551,6 +1552,12 @@ Technical foundation decisions that constrain implementation: engine, client-ser
**Consumers** (build geography now; the others adopt the pattern in their own phases — do **not** build them now): Layer-1 geography (Phase 4) → economics (dynamic; pause essential) → save-game inspection (load → pause → inspect; `save_state.rs` substrate).
**Amended 2026-07-13 (T-960 rescope — Si audit ratifications):**
- **(a) Overlay mechanism simplified.** The per-button `pending`/locked + `notify_gen_layer_ready(id)` unlock mechanism in item (3) was never built; the shipped pattern — plain always-toggleable buttons plus a single per-body "generating" pending indicator — has carried two layer deliveries (the L1 triad, then T-1046's district grid) and is ratified as the standard. Stable `gen_*` button ids remain the contract.
- **(b) `gen_l0_heightmap` dropped.** Relief already renders via the always-on `terrain` overlay (D-191 §7); a second generation-labeled L0 toggle would duplicate it.
- **(c) Legend panel stands.** The left-side legend (shape/color key for attractor types and sub-biomes) remains an unshipped, in-scope deliverable of item (3)/T-960.
- **(d) No tile-level Atlas map.** The planetary Atlas maps generation layers down to settlement/quarter-skeleton granularity only; chunk/tile/voxel fill (L5) is verified by the believability/derivation harnesses and inspected **in-world in Phase 5** — never as a planetary map layer (at most aggregate stats). Ratifies T-1046's implementation precedent; matching D-191 amendment + CLAUDE.md Phase-4 wording updated the same day.
- **Rationale:** Reusing the real UI — rather than a parallel offline renderer or dumped files — means the debug/review surface never diverges from what ships, and a dropped artifact can't go stale. Agent-navigability converts qualitative "does the synthesis look natural?" review from a manual eyeball pass into an automatable sweep that flags the few outliers for a human. The harness rides seams that already exist (`TickRate::Paused`, the paused-allowlist, `gameplay_occluded`, the bridge framing, the `run-visual` capture primitive) — a naming-and-contract exercise, not a new subsystem.
- **New surface:** server pause-gating (run-conditions on the world phases keyed to a pause command); client `AtlasAgentInterface` (`observe`/`act`, Control-tree walker) + its local transport; the generation overlay rendering + selector + legend; interactive capture wired to `run-visual`.
- **Implementation:** Phase 4 (epic T-750), built bottom-up — auto-pause substrate, T-969 proxy (D-225), T-960 viewer, agent channel, agent capture. Geography is the first consumer.
+2 -1
View File
@@ -384,10 +384,11 @@ What we're building: game concept, design pillars, prototype definition, map spe
- **(c) Deeper Sol is a future DLC.** Any treatment that makes Sol *feel like actual Sol* (real Earth/Mars/Luna geography, real history, real political textures) is reserved for a separate, future DLC with its own scope. Explicitly NOT current work.
- **Rationale:** Sol carries enormous authorial expectation (real Earth/Mars/Luna geography, real human history). Fudging it would land worse than leaving it sealed. Keeping Sol out of scope keeps the Reach the focus and the realism debt manageable; reserving Sol for a hypothetical DLC keeps the door open without committing to the (massive) job now.
- **Implementation:** generation pipelines filter out bodies whose system has `settlement_wave = 'origin'`; the Atlas zoom UI gates Sol at the system map (no body-level navigation panes). Effective immediately on the Phase-4 fill-seam cascade (T-1000 founding_age backfill explicitly excludes Sol).
- **Amended 2026-07-13:** the player-access boundary is concretely the **Oort-cloud gateway station** — the deepest Sol presence a player ever reaches (lore-canonical cap; reaffirmed by Jeroen during T-949 scoping). Sol stays excluded from all deterministic generation runs, and its client-side authored `markers.json` read persists as the documented D-223/D-236 exception until T-1073 (gated on Q-107) gives Sol's geometry a server-side authored home.
- **Raised by:** Jeroen, 2026-05-26 — formalising what was previously implicit in D-223's naming exemption and GJ-0's wiki frontmatter into a single canonical scope rule.
- **Cross-reference:** [D-145](#d-145-base-building-dlc--gj-902-unclaimed-moon-as-player-settlement-site) (DLC-scoping precedent), [D-191](architecture.md#d-191-atlas-of-the-reach--phase-3-scope-and-pipeline) (Atlas Phase-3 — this constrains Sol's Atlas treatment), [D-223](architecture.md#d-223) (Sol naming exemption + offline `sol_import.py` geometry — this generalises that scope), [D-171](economics.md#d-171-three-currency-system) / [D-174](economics.md#d-174-shadow-economy-layer) (Sol-as-shadow-currency — orthogonal, unaffected), GJ-0 wiki frontmatter (`settlement_wave: origin`, `political_zone: earth_sphere`).
- **Dissent:** None
---
*35 decisions (26 active, 9 superseded). Last updated: 2026-05-26 (D-236 added — Sol player-access scope)*
*35 decisions (26 active, 9 superseded). Last updated: 2026-07-13 (D-236 amended — Oort-gateway access cap)*