chore(meta): close Atlas-viewer batch — T-960/T-970/T-949 done (PR #176 merged)
Review round processed in full (12 findings + 2 recommendations, no retractions); merged and gate-verified on main; worktree + branch torn down. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1277,3 +1277,6 @@ 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 ('06FB0TNSRZ8BFVNWDH17CMH1YM', 'status', 'in_progress', 'review', NULL, '2026-07-14 14:36:24', '2026-07-14 14:36:24.074', '2026-07-14 14:36:24.074', NULL, 'f610c47b468432be2311ffb750fda80a', 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', 'status', 'in_progress', 'review', NULL, '2026-07-14 14:36:24', '2026-07-14 14:36:24.077', '2026-07-14 14:36:24.077', NULL, '38a216c974f2c48757c2c2d08a9d4d1d', 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', 'status', 'in_progress', 'review', NULL, '2026-07-14 14:36:24', '2026-07-14 14:36:24.077', '2026-07-14 14:36:24.077', NULL, 'bdbd4faf5158ae520a7b6e02aa0f0871', 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', 'status', 'review', 'done', NULL, '2026-07-14 16:03:22', '2026-07-14 16:03:22.069', '2026-07-14 16:03:22.069', NULL, 'b754b491146d3be5d46c4bd83eccb4dd', 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', 'status', 'review', 'done', NULL, '2026-07-14 16:03:22', '2026-07-14 16:03:22.074', '2026-07-14 16:03:22.074', NULL, '08a20f24aa5ecd449aabaca49017d2af', 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', 'status', 'review', 'done', NULL, '2026-07-14 16:03:22', '2026-07-14 16:03:22.075', '2026-07-14 16:03:22.075', NULL, '28e7a1cd73d82111ebd5d537666e03a2', 2) ON CONFLICT(hash) DO NOTHING;
|
||||
|
||||
@@ -1441,3 +1441,72 @@ CURRENT READ INVENTORY (verified 2026-07-13):
|
||||
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.', 'review', 'medium', NULL, 'client', NULL, '2026-05-03 14:14:23', '2026-07-14 14:36:24.077', NULL, '44aa53dcae1945b971c673cf3124f7b1', 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.', 'done', 'high', NULL, 'client', 'D-191', '2026-05-22 17:42:34', '2026-07-14 16:03:22.067', NULL, '470c5af080778bdd00875b2e17b92dfc', 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).', 'done', 'high', NULL, 'server', 'D-226', '2026-05-24 09:22:33', '2026-07-14 16:03:22.074', NULL, '255f751baf2f968ce8d282ee1da1354f', 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 implement→break→revert 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.', 'done', 'medium', NULL, 'client', NULL, '2026-05-03 14:14:23', '2026-07-14 16:03:22.075', NULL, '2bc4ee40e5c80f41fd705d1d3081995c', 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);
|
||||
|
||||
Reference in New Issue
Block a user