Rewrites the committed .pql/changelog/ from the old T-NNN-keyed format to the record_id identity model (pql 1.10.0, D-26): tickets keyed by a ULID record_id, the friendly T-NNN in ticket_idmap, references and hashes recomputed. Produced by the one-off cmd/migrate-ids in the pql repo. Other clones: install pql >= 1.10.0, then rm .pql/pql.db && pql plan rebuild to regenerate the local DB from this changelog. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
492 lines
183 KiB
SQL
492 lines
183 KiB
SQL
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 ('06FB0TNSRXN360AQN3973AHS8M', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_dialogue_sprint20: 5 failures — AudioManager.get_active_dip or other API drift', '5 failing test cases in test_dialogue_sprint20.gd. The suite tests D-020 signal decoupling for dialogue_box. Likely failure: test_show_dialogue_does_not_call_audio_manager_directly compares AudioManager.get_active_dip() before/after show_dialogue — if AudioManager.get_active_dip() behavior changed or is not returning clean state, this would fail. Investigate by running the suite in isolation and reading specific assertion failures from the log. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:11:54', '2026-05-02 08:11:54', NULL, '4dae7120006d6a193a64f8cf9a302c6c', 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 ('06FB0TNSRXMVYQJV2QDHH8H7P8', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_input_roundtrip: 3 failures — server binary missing or LocalBridge API change', '3 failing test cases in test_input_roundtrip.gd. All tests check _connect_to_server() which skips if server binary not found — but 3 still fail, suggesting either: (1) server binary is present but something in LocalBridge.send_message, poll, or Protocol.encode_player_inputs changed, or (2) test environment returns false from _connect_to_server but then asserts fail. Investigate by running with --filter test_input_roundtrip and checking the log for exact assertion sites. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:11:59', '2026-05-02 08:11:59', NULL, '43bb1bdbd99567c04b87659d92fe01ea', 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 ('06FB0TNSRY3TXD5HDKHFVGDG18', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_implant_app_lifecycle: 1 failure — ImplantApp or HudGroups state API', '1 failing test case in test_implant_app_lifecycle.gd. Suite tests ImplantApp._internal_app_changed, nav stack, preserves_state, and HudGroups state. after_test resets HudGroups._active_app, _active_mode, _groups — if these private fields were renamed or removed, after_test would fail and bleed state. Or a specific on_open/on_close hook fires differently. Run --filter test_implant_app_lifecycle and check specific assertion. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:12:32', '2026-05-02 08:12:32', NULL, '051b9e0b60e23d92ed295ee5e6fbf2f1', 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 ('06FB0TNSRWK87PCWGZ6GWT2TBM', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_game_state_sprint20: 1 failure — SnapshotHandler or stationary_ticks path', '1 failing test case in test_game_state_sprint20.gd. before_each resets SnapshotHandler._prev_player_position. If this static var was renamed or moved, the before_each hook would error. Alternatively a stationary_ticks path changed in SnapshotHandler. Verify SnapshotHandler still has static var _prev_player_position at that exact name. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:12:38', '2026-05-02 08:12:38', NULL, '8842e278bdab2bdfb8a5a39315a70f73', 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 ('06FB0TNSRYF23MZ86S1XF1542G', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_fog_shader: 1 failure — stale VIS_PERIPHERAL or peripheral sector assertion', '1 failing test case in test_fog_shader.gd. The most likely failure is test_fog_state_forward_vs_peripheral: it asserts Forward > Peripheral visibility values, but Sprint 22 (#569) removed peripheral sector. Now all visible tiles write VIS_FORWARD regardless. The test checks the texture is non-null (not the actual byte values), so it should pass... unless the failure is in test_fog_state_exploration_persists which has a weak assertion. Run --filter test_fog_shader to identify the specific failure. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:12:45', '2026-05-02 08:12:45', NULL, '307954ea49e0c00d28b8df75bf36eb8a', 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 ('06FB0TNSRZYDBRV5T9QVQAXGV0', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_e2e_connection: 1 failure — server binary path or TCP connection state', '1 failing test case in test_e2e_connection.gd. test_send_input_receive_snapshot skips if server binary not found. If it fails, either: (1) server binary exists but connection fails (port collision, timing), or (2) LocalBridge.reset() method was removed (the test calls _bridge.reset() but this may not exist on LocalBridge). Verify LocalBridge has a reset() method. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:12:51', '2026-05-02 08:12:51', NULL, 'b4dbcd91698ef145736699282ec6bacf', 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 ('06FB0TNSRY9FV0S9RE42WY7SHW', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_audio_sprint13: 1 failure — AudioManager.clear_dip or API drift', '1 failing test case in test_audio_sprint13.gd. before_test calls AudioManager.clear_dip(), stop_all_loops(), set_volume() for all buses. If any of these methods were renamed or a bus constant changed, setup would fail and cascade. Or a specific dip timing assertion is stale. Run --filter test_audio_sprint13 and read the specific failure. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:12:56', '2026-05-02 08:12:56', NULL, '46d2fa20895bf94f89ab0bd4f35fce3c', 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 ('06FB0TNSRXCE9D9JYBZWVXMG68', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_ai_dialogue_sprint26: 1 failure — HardwareDetector autoload missing or settings_dialog API', '1 failing test case in test_ai_dialogue_sprint26.gd. The HardwareDetector tests skip if autoload not found. The GameState field tests (ai_enhanced_dialogue_enabled) look correct. The failing test is likely in the settings_dialog section: SETTINGS_DIALOG_SCENE preloaded at class level — if settings_dialog.tscn doesn''t exist or a method was renamed, class-level preload would fail. Check res://ui/settings_dialog.tscn exists and the relevant methods. Sprint 38 triage #871.', 'backlog', 'low', NULL, 'client', NULL, '2026-05-02 08:13:02', '2026-05-02 08:13:02', NULL, 'ae1744a3e74b50f789af254219b2bacd', 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 ('06FB0TNSRW2J2WY3FV4K2C3YRM', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_dialogue_sprint20 — 5 cases fail (signal decoupling suite)', '5 tests in test_dialogue_sprint20.gd fail since sprint-36. Tests verify D-020 dialogue_box.gd signal decoupling (#558). Code analysis shows signals are correctly implemented but failures persist. Requires actual Godot test run to identify root cause. Opened 2026-05-02 during #871 triage. Tests: test_show_dialogue_emits_dialogue_state_changed_true, test_show_dialogue_does_not_mutate_game_state_directly, test_hide_dialogue_emits_dialogue_state_changed_false, test_show_dialogue_emits_audio_dip_requested_dialogue, test_show_dialogue_does_not_call_audio_manager_directly.', 'cancelled', 'medium', NULL, 'client', NULL, '2026-05-02 08:20:14', '2026-05-02 08:20:14', NULL, '5f474109b5a672e8eb82b8d6b9988e14', 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 ('06FB0TNSRYMWW54FKG4TMV9ZWM', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_input_roundtrip — 3 live-server cases fail', '3 tests in test_input_roundtrip.gd fail. Tests require the Rust server binary at server/target/debug/settled-reach-server. When binary is present, round-trip input tests (movement, interact, move_then_interact) fail — likely a protocol mismatch or timing issue. Opened 2026-05-02 during #871 triage. Skipped gracefully when binary absent.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:19', '2026-05-02 08:20:19', NULL, '65519ef0ba9bc9932f1d6fa59735e95a', 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 ('06FB0TNSRYHKX5YTGVJYVPFR9M', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_implant_app_lifecycle — 1 case fails (unknown)', '1 test in test_implant_app_lifecycle.gd fails since sprint-36. Suite tests ImplantApp hook ordering, preserves_state, register_screen. Cannot identify the specific failing test from code analysis alone — requires actual Godot test run. Opened 2026-05-02 during #871 triage.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:22', '2026-05-02 08:20:22', NULL, '1371232c3fb1aa78881adbe258be1b18', 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 ('06FB0TNSRZNA6DFJ4MCGC9Z8GR', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_game_state_sprint20 — 1 case fails (stationary_ticks/zone_id)', '1 test in test_game_state_sprint20.gd fails. Suite tests D-020 server-authoritative stationary_ticks and zone_id. Logic appears correct from code analysis against snapshot_handler.gd — requires actual Godot test run to identify which of the 9 test cases fails. Opened 2026-05-02 during #871 triage.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:28', '2026-05-02 08:20:28', NULL, 'cab9c7755545f2155108fe8f8d0e6ed3', 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 ('06FB0TNSRW2VWRZ69X3SVAW6SG', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_fog_shader — 1 case fails (FogState boundary/timing)', '1 test in test_fog_shader.gd fails. FogState is registered as autoload so all tests run (not skipped). Cannot identify the specific failing test from code analysis. Candidates: test_boundary_wall_fog_vis_forward (uses update_from_state on live FogState), performance timing tests. Requires actual Godot test run. Opened 2026-05-02 during #871 triage.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:32', '2026-05-02 08:20:32', NULL, '4a4e83ea32e43879c0b343857b96b3f0', 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 ('06FB0TNSRYZF0J8H0X0HQJPWXR', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_e2e_connection — 1 case fails (live server required)', '1 test in test_e2e_connection.gd (test_send_input_receive_snapshot) fails when server binary is present. Requires server/target/debug/settled-reach-server. Skips gracefully when binary absent. Likely protocol or connection timing issue. Opened 2026-05-02 during #871 triage.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:37', '2026-05-02 08:20:37', NULL, '75bd889c7e88afadf64bd91a971334e5', 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 ('06FB0TNSRYYP8VGT5WQK2YY7YR', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_audio_sprint13 — 1 case fails (AudioManager/zone)', '1 test in test_audio_sprint13.gd fails. Suite tests D-073 zone crossfade, D-068 volume persistence, D-069 dip timing. All code paths verified correct against AudioManager implementation. Requires actual Godot test run to identify which specific test case fails. Opened 2026-05-02 during #871 triage.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:42', '2026-05-02 08:20:42', NULL, '57e24f494f816b6d59dd6b59677dc90b', 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 ('06FB0TNSRYW63JGGSJ5W47V9TC', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_ai_dialogue_sprint26 — 1 case fails (HardwareDetector/settings)', '1 test in test_ai_dialogue_sprint26.gd fails. Suite has 67 tests — HardwareDetector-dependent tests skip gracefully when autoload absent, but HardwareDetector IS registered as an autoload so most run. Cannot identify specific failing case without actual test run. Opened 2026-05-02 during #871 triage.', 'cancelled', 'low', NULL, 'client', NULL, '2026-05-02 08:20:46', '2026-05-02 08:20:46', NULL, '8bec33d28c85029aabf8dcb77963ad9c', 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 ('06FB0TNSRXETWQ0T9YEDYZEX9W', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_examine_display_sprint18: 2 failures — ExamineDisplay scene or API mismatch', '2 failing test cases in test_examine_display_sprint18.gd. Scene path res://ui/examine_display.tscn exists. Failures are likely in the ExamineDisplay-specific tests (not the GameState snapshot tests which look straightforward). Check whether ExamineDisplay API changed: _show(result), _dismiss(), _is_showing(), auto_dismiss timer wiring. Sprint 38 triage #871.', 'done', 'low', NULL, 'client', NULL, '2026-05-02 08:12:04', '2026-05-02 08:22:58', NULL, '95408ce7d67c9e917e0e7f2cc7dd64fe', 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 ('06FB0TNSRZ5D364SW1QJ7RZJ04', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_client_p1: 2 failures — FogEntities or EntityRenderer API change', '2 failing test cases in test_client_p1.gd. Suite tests fog byte encoding (#3-#6) and entity lifecycle (#7-#9). The fog tests look correct against current FogState API. Entity tests may be failing if EntityRenderer or FogEntities constructor/script changed. Run --filter test_client_p1 and check specific failed assertions. Sprint 38 triage #871.', 'done', 'low', NULL, 'client', NULL, '2026-05-02 08:12:09', '2026-05-02 08:22:58', NULL, 'c2efef4d18140a264b216082b05fe13d', 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 ('06FB0TNSRZ1JZHT0YSRW8ZDC6R', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_monologue_display: 1 failure — MonologueDisplay private API mismatch', '1 failing test case in test_monologue_display.gd. Suite reads private state (_visible, _queue, _next_fade_in_msec) from monologue_display.tscn instance. If any of these internal var names changed or the scene path moved, the test fails. Check client/ui/monologue_display.gd for current private var names. Sprint 38 triage #871.', 'done', 'low', NULL, 'client', NULL, '2026-05-02 08:12:26', '2026-05-02 08:22:59', NULL, '2a8d1fd6844777e65c5ec7fbd2937892', 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 ('06FB0TNSRYCD16X79D3VNXAYBR', 'bug', '06FB0TNSRXJDJRGQQ073VZRA4W', 'test_time_display_sprint17: 1 failure — test_hud_time_row_updates_after_process', '1 failing test case in test_time_display_sprint17.gd. Likely test_hud_time_row_updates_after_process: calls instance._process(0.016) then asserts hud.get_time_text() returns ''12:00 . Afternoon . D1''. If main.gd _process no longer calls HUD update_from_state or if HUD.get_time_text format changed, this would fail. Check main.gd _process for HUD update wiring. Sprint 38 triage #871.', 'done', 'low', NULL, 'client', NULL, '2026-05-02 08:12:20', '2026-05-02 08:22:59', NULL, 'd84157aa089ee960b82fa123deb2a0ee', 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 ('06FB0TNSRYWGGD3W648EJEJMC0', 'story', NULL, 'Add decisions-orphan-tickets CLI — surface tickets with invalid decision_ref', 'Follow-up from PR #136 review (T8): tickets.decision_ref is free-text without a foreign key. A typo''d D-ID, or a decision that gets renumbered/deleted, will silently leave tickets pointing at nothing — they won''t show up under the referenced decision in ''make decisions-coverage'' or ''tooling/db/decision show <D-NNN>''.
|
||
|
||
Deliverable: a new CLI subcommand (e.g. ''tooling/db/decision orphan-tickets'') that lists tickets whose decision_ref is set but does not match any row in the decisions table. Optionally add a ''make decisions-orphan-tickets'' Makefile target.
|
||
|
||
Schema unchanged — pure SELECT. Avoids the fragility of a two-way foreign key across markdown-sourced decisions and DB-sourced tickets.', 'done', 'low', NULL, 'ci', NULL, '2026-04-22 06:22:41', '2026-05-02 16:37:06', NULL, '320c8b375993d15035df6236fd1c0201', 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 ('06FB0TNSRX0B8MD2GRZ8KV1APC', 'task', NULL, 'Switch meta.schema_version to monotonic semver for savegame migration lineage', 'Follow-up from PR #136 review (T9): the current meta.schema_version field stores a SHA-1 of server/data/systems-schema.sql at generation time. Two SHAs cannot be ordered — you cannot tell from the hash alone which schema version is newer.
|
||
|
||
When the savegame system is built (Phase 5+) and needs migration lineage (forward-migrating an old save to a current systems.db), SHA hashing is the wrong primitive. Switch to an explicit monotonic version number (semver or integer) bumped manually whenever the schema changes in a backwards-incompatible way. The SHA can still be stored alongside for tamper detection.
|
||
|
||
This is a Phase 5+ item — do NOT change now. Ticket exists to capture the design debt so it isn''t rediscovered during savegame work.
|
||
|
||
Blocked by: Phase 5 (world generation + walkable world) reaching savegame design.', 'done', 'low', NULL, 'ci', NULL, '2026-04-22 06:22:51', '2026-05-02 16:37:06', NULL, '8cbd20a953a743909d6f00ad7ffddd1b', 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 ('06FB0TNSRZ2W0H4Z2CDQSJT5M0', 'task', NULL, 'Copy-team review: wiki/corporations authored by server team in #860', '**Follow-up to sprint 37 server #860.** Server-team agent Dudley authored/modified 21 wiki/corporations/*.md files to resolve the economy-db coverage gate. Per CLAUDE.md team scope rules, wiki/ is copy-team territory — this ticket asks copy team to review the cross-team writes for voice, style, lore consistency, and factual accuracy.
|
||
|
||
**Files to review:**
|
||
|
||
*Modified (tag additions for economy coverage):*
|
||
- baektu-mining-alliance.md, bergkraft-antriebswerke.md, bifrost-marmor.md
|
||
- gate-corporation.md, hanyang-precision.md, jeju-lattice.md
|
||
- nordmark-skog.md, norrland-woodcraft.md, salud-alliance.md
|
||
- shetland-wool.md, societe-chimique.md, stalownia-kowalski.md
|
||
- svanevann-waters.md, thrds.md, tongyeong-drive.md
|
||
|
||
*New (~36-line corp pages):*
|
||
- arbour-aggregates.md
|
||
- earth-standard-group.md
|
||
- rush-mining.md
|
||
- scapa-flow-industries.md
|
||
- sede-chemical-works.md
|
||
- threshold-fuel-syndicate.md
|
||
|
||
**Scope of review:**
|
||
- Voice/style consistency with existing wiki corp pages
|
||
- Lore consistency (system references, corridor geography, D-record citations)
|
||
- Tag values match existing commodity vocabulary
|
||
- Frontmatter schema compliance
|
||
|
||
**Rationale for accepting cross-team write:** Lead decision 2026-04-21 — sprint 37 is a maintenance sweep, Dudley''s writes were pragmatically needed to unblock the coverage gate, and the content is plausibly written. Quality review happens here, not at merge time.
|
||
|
||
**If issues are found:** File fixes as direct copy-team tickets; do not revert the server PR.
|
||
|
||
**Context:** server PR sprint-37/server, ticket #860 (original), wiki/authoring/tier1-module-authoring.md (schema reference).', 'done', 'medium', NULL, 'copy', NULL, '2026-04-21 15:34:55', '2026-05-02 16:46:06', NULL, '8fa992266fc07171052577a15ddcc2e2', 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 ('06FB0TNSRXTXW5V42XZ8HAF990', 'task', NULL, 'Implement CityGenerationContext struct (D-200)', 'Rust struct populated from systems.db at game startup. Fields: city_id, political_archetype, prosperity_baseline, surrounding_biome, road_entry_directions, footprint_radius_km, founding_orientation, world_tier. See D-200, workshop-outcomes.md.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:18', '2026-05-02 20:51:30', NULL, 'c4c3d35deb4096386377dd1a4f45d6fe', 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 ('06FB0TNSRYTHKJCGTFPRP3G1P0', 'story', NULL, 'Free camera viewer — decouple camera from player, WASD pan + scroll zoom, implant/atlas/map access', 'Bare-minimum debug viewer to inspect generated tile output without a player character. This is throwaway/iterative — the rendering system will evolve with the generation pipeline. Do not over-engineer.
|
||
|
||
Deliverables:
|
||
1. Decouple Camera2D from GameState.player_position — add a debug toggle key (e.g. F4)
|
||
2. WASD / arrow key pan in free camera mode (no server input sent)
|
||
3. Scroll wheel zoom
|
||
4. Implant UI accessible in free camera mode — atlas (implant/map/atlas) and star chart (implant/map) openable as normal
|
||
|
||
Explicitly NOT in scope:
|
||
- Visual polish
|
||
- Fog or LOS adjustments
|
||
- Any rendering changes — use whatever TileRenderer produces today
|
||
- Save/restore of camera position
|
||
|
||
Key files: client/scripts/main.gd (camera lerp in _process), client/scripts/autoloads/hud_groups.gd', 'done', 'high', NULL, 'client', NULL, '2026-04-24 10:56:54', '2026-05-03 09:23:43', NULL, '1046988861533625612c115427a5264d', 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 ('06FB0TNSRX8QPW2MH203K203HW', 'task', NULL, 'Strip archetype-driven client code (follow-up to #878 server)', '**Follow-up to server #878.** Per lead direction 2026-04-21: the CharacterArchetype trace is Phase 6 filler, not production. Server #878 strips the full server-side trace. This ticket mirrors it on the client.
|
||
|
||
**Keep (production, per lead):**
|
||
- Character creation UI flow
|
||
- Insert screens / diegetic neural overlays
|
||
|
||
**Strip (uncleaned filler):**
|
||
- `client/scripts/autoloads/game_state.gd` — `character_archetype: String` field (line 100), `lattice_profile` derivation from archetype (line 47)
|
||
- `client/scripts/autoloads/session_manager.gd` — `save_character_archetype()`, `_read_archetype_file()`, character.txt save/load (lines 58, 172-192)
|
||
- `client/scripts/protocol/protocol.gd` — character_archetype field on StartupMessage encoding
|
||
- `client/scripts/autoloads/sim_bridge.gd` — archetype wire-up
|
||
- `client/tests/test_signal_sprint24.gd` — audit; delete or narrow if archetype-dependent
|
||
- Any monologue color-palette code keyed off archetype (search for lattice_augmented / lattice_baseline)
|
||
|
||
**Blocked by:** server #878 (removes `character_archetype` field from StartupMessage — protocol break rides #874''s PROTOCOL_VERSION wave).
|
||
|
||
**Verification:** client launches, character creation UI loads, insert screens render, game session starts without archetype state in the codebase. Grep `character_archetype`, `lattice_profile`, `smuggler`, `detective` in client/ — only character-creation UI references remain.
|
||
|
||
**Context:** see `docs/architecture/sprint-37-878-audit.md` (Tyre''s full audit of the archetype trace) and the revised #878 scope in the server task description.', 'done', 'medium', NULL, 'client', NULL, '2026-04-21 15:05:27', '2026-05-03 09:23:44', NULL, 'ef6fdd4adeafefe5ef47c21df9f3f696', 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 ('06FB0TNSRZB98P4FKEAGW9PFDW', 'task', NULL, 'Revive fog state behavioral tests (exploration persistence, grow-only bounds)', 'test_fog_sprint22.gd was deleted in Sprint 37 (#870 parse-error cleanup). It contained unique behavioral tests for FogState: EXP_EXPLORED persistence after leaving LOS, grow-only bounds invariant, texture-resize copy, BoundaryWall handling (#585). test_fog_shader.gd covers shader file content only — the FogState data management tests are not covered elsewhere. Rewrite against current FogState API when time allows. Spec: D-059, D-066, #569.', 'done', 'medium', NULL, 'client', NULL, '2026-04-21 15:01:10', '2026-05-03 09:23:45', NULL, '43e3063f53df8539a1040f60360dea82', 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 ('06FB0TNSRZ9251FR8EKRRKAXNG', 'bug', NULL, 'dialogue_box confrontation_monologue signal does not fire in headless test mode', 'test_d063_confrontation_signal_fires_on_confrontation_option in test_dialogue_sprint18.gd: signal_fired remains false after _on_option_pressed(0) on a confrontation option. _start_confrontation_beat calls create_tween() before emitting confrontation_monologue; likely the tween creation or tween_property call on ''panel'' aborts execution before the emit in headless mode. Investigate whether panel is null or tween creation fails headless. Test spec: D-063.', 'done', 'medium', NULL, 'client', NULL, '2026-04-20 16:09:48', '2026-05-03 09:23:45', NULL, '80ed1e96e16f42b2348bb0733ba6d1e6', 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 ('06FB0TNSRXJDJRGQQ073VZRA4W', 'bug', NULL, 'Pre-existing test failures across 13 suites (sprint-36/37 triage umbrella)', 'Umbrella for pre-existing client test failures that pre-date sprint 36 work and are unrelated to ongoing sprint features. Each needs investigation: stale assertion, real regression from a prior sprint, or flaky. Recommend splitting into per-suite subtasks once a sprint has bandwidth.
|
||
|
||
## Current state (2026-04-22, after sprint-37 PR #135 review-fix pass)
|
||
|
||
**23 failing test cases across 13 suites, 60 assertion-level failures** (each test case can report multiple failed assertions):
|
||
|
||
| Suite | Failing test cases |
|
||
|---|---|
|
||
| test_dialogue_sprint20.gd | 5 |
|
||
| test_rendering.gd | 3 |
|
||
| test_input_roundtrip.gd | 3 |
|
||
| test_examine_display_sprint18.gd | 2 |
|
||
| test_client_p1.gd | 2 |
|
||
| test_time_display_sprint17.gd | 1 |
|
||
| test_monologue_display.gd | 1 |
|
||
| test_implant_app_lifecycle.gd | 1 |
|
||
| test_game_state_sprint20.gd | 1 |
|
||
| test_fog_shader.gd | 1 |
|
||
| test_e2e_connection.gd | 1 |
|
||
| test_audio_sprint13.gd | 1 |
|
||
| test_ai_dialogue_sprint26.gd | 1 |
|
||
|
||
**Delta vs sprint-36 baseline:** Sprint-36 triage recorded 22-33 failing test cases (two counts given in the original ticket — title said 22, enumeration summed to 33). Current 23 is consistent with those numbers within drift. Some suites improved:
|
||
|
||
- test_bug_report_ring_buffer (was 2, now 0) — resolved by sprint-37 #869 fix
|
||
- test_game_state (was 1, now 0) — resolved, root cause unidentified; no longer in output
|
||
- test_rendering (was 5, now 3)
|
||
- test_input_roundtrip (was 6, now 3)
|
||
- test_examine_display_sprint18 (was 3, now 2)
|
||
- test_client_p1 (was 3, now 2)
|
||
- test_e2e_connection (was 2, now 1)
|
||
|
||
No suite regressed upward. No new suites surfaced failures. The 60 assertion-level count (vs the 22-33 test-case count) is a different counting mode reported by the gdUnit4 JSON summary — the same 23 test cases can raise multiple assertion failures each.
|
||
|
||
**Umbrella scope also covers** the coverage gaps from sprint-37 #870 deletions that are not tracked by named revive tickets: test_entanglement_sprint22 (no live client behavior — Entanglement is a server-side seed concept per #178), test_sprint30 (no unique live coverage), test_session_manager_sprint19 (SessionManager API contracts — ID format, uniqueness, resume_game — none directly asserted in the new merge-path tests; tracked here rather than filing a dedicated ticket).
|
||
|
||
Failure log archived to /tmp/sr-test-full.log on dev branch sprint-36/client (timestamp 2026-04-21).', 'done', 'medium', NULL, 'client', NULL, '2026-04-21 07:29:34', '2026-05-03 09:23:46', NULL, 'af2408340ccb59c9ba20c2d1dc2f2278', 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 ('06FB0TNSRZ9Q7NHVDRT6ARMCWW', 'task', NULL, 'D-210 SubBiomeVariant implementation', 'D-210 defines SubBiomeVariant for fine-grained biome classification within SettingType::Wilderness districts. Currently deferred — SettingType::Wilderness carries a plain String biome field. Implement SubBiomeVariant enum and wire it into the atlas skeleton generator when the biome taxonomy is finalized.', 'backlog', 'low', NULL, 'server', NULL, '2026-05-03 10:30:14', '2026-05-03 10:30:14', NULL, 'fa0c9f8a80c893c3db9fe374a93acd30', 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 ('06FB0TNSRXCY04WSBRF2346M78', 'task', NULL, 'Populate atlas_city_names corp HQ entries', 'Python: cross-reference corporations.headquarters_system/body to populate corp_id on atlas_city_names rows.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:38:53', '2026-05-03 14:00:25', NULL, '05203d41cf586c7c6f7f36fb2b4c4f44', 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 ('06FB0TNSRXK4THJN2B3PWA98KM', 'task', NULL, 'Add body_radius_km column to bodies table (D-204)', 'Physical radius for area_count formula. planet_class fallback for NULL values. See D-204.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:38:38', '2026-05-03 14:00:25', NULL, '0927249186f9082ecbab9976b319e05e', 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 ('06FB0TNSRXN72YEPAD3AWQ7CY0', 'task', NULL, 'Pre-compute province boundaries from watershed analysis (D-205)', 'Python: extract watershed drainage basin boundaries from heightmaps, store as polylines in atlas_province_boundaries. ~2d effort.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:38:46', '2026-05-03 14:00:25', NULL, '1604e5db3bbe7d46dbd46018d49b018b', 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 ('06FB0TNSRW4K5KPS81BAMN1F38', 'task', NULL, 'Add atlas_body_heightmaps table to systems-schema.sql (D-202)', 'Float32 LE BLOB storage for heightmaps. ~512KB per body. See D-202 for schema.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:38:24', '2026-05-03 14:00:25', NULL, '1fd76a3a3ff9fd16ecc1a0c1785d9ab4', 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 ('06FB0TNSRYVH6DGX06M2T5ZVFG', 'task', NULL, 'Implement D8 drainage routing algorithm (D-208)', 'D8 priority-flood from heightmap. River threshold flow_accumulation > 200. Output: RiverNetwork (river_cells, confluences, mouths), drainage basins. ~50ms/body target. See D-208. ~3d effort.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:30', '2026-05-03 14:00:25', NULL, '233e1733906cfe2f9c5e4ca471c2f642', 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 ('06FB0TNSRYPSX7DHHYQ2GFKX28', 'task', NULL, 'Add atlas_province_boundaries table to systems-schema.sql (D-205)', 'Watershed boundary polylines per body. See D-205.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:38:34', '2026-05-03 14:00:25', NULL, '351f01e5fc236ab0b6ce228633337a68', 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 ('06FB0TNSRWB9G78ZWF6R4D51W0', 'task', NULL, 'Implement heightmap BLOB loader in Rust', 'Load float32 LE heightmap from atlas_body_heightmaps via SQLite. bytemuck reinterpret. ~0.5d.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:22', '2026-05-03 14:00:25', NULL, '3602e701e76198ba669ce3498efaefef', 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 ('06FB0TNSRYVE81M6P7JG20BZ0G', 'bug', NULL, 'Fix WorldTier enum values in generator.rs (D-218)', 'Replace Peripheral/Connected/Core with Epicenter/Regional/Backwater/Passage/Waypoint per D-218. Blocks all generation Rust code.', 'done', 'critical', NULL, 'server', NULL, '2026-05-01 10:38:20', '2026-05-03 14:00:25', NULL, '3bf97ea70aecf780a6c76d513d7aba45', 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 ('06FB0TNSRXYDC7HA2Y9VT5FQD4', 'task', NULL, 'Derive body_radius_km from planet_class fallback', 'Python: populate body_radius_km column. Use explicit values where available, planet_class lookup otherwise. 0.5d effort.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:38:57', '2026-05-03 14:00:25', NULL, '481649564d57b93e6c145e795388123e', 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 ('06FB0TNSRW41Q268P7XSKE8A2C', 'task', NULL, 'Implement BodyWorldState resource and LRU cache (D-203)', 'Bevy Resource holding Layer 1-2 output per body. LRU cache policy, 50 bodies, ~5MB. See D-203.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:26', '2026-05-03 14:00:25', NULL, '630d276e3e09a84ff5bd29ab5a26b742', 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 ('06FB0TNSRWC5E7J4B2XRTZZHK0', 'task', NULL, 'Add atlas_city_names table to systems-schema.sql (D-207)', 'Name reservation table replacing authored city positions in markers.json. Columns: body_id, name, economic_role, population, corp_id (nullable), reserved (bool). See D-207.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:38:28', '2026-05-03 14:00:25', NULL, '71742106e8bab4e73fa2291a0b693f6f', 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 ('06FB0TNSRWVCBQ6XQNJSDT9KTG', 'task', NULL, 'Implement attractor-matching pipeline (D-211, D-195)', 'Five-phase pipeline: score matrix build, Tier A greedy, Hungarian Tier B+C, synthetic overflow, name fulfillment. Two-tier mismatch flagging (0.35 warning, 0.15 error). See D-211, D-195. ~4d effort.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:35', '2026-05-03 14:00:25', NULL, '94da85249f362c19a55bbc9f70870114', 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 ('06FB0TNSRYHDC2XE89TEFCRZCG', 'task', NULL, 'Generator polish follow-ups to #853: suffix monotony auto-fix + explicit cultural-history prompting', '**Follow-up to #853 (Sprint 37).** Dudley''s #853 patches resolved 5 of 7 subtasks cleanly. Two bits remain as partial/deferred:
|
||
|
||
**§3 — Suffix monotony (partial):** `gemma_naming.py` now *detects* when >40%% of a body''s mountain names share a trailing word and emits `suffix_monotony_warning` in the counts dict, but does not auto-regenerate. Rationale (per code comment): the batch pipeline has no voice access, so auto-fix would require a targeted re-run. This ticket: either add a targeted re-run pass when the warning fires, or write a wrapper script that catches the warning and re-queries only affected bodies.
|
||
|
||
**§5 — Cultural crossmix (partial):** The existing corridor_substyles refill mechanism (next-adjacent register) provides some cross-cultural blending, but the ticket asked for explicit `corridor + cultural-history` context threaded into the naming prompt. This ticket: extend `build_batch_prompt` to accept and include a cultural-history blurb (drawn from the body''s corridor_substyles description or a new per-corridor history registry) so the LLM sees both the primary register and the secondary influences.
|
||
|
||
**Priority:** low — naming generation is functional; these are quality polish that would help after a full atlas regen surfaces visible patterns.
|
||
|
||
**Context:** see Sprint 37 #853 original spec and Paula''s analysis notes in `docs/design/atlas-generator-refinement-notes.md`. Paula''s collision script should be re-run after these land to verify measurable impact.', 'done', 'low', NULL, 'server', NULL, '2026-04-22 06:20:44', '2026-05-03 14:00:25', NULL, '95b70490cb946eb20b63b7e8d22fab5c', 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 ('06FB0TNSRX0TPK51K258877QAM', 'bug', NULL, 'Multiple baseline tests panic with Bevy Resource-does-not-exist on main', 'Discovered: 2026-04-21 during sprint 37 server work verification. Confirmed present on clean main (commit f0465e40), NOT a sprint regression.
|
||
|
||
**6 failing tests share the same Bevy runtime panic pattern:**
|
||
- t3_pause_mid_corridor_discards_movement_and_resumes (cross_room_transitions.rs)
|
||
- player_moves_north_through_full_pipeline
|
||
- proof_room_tick_10_matches_golden
|
||
- entity_collision_blocks_movement
|
||
- movement_validated_within_app
|
||
- world_boots_and_ticks
|
||
|
||
**Symptom (same across all 6):**
|
||
thread panicked: Encountered an error in system ''Enable the debug feature to see the name'': Parameter ''Enable the debug feature to see the name'' failed validation: Resource does not exist
|
||
|
||
**Likely root cause:** A Resource was removed from the app init somewhere without updating the test harness (or the test harness was never updated when a system was added). The Bevy debug feature is OFF so system names are hidden.
|
||
|
||
**Investigation steps:**
|
||
1. Enable Bevy debug feature (feature = [''debug''] on bevy_ecs dep) OR set BEVY_BACKTRACE=full — get the actual panicking system name and missing Resource.
|
||
2. Most likely one Resource missing in test harness setup fixes all 6 (they share symptom).
|
||
3. Fix: either insert the resource in the test fixture, or wrap the system param in Option<T>/If<T>.
|
||
|
||
**Why not blocking sprint 37 PRs:** these predate sprint work. Sprint 37 work actively removes 7 archetype-dependent failing tests (archetype_monologue.rs + v01_integration_playthrough.rs) — net improvement to test health. The 6 baseline failures remain, unrelated.
|
||
|
||
**Assigned:** Hoshe (QA ownership)', 'done', 'medium', NULL, 'server', NULL, '2026-04-21 17:02:53', '2026-05-03 14:00:25', NULL, 'a83190a3650bde732237e95adc429b6c', 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 ('06FB0TNSRWDVZVJ7R9EAVJJC9G', 'task', NULL, 'Populate atlas_city_names from wiki content', 'Python: read wiki settlement data, populate atlas_city_names rows. Named cities with economic_role and population. Corp HQ cross-reference from corporations table.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:38:50', '2026-05-03 14:00:25', NULL, 'acccb911d6ef327eb850fcc09e176c24', 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 ('06FB0TNSRYD4BWGGKHXSQ1M998', 'task', NULL, 'Implement SettlementClass and settlement type enums (D-196)', 'SettlementClass: NameLocked/PopulationBudget/EconomicTriggered/OrganicGrowth. Active/ghost thresholds per class. See D-196.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:39:10', '2026-05-03 14:00:25', NULL, 'caa598dc1da327977ac07e4cab686954', 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 ('06FB0TNSRYZGFVVQZWJDT1VCYG', 'task', NULL, 'Expand check-systems-db-stamp GENERATOR_SOURCES to cover naming helpers', '**Follow-up to PR #137 / Tyre review of #847 stamp infrastructure.**
|
||
|
||
`tooling/check-systems-db-stamp` only tracks `generate_atlas` source files. The atlas generation pipeline now has two naming helpers that feed into the final `systems.db` content but are not covered by the stamp:
|
||
|
||
- `tooling/planet-gen/gemma_naming.py` — batch-names bodies/features via Gemma LLM (#833 / #853).
|
||
- `tooling/planet-gen/naming_core.py` — shared algorithms (Levenshtein, distinctiveness, batch prompts) used by `gemma_naming.py`.
|
||
|
||
If either of these changes without re-running the generator and re-stamping, `make check-systems-db-stamp` will pass while `systems.db` drifts from its source SHAs. This is the exact failure mode `check-systems-db-stamp` exists to prevent.
|
||
|
||
**Scope:**
|
||
|
||
1. Extend `GENERATOR_SOURCES["generate_atlas"]` in `tooling/check-systems-db-stamp` to include:
|
||
- `tooling/planet-gen/gemma_naming.py`
|
||
- `tooling/planet-gen/naming_core.py`
|
||
2. If there is a parallel `IMPORT_ECONOMICS_SOURCES`-style constant in the atlas pipeline (mirror the `import_economics` pattern), mirror the update there too. Comment at line 35-37 of the stamp script notes the pattern.
|
||
3. Decide whether either naming helper warrants its own `generator_name` entry (if naming is ever run independently of the full atlas generation) — default is fold them into `generate_atlas` unless the economy-db precedent applies.
|
||
4. Re-stamp via the normal atlas regen path so the SHA captures the new file set, then verify `make check-systems-db-stamp` still says OK.
|
||
|
||
**Non-goal:** Do not modify `systems.db` content; this is a stamp-infrastructure expansion only.
|
||
|
||
**Cross-reference:** PR #137, #847 (atlas determinism smoke test, merged with the original narrow source list), `tooling/check-systems-db-stamp` line 38–48.
|
||
|
||
**Rationale:** The stamp was added specifically to catch the drift-without-regen class of bug. A narrow source list lets that bug through for naming changes, which are now a meaningful and frequent source of atlas content edits.', 'done', 'medium', NULL, 'server', NULL, '2026-04-22 07:58:45', '2026-05-03 14:00:25', NULL, 'cfe4bac21568e462067f4859473428e6', 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 ('06FB0TNSRXRJH5BH1XZYN4DZE0', 'story', NULL, 'District skeleton generator — Phase 1 implementation', 'Implement actual Phase 1 generation logic for DistrictSkeleton. The data model in server/src/simulation/generator.rs is complete but all generation is stubs.
|
||
|
||
Input: a city entry from markers.json (name, lat/lon, population_tier, primary_function, planet_class, economy node reference)
|
||
Output: a filled DistrictSkeleton with real values — block grid assignments, SettingType, ComplexityTier, WorldTier, ZonePalette, DistrictLayoutMode (Grid vs Organic), reservations list, zone_palette.
|
||
|
||
RESCOPED per planet-down-cascade workshop: Stages 1-2 only (classification + block grid). Stages 3-5 deferred. Depends on WorldTier fix and city decomposition.
|
||
|
||
Scope for this ticket (Phase 1 skeleton only — no chunk-level tiles):
|
||
- Derive SettingType from primary_function + planet_class
|
||
- Derive ComplexityTier from population_tier + system WorldTier
|
||
- Assign DistrictLayoutMode (grid vs organic) from settlement_pattern
|
||
- Populate 4x4 block grid with ZoningType assignments from primary_function
|
||
- Generate multi-block reservations for high-population cities (parks, transit terminals)
|
||
- No chunk fill, no tile data, no NPC placement
|
||
|
||
Blocked by: #897 (generation cascade planning — D-records define the contract this implements), #900 (WorldTier enum fix)
|
||
|
||
Key files:
|
||
- server/src/simulation/generator.rs — DistrictSkeleton and all related types
|
||
- tooling/planet-gen/generate_atlas.py — city placement input (markers.json)
|
||
- server/data/systems.db — economy node cross-reference', 'done', 'high', NULL, 'server', NULL, '2026-04-24 10:57:11', '2026-05-03 14:00:25', NULL, 'd59d8b0e2c34053b4503e36a2da7b326', 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 ('06FB0TNSRYS4PFPZ8N2SW2KV1M', 'task', NULL, 'Implement DistrictType, PoliticalArchetype, FoundingOrientation enums (D-213, D-214, D-215)', 'All generation-pipeline enums for district classification. See D-213, D-214, D-215.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:39:14', '2026-05-03 14:00:25', NULL, 'd5f11b5f3156501ff97b52f4ee9f86f0', 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 ('06FB0TNSRY2912ZVY8PKFG58YM', 'task', NULL, 'Normalize economic_role values in bodies table', 'Migration: normalize inconsistent values (agriculture->agricultural, resource_extraction->extraction, coordination->service_mixed). Add validation to import_economics.py. See D-194 data quality blocker #3.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:02', '2026-05-03 14:00:25', NULL, 'de4ab761ef2067d54274d3b9713cc79b', 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 ('06FB0TNSRZT1JNFQAK8XTPSSMC', 'task', NULL, 'Implement WorldTier, ComplexityTier, SettingType enums in Rust (D-218, D-201)', 'Replace String type aliases with real enums. WorldTier: Epicenter/Regional/Backwater/Passage/Waypoint. Depends on WorldTier bug fix.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:06', '2026-05-03 14:00:25', NULL, 'e0687a4130d32df6523f714fe18c00e9', 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 ('06FB0TNSRXNYREKVCGGKEFV01M', 'task', NULL, 'Add atlas_feature_names table to systems-schema.sql', 'Geographic feature name reservations (rivers, mountains, passes). Columns: body_id, name, feature_type, priority.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:38:31', '2026-05-03 14:00:25', NULL, 'ece3df838a0e8f21853c584c8e6122a4', 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 ('06FB0TNSRWNSD8GZKVG1RCBS4W', 'task', NULL, 'Import heightmap BLOBs into atlas_body_heightmaps', 'Python pipeline step: read heightmap PNGs from planet-gen output, convert to float32 LE BLOBs, insert into atlas_body_heightmaps. Part of generate_regional.py or standalone importer.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:38:42', '2026-05-03 14:00:25', NULL, 'f4e7a579e278165ea1462bac9070f515', 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 ('06FB0TNSRXJNA7QBYRTW11Z7CW', 'task', NULL, 'Implement three-component district mix (D-194)', 'Population tier guarantees + 10x9 multiplier table + political archetype modifiers + founding age character. Self-contained per city. See D-194. ~3d effort.', 'done', 'high', NULL, 'server', NULL, '2026-05-01 10:39:39', '2026-05-03 14:00:26', NULL, '037a473f0ea8fd02b9dd9b108810e99b', 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 ('06FB0TNSRXRNJQH5CCWPJRV30M', 'task', NULL, 'Implement SystemNameIndex with Aho-Corasick text scanning (D-206)', 'Aho-Corasick automaton over all body/system names from systems.db. Scans news ticker, NPC dialogue, documents to trigger background pre-generation before player travels. Part of the background generation infrastructure (Tier 5, after #924). ~1d effort.', 'done', 'low', NULL, 'server', 'D-206', '2026-05-02 07:46:35', '2026-05-03 14:00:26', NULL, '242cfd92daffcdf55a26f8551b6ce9a4', 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 ('06FB0TNSRXXSC85WGGC94C452M', 'task', NULL, 'Implement GeographicAttractor, AttractorType, CompatibilityMatrix types (D-211, D-195)', 'Rust type definitions for the attractor-matching pipeline. GeographicAttractor struct, AttractorType enum (7 variants), CompatibilityMatrix (10x7 scoring table from D-195). Prerequisite types for #919 (attractor-matching pipeline). ~0.5d effort, Tier 3.', 'done', 'medium', NULL, 'server', 'D-211', '2026-05-02 07:46:25', '2026-05-03 14:00:26', NULL, '7ae4df25dde1285b84c04e8c9ecc3905', 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 ('06FB0TNSRY6Q1B8ADW41ZMYARM', 'task', NULL, 'Implement background generation queue (D-206)', 'Rayon thread pool, priority queue (Immediate/High/Medium/Low), Aho-Corasick SystemNameIndex for event-driven pre-generation. See D-206.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:39:53', '2026-05-03 14:00:26', NULL, '8c885d77c9d06accb79650eaa2a65e7d', 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 ('06FB0TNSRY8YKG6MYGRRRQYHH4', 'task', NULL, 'Implement TerritorialStatus derivation (D-212)', 'Priority-ordered classification per Province. 6 values. placed_at_generation flag. See D-212.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:39:42', '2026-05-03 14:00:26', NULL, 'c5d217c64e26a07f38cfd6aa8c0ff731', 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 ('06FB0TNSRWJP1EK9KN6F0YCWRC', 'task', NULL, 'Implement BlockIrregularity from founding_age (D-216)', 'Age-based block grid irregularity. Archetype-specific step values. Minimum 0.05. See D-216.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:39:45', '2026-05-03 14:00:26', NULL, 'd22e070684eb925aa31844509ce4fa80', 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 ('06FB0TNSRXWNCFHAQF2WQRFTAG', 'task', NULL, 'Implement tile condition thresholds (D-217)', 'Prosperity-driven tile condition: Intact>0.63, Worn 0.43-0.63, Cracked 0.23-0.43, Broken<0.23. Threshold-crossing cache invalidation. See D-217.', 'done', 'medium', NULL, 'server', NULL, '2026-05-01 10:39:49', '2026-05-03 14:00:26', NULL, 'd424c82637bd901199ef49122f0a6929', 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 ('06FB0TNSRZJPKKA5H11G5YNJ4R', 'task', NULL, 'Render province boundaries on planetary map (D-205)', 'Load atlas_province_boundaries polylines from systems.db and render on the Godot planetary map. Fill provinces with TerritorialStatus-derived colors. Depends on #907 (province boundary pre-computation in Python). Tier 5, ~2d effort.', 'done', 'low', NULL, 'client', 'D-205', '2026-05-02 07:46:40', '2026-05-03 14:12:45', NULL, 'e0ee45d67cbc093c818e220b3e0cfc87', 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', NULL, '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.', 'backlog', 'medium', NULL, 'client', NULL, '2026-05-03 14:14:23', '2026-05-03 14:14:23', NULL, 'bb3c96c0f068f53bbb22995b5f465bf4', 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 ('06FB0TNSRXBP82ANSVAFMACCHW', 'epic', '06FB0TNSRZE4CSS8YR0FCEXMK8', 'Phase 1: Wiki content complete — all planets, moons, stations, heightmaps, artwork', 'Deliverable: Implant-ready Godot map of the Reach with click-throughs + wiki/GTTR popups for all systems/planets/moons/stations. Includes: body catalog (epic #738), galaxy map navigator UI, system orbital schematic, heightmap pipeline, planetary shader screenshots, GTTR per-body entries. Schema + tooling already built (atlas CLI, bodies/stations tables, sync-wiki).', 'done', 'critical', NULL, NULL, NULL, '2026-03-25 13:29:07', '2026-05-22 16:56:36', NULL, '939e09e5fe0f2570fdd79db4daa7d4b6', 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 ('06FB0TNSRY23YPP1Q0TYJ816HW', 'epic', '06FB0TNSRZE4CSS8YR0FCEXMK8', 'Phase 2: Economics layer — supply/demand, transport, corporations, supply chains', 'Deliverable: Economics spreadsheets/graphs showing simulation running in fast-forward with runtime-tweakable values. X4-style production chains adapted to 300-system scale. Hundreds of corporations with supply chains. Reusable as in-game economic news implant components. Depends on Phase 1 (wiki content provides the economic profiles the simulation reads).', 'done', 'high', NULL, NULL, NULL, '2026-03-25 13:29:24', '2026-05-22 17:11:16', NULL, '027eb6fc96d03ac80f60816d4e558cb2', 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 ('06FB0TNSRZ8Z6NN74YKCCRCPMR', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Generation validation pass + Phase 5 dependency gate', 'Validation pass: generated content reads correctly (settlements legible, walkable, named). Establishes the dependency gate that locks Phase 5 (player control, epic #749) behind Phase 4 completion per the cascade rule (D-166 amended 2026-05-22).', 'backlog', 'medium', NULL, 'server', 'D-166', '2026-05-22 17:42:34', '2026-05-22 17:42:34', NULL, '7c1e4644e95572686e56d371698fe0e6', 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 ('06FB0TNSRZKXHAYMT7Q6WW3XDC', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Layer 5 — Chunk→Tile fill (floors, walls, doors, objects)', 'THE primary gap (generator.rs is stubbed). Generate walkable tiles from the block/chunk skeleton: floors, walls, doors, placed objects, using tile-condition thresholds 0.63/0.43/0.23 (D-217). Output is the walkable world data.
|
||
|
||
Refinement (round 2, 2026-05-25): Layer-5 fill is the D-230 on-demand derive phase (<5ms shell derivation Void/Wall/FloorSlab/Roof from the cached tags) plus the BuildingExteriorTag visual grammar and material vocabulary (D-235: WallMaterial/RoofForm/FacadeRhythm/StreetSurface, template-filtered (era = maintenance/wear, not a material gate)) plus interstitial and operations-surface fill driven by BulkClass coverage (D-233). Blocked by 957, 976, 977.
|
||
|
||
Refinement (2026-05-26): READY behind 1006/957/976/977/1005. shell_derive = rectangle-containment + z-range over cached tags (~0.5ms/chunk). FillChunk pre-condition: only after SkeletonGenerated; re-enqueue High if block_tags absent. Wire chunk_streaming.rs to enqueue FillChunk on load-radius entry (no GenerationQueue interaction today). Interstitial token derived from setback_tier (D-235) x position; bulk operations-surface tagged built-infra, not open space. Child 988 = exterior grammar, now 3-step template-filtered (era is wear, not a material gate). Files: gen_queue.rs FillChunk arm, workers/stubs.rs, plugin.rs SkeletonGenerated handler.', 'backlog', 'high', NULL, 'server', 'D-217', '2026-05-22 17:42:34', '2026-05-22 17:42:34', NULL, '8636bae8d7812ee36cd47485270f837e', 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 ('06FB0TNSRXDCJS4P9Z5JQ1DAAM', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Asset pipeline + catalog (walls, doors, props; rural & station variants)', 'Parallel asset pipeline producing the walls/doors/props/lamp-posts/etc. the tile fill places, with rural and station variants, tracked in a production-status catalog. Runs alongside generation.', 'backlog', 'medium', NULL, 'visual', 'D-166', '2026-05-22 17:42:34', '2026-05-22 17:42:34', NULL, 'c8a3f14cb0c76f54acc321de853f0df3', 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 ('06FB0TNSRWFFQWH38616CABT04', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Markers → names-only flavored pool + remove 6 hand-authored template machinery (D-223)', 'Implement D-223. (1) Reduce ALL markers.json to a flavored name pool — names only (river/mountain/settlement names), no positions or topographic geometry. River/mountain positions derive from heightmap + D8 drainage (D-208); settlement positions from the economic sim + placement (D-211). (2) Remove the 6 hand-authored template machinery: delete hand-authored marker positioning for Lendel/Edict/Vuurkloof/Røros/Cairnside/Estrade, drop the reserved=1 pinning, and remove all ''template'' special-casing in the atlas pipeline (generate_atlas.py, gemma_naming.py, test_batch_naming.py, apply_name_fixes.py) and the atlas_city_names schema. The 6 BODIES remain real places — keep their wiki/lore/names/economic profiles; only the authored machinery is removed. After this there is no template category. (3) Update atlas pipeline + schema, regen-db. (4) Leave historical archives (sprints, workshops, audits, CHANGELOG, atlas proposals) untouched. Foundation/gating item for the rest of Phase 4.
|
||
|
||
## Rework plan (verified 2026-05-22 via pipeline map)
|
||
Break + geometry-re-add risk is ENTIRELY in generate_atlas.py; import_economics.py is names-only-safe (reads names/DB only; populates atlas_city_names from cities name/kind/population).
|
||
1. generate_atlas.py: RETIRE geometry production. process_body() must stop calling place_cities/generate_infrastructure/place_gate_terminal and stop writing geometry to markers (else it re-adds stripped geometry). load_markers(): drop grid validation. sync_markers_to_db(): stop reading center/path/grid/area_fraction.
|
||
2. Atlas geometry tables — empty/drop via MIGRATION_SQL: atlas_cities(center), atlas_roads/rivers/railroads(point_count), atlas_pois/oceans(center), atlas_mountain_ranges(geometry), atlas_body_grids(w/h). SURVIVE: atlas_city_names, atlas_feature_names, atlas_province_boundaries, atlas_city_positions, atlas_body_heightmaps.
|
||
3. Meta-stamp: update tooling/check-systems-db-stamp GENERATOR_SOURCES + Makefile regen-db if generate_atlas is reduced/retired.
|
||
4. reserved/template machinery: apply_name_fixes.py template patches, gemma_naming.py template-name preservation, import_economics reserved=1 corp-HQ insertion — review per D-223 (name-protection reserved may stay; position pinning already gone via strip).
|
||
5. Sol: tooling/planet-gen/sol_markers/*.json + sol_import.py — migrate to names-only (separate, not in regen-db critical path).
|
||
6. Verify: make regen-db green; atlas geometry tables empty (reveals the gap for the server cascade).', 'done', 'high', NULL, 'server', 'D-223', '2026-05-22 17:37:25', '2026-05-22 21:30:01', NULL, 'd8e039a56df41233cc797a4b1e796fa9', 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 ('06FB0TNSRZZ5XKET93HPHKQHKW', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Phase-4 test hardening — deferred review gaps (#953/#963 review)', 'Follow-ups from the Hoshe/Tyre pre-bake review (the BLOCKER/MAJOR items were fixed inline; these are the deferred MINOR/coverage items):
|
||
|
||
TESTS:
|
||
- features.rs: full per-type attractor reachability fixtures — craft heightmaps that guarantee LakeShore (enclosed depression), PassEntrance (saddle), PlainCenter (flat), RiverCrossing (confluence). Currently only RiverMouth/CoastalAccess/ValleyFloor are exercised on the slope/sine fixtures.
|
||
- heightmap.rs: 8-bit grayscale decode path; sea_level passthrough assertion; downsample identity/upsample early-return.
|
||
- drainage.rs: basin area_pct bit-for-bit determinism (only river_cells + basin count checked today).
|
||
- layer1.rs: attach_feature_names mountain branch with a non-empty mountain pool + ≥1 Alpine attractor.
|
||
- features.rs: thin_by_spacing behavior (spacing collisions, equirectangular column wrap).
|
||
- import_economics.py: automated idempotency test — two runs on a scratch DB yield identical atlas_city_names count (not doubled), and 0 rows for system ''GJ 0'' (Sol exemption). Wire alongside check-systems-db / pre-push.
|
||
- Wire test_sim_determinism.py into pre-push or a make target.
|
||
|
||
MINOR CODE NITS:
|
||
- drainage.rs ~480-488: comment the intentional isolated-basin fallback divergence from the old merge-to-basin-0 behavior (Tyre N1).
|
||
- planet_simulation.py ~787-788: oasis_water binary_dilation iterations are fixed-pixel — scale by GRID_W/512 for biome-display consistency at 1024 (cosmetic, Atlas only, not cascade; Tyre N2).', 'backlog', 'medium', NULL, 'server', NULL, '2026-05-23 06:09:45', '2026-05-23 06:09:45', NULL, 'e29f5ce66f23aaf1b6439e74789cde9b', 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 ('06FB0TNSRZHWCPTQ6EZ2Y1SXA0', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Layer 0 — canonical 16-bit heightmap.png (2048×1024) + rename relief→reliefmap (D-202)', 'Replace the DB heightmap-BLOB model (D-202) with a per-body file-based canonical elevation, and fix the misleading naming.
|
||
|
||
(1) RENAME the existing color hypsometric ''heightmap.png'' → ''reliefmap.png'' (display only, keep 1024×512) across all ~2398 bodies. It is a relief render, not a heightmap.
|
||
(2) BAKE a new canonical ''heightmap.png'' = 16-bit GRAYSCALE elevation at 2048×1024, from planet_simulation at higher native resolution (value-noise is resolution-independent; rescale gaussian sigma so mountains keep physical size). Single source of truth for elevation — deterministic, viewable, ~0.5-1.5MB/body PNG-compressed. 2048×1024 chosen to bound install size (sub-pixel detail is synthesized procedurally by lower cascade layers anyway).
|
||
(3) Rust heightmap.rs: load the 16-bit PNG from the body''s terrain_reference path (add ''png'' crate dep), normalize to f32 [0,1]. Layer 1 (continental drainage/basins/mountain-ranges) DOWNSAMPLES to ~512×256 (keeps the ~45ms benchmark); lower layers (region/block/tile) sample full-res for local detail. Decouples cost from resolution.
|
||
(4) DROP atlas_body_heightmaps table + the DB-BLOB write path in import_heightmaps.py (the PNG is now the store).
|
||
(5) Update terrain_reference convention, populate_terrain_reference.py, the Atlas client heightmap loader, and AMEND D-202.
|
||
|
||
The asset bake + 2398-file rename (1,2) run where numpy/scipy are available; the Rust loader + decision (3,5) land independently in ''rust country''. Foundation for #953 (Layer-1 elevation input) and all lower cascade layers.', 'done', 'high', NULL, 'server', 'D-202', '2026-05-22 22:29:30', '2026-05-23 06:44:16', NULL, '15f2490083b86d97cc7679ca9e7a53c4', 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 ('06FB0TNSRY2Y8HR0SWX9BSW7MW', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Rework or replace pre-push clerk review — non-exhaustive + token-burn', 'Clerk was DISABLED 2026-05-23 in .config/hooks/pre-push (SR_RUN_CLERK=1 to force-run) because it was net-negative in practice during the #963 push:
|
||
|
||
PROBLEMS:
|
||
1. Non-exhaustive / non-deterministic: a single run reports ~the first concrete contradiction it finds and stops. Across one push, three DISTINCT real D-202 inconsistencies surfaced only on the 1st, 2nd, and 3rd re-push (D-200/D-201 contradiction, stale 2048×1024 docstring, sea_level self-contradiction) — each run missing the others. So an APPROVED verdict cannot be trusted as ''clean''.
|
||
2. Token burn: re-reviews the entire origin/main..HEAD range on every push attempt; no per-commit verdict cache, so a one-line fix + re-push re-runs ~20 agent reviews.
|
||
|
||
REWORK DIRECTIONS (from the session discussion):
|
||
- Exhaustive enumeration: prompt must list ALL contradictions in a pass, not stop at the first; bias toward completeness.
|
||
- Holistic D-record check: review the cumulative decisions/ diff for internal + cross-record consistency (consistency is a global property the per-commit model approximates badly — e.g. line 928 vs 930 within D-202).
|
||
- Verdict cache: gitignored SHA->verdict log; reuse cached verdict only when both the commit AND the decisions/ state are unchanged (invalidate on any decisions/ change in range, since that can flip an earlier commit''s verdict — exactly what happened with the 2048 docstring once D-202 changed).
|
||
- Move the skip mechanism into the cache (mark a SHA as skip) and REMOVE the ''Clerk-Skip:'' commit-message trailer (no magic values in commit messages).
|
||
- Consider: is per-commit the right granularity at all, vs one holistic range review?
|
||
|
||
Until reworked, decision-record consistency is the author''s responsibility (manual audit).', 'backlog', 'medium', NULL, 'meta', NULL, '2026-05-23 07:49:02', '2026-05-23 07:49:02', NULL, 'f4e203a52313264d1e9988dcefd698f9', 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 ('06FB0TNSRWVJCSHJ28MP9PSW18', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Rust dependency maintenance — rand advisory + freshness + serde_yaml', 'From a security/freshness review (2026-05-23, cargo audit + cargo update --dry-run):
|
||
|
||
SECURITY: No CVEs/vulnerabilities (cargo audit clean across 214 deps; cargo deny advisories ok). One advisory:
|
||
- rand 0.9.2 RUSTSEC-2026-0097 — ''unsound with a custom logger using rand::rng()''. WARNING-level (unsound, not an exploitable vuln), already allow-listed in deny.toml. Fix available: rand 0.9.4 (semver-compatible). Bump rand → 0.9.4 to clear it (rand 0.10.1 is a major, separate).
|
||
|
||
FRESHNESS: ~70 semver-compatible updates available (all routine patch/minor): bevy_ecs/app/tasks 0.18.0→0.18.1, clap 4.5→4.6, rayon 1.11→1.12, pathfinding 4.14→4.15, uuid 1.20→1.23, serde_json, tracing-subscriber, zerocopy, etc. A (lockfile-only) applies them; do as its own commit + cargo test.
|
||
|
||
MAINTENANCE: serde_yaml 0.9 is deprecated/archived upstream (no advisory, but unmaintained). Plan a migration (serde_norway / serde_yml) eventually — it parses body-def frontmatter + agent files.
|
||
|
||
Do as a focused dep-maintenance pass (not mixed into feature work): (1) rand 0.9.4 bump [security], (2) compatible-update sweep [freshness], (3) serde_yaml migration [maintenance, larger]. Re-run cargo audit + cargo test after each.', 'done', 'low', NULL, 'server', NULL, '2026-05-23 08:34:30', '2026-05-23 09:03:54', NULL, '38f83f416cdda3e15c8575bcd7c69e35', 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 ('06FB0TNSRWWKYN8PJC178XBRSG', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'clippy-1.93 test-code debt + pre-push --all-targets gap', 'Surfaced 2026-05-23 when a warm server/target/ made the pre-push hook actually run clippy (it skips on cold worktrees). Two parts:
|
||
|
||
1. HOOK GAP: .config/hooks/pre-push runs ''cargo clippy -- -D warnings'' WITHOUT --all-targets, so it only lints lib+bins (non-test) — test and example targets are never clippy-checked. That''s why test-code clippy debt accumulated unflagged. Decide: add --all-targets to the hook (after cleaning the debt below), or leave tests unchecked.
|
||
|
||
2. TEST-CODE clippy-1.93 debt (NOT auto-fixable; needs judgment), all in cfg(test) modules / tests/ — does NOT block the current hook:
|
||
- disallowed_types HashSet/HashMap → BTreeSet/BTreeMap: tests/shadowcast_bench.rs (×8), tests/news_ticker.rs (HashSet + HashMap), src/npc/mood.rs (cfg(test)), src/simulation/sound.rs (check if cfg(test) or lib — verify SoundEventKind: Ord before swap).
|
||
- field_reassign_with_default: src/npc/disclosure.rs, src/simulation/monologue.rs (×2), src/simulation/save_io.rs (test setup) → struct-init.
|
||
- assertions_on_constants: src/simulation/listening.rs, tests/cross_room_transitions.rs (intentional invariant asserts → const block or scoped #[allow] with comment).
|
||
- approx_constant: src/settings/types.rs Float(3.14) — DELIBERATE non-pi value → scoped #[allow], do NOT replace with PI.
|
||
- drop_non_drop: src/npc/vision.rs drop(Mut<WalkabilityMap>) — verify if it''s an intentional early borrow-release (#[allow] + comment) or removable.
|
||
- unnecessary_get_then_check: tests/information_boundaries.rs (×3) → contains_key.
|
||
- cloned_ref_to_slice_refs: tests/triangle_validation.rs → std::slice::from_ref.
|
||
- doc_overindented_list_items: tests/news_ticker.rs.
|
||
- unused_must_use: src/simulation/input.rs (cfg(test)) → let _ = .
|
||
|
||
Do as one focused clippy-1.93 sweep + cargo test. Machine-applicable ones already landed in the prior commit.', 'done', 'low', NULL, 'server', NULL, '2026-05-23 08:37:58', '2026-05-23 09:03:54', NULL, 'ce9ef3b6529697da28989e898b0da129', 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 ('06FB0TNSRWN22SX82ZTBDWSPY4', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Layer 1 — empty-world topography (heightmap → drainage → feature tags → sub-biome)', 'Audit + wire the existing atlas modules into a reproducible Layer-1 pipeline: heightmap BLOB load (D-202) → D8 priority-flood drainage (D-208) → 7 geographic feature tags (D-209) → sub-biome variants + terrain_modification_cost (D-210). Attach river names from the markers name pool (D-223) to the largest computed rivers; mountains take names from the pool (positions given by the fixed heightmap).', 'done', 'high', NULL, 'server', 'D-208', '2026-05-22 17:42:34', '2026-05-23 09:08:20', NULL, '471e12a02690a414f06c0e83ffb7fbbe', 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 ('06FB0TNSRZ947KMQDDRX9RSH2M', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Deterministic seed→output harness + golden-seed regression test', 'End-to-end determinism guarantee: same seed → byte-identical generation output across the whole cascade. Golden-seed regression test that runs the pipeline and diffs against a stored fixture. The load-bearing property — every layer must be reproducible (D-010 principle 4). rng.rs exists; wire it through and lock it with a test.
|
||
|
||
---
|
||
Refinement (2026-05-23, /whats-next):
|
||
- SCOPE: build an extensible per-layer harness interface (run_cascade(seed, layer_range) -> snapshot) as the primary deliverable; Layer 0->1 golden test is the first instantiation. Layers #954-959 plug in as they land.
|
||
- FIXTURE: two golden files under server/tests/golden/ following the UPDATE_GOLDEN=1 pattern -- SHA-256 of heightmap.png bytes (Layer 0) + msgpack of Layer1Output (Layer 1). NOT systems.db (explicitly non-byte-deterministic per asset-pipeline rule / D-202).
|
||
- SEEDCHAIN IN SCOPE: implement a real SeedChain type (master world seed -> per-body -> per-district derivation) and thread it through atlas callers (skeleton_gen.rs and generator.rs currently pass a plain seed:u64 with manual wrapping_add). Harness verifies cascade(world_seed=42) derives all sub-seeds deterministically. Replaces the doc-comment-only SeedChain references.
|
||
- COUPLING: Q-098 (Layer-1 output persistence vs recompute) is tied to #952; resolve or reference during implementation.
|
||
- REUSE: AtlasRng (server/src/atlas/rng.rs), SimRng (server/src/simulation/rng.rs), test_sim_determinism.py (Layer-0 Python guard), drainage.rs inline determinism tests, golden suite (make golden-diff/golden-update).', 'done', 'high', NULL, 'server', 'D-200', '2026-05-22 17:42:34', '2026-05-23 10:26:23', NULL, 'f25f41423fdae8d069b210067267852a', 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 ('06FB0TNSRW31YK22RGJ5WQB8Z0', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Activate AnalyzeBody cascade execution + BodyWorldStateCache populate (D-225)', 'Tyre''s #960 design long pole (D-225). gen_queue.rs::run_work_item''s AnalyzeBody is a documented stub (deferred from #142): it returns BodyAnalyzed without running the cascade or populating BodyWorldStateCache. Activate it: on the Rayon background tier, resolve the body heightmap, run run_cascade(Topography) (~45ms), build BodyWorldState from Layer1Output, and deliver the computed state so the main thread inserts it into the D-203 LRU. GenCompletion::BodyAnalyzed must carry the computed BodyWorldState (or a results side-channel), not just body_id (Tyre R3). MUST run off the tick thread (D-203 — no blocking CPU on main). Unblocks the atlas layer-stream proxy (D-225).
|
||
|
||
---
|
||
Scope (Tyre, 2026-05-23): #968 owns the full connect-the-queue-to-the-app loop — GenerationQueue (#924) + BodyWorldStateCache (#917) are built but referenced NOWHERE in the running app (inert tier), so this is one closed loop, not separable. (1) un-stub run_work_item AnalyzeBody to run run_cascade(Topography) and map CascadeSnapshot -> BodyWorldState (new constructor); (2) GenCompletion::BodyAnalyzed carries the computed BodyWorldState, not just body_id (was Tyre Risk 3); (3) register GenerationQueue + BodyWorldStateCache as resources (a GenerationPlugin or fold into an atlas plugin) + a Bevy drain system (PreInput per D-206) draining completions -> cache.insert(state); (4) acceptance: submit AnalyzeBody with a test heightmap path -> drain -> cache populated with non-empty Layer-1 data. BOUNDARY: AnalyzeBody carries resolved inputs { body_id, heightmap_path: PathBuf, sea_level: f32, body_seed: SeedChain } — the enqueuer resolves (mod-first BodySourceResolver + SeedDomain::Body derivation are #969/policy); run_work_item is pure compute (inputs -> BodyWorldState), no FS/DB access. #969 proxy is the production submitter. Do NOT split the drain wiring into a middle ticket.', 'done', 'high', NULL, 'server', 'D-225', '2026-05-23 12:23:55', '2026-05-24 08:50:20', NULL, '6036a0872de37019d2bf47bcf3002d4a', 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.', 'backlog', 'high', NULL, 'server', 'D-226', '2026-05-24 09:22:33', '2026-05-24 09:22:33', NULL, '40c7512deeed7c48e257258cfa1460d7', 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 ('06FB0TNSRWTP633SM8XB302MBM', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Atlas agent control channel — observe/act named-intent navigation (D-226)', 'D-226 layer 4 (apex). A client-side AtlasAgentInterface exposing a JSON control channel so an automated agent (terminal/curl, headless Godot) can navigate the REAL Atlas UI: observe -> JSON of (a) current data state shown and (b) a walkable UI affordance tree (toggle controls: id/label/state/locked); act -> named SEMANTIC intents (select_system/open_system/select_body/open_regional/select_city/set_overlay/reset_view/back/close_atlas) backed by the same handlers a click calls (the map uses _gui_input, NOT pixel-clicks), plus get_layer_data_summary (attractor/river/basin counts as JSON without rendering). Single AtlasAgentInterface autoload/static class for a stable contract; generic Control-tree walk so economics/saves plug in later. Turns human-eyeball review into an agent QA sweep. Depends on #960 (the viewer) + the auto-pause substrate. Screenshot capture is a separate ticket (kept off the critical path).', 'backlog', 'medium', NULL, 'client', 'D-226', '2026-05-24 09:22:38', '2026-05-24 09:22:38', NULL, 'bbc8b47323d40fefaf53c54b57755160', 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 ('06FB0TNSRZHH3XBGFRZYJ393FG', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Agent interactive screenshot capture — reuse run-visual primitive (D-226)', 'D-226 layer 5 (capture). A capture_layer_screenshot affordance on the agent channel: set the requested overlays active, clear hover state, render the canvas, return a PNG path. REUSE the existing capture primitive (tests/run-visual + the frame-delayed save_png pattern proven by character_creation.gd standalone capture) — do NOT build a new headless rasterizer. Complements the existing scenario/flow visual-golden regression (that batch/regression role is unchanged); this adds INTERACTIVE agent-driven capture. Isolated from the agent channel (#agent-channel) so the headless-render wrinkle can''t gate the navigation apex. Depends on the agent control channel.', 'backlog', 'medium', NULL, 'client', 'D-226', '2026-05-24 09:22:41', '2026-05-24 09:22:41', NULL, 'b2e500aca5a3a5a4de91859b07b27c52', 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 ('06FB0TNSRXQH2YH9MPZV004C18', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Atlas layer-stream proxy + bridge protocol (D-225)', 'D-225 layer-stream proxy: server-side delivery of per-body Layer1Output to the Godot client, mod-first, compute-on-demand, no bake. NEW: BodySourceResolver (server/src/atlas/source_resolver.rs) resolves body_id -> heightmap.png across mod dirs + base install (terrain_reference from systems.db, read-only); v1 wires base root only but the resolver + search-order exist and are tested with a synthetic mod root. layer_proxy.rs: cache hit serializes; miss enqueues Immediate AnalyzeBody + replies Pending, pushes response on completion. BRIDGE: additive message tag on the EXISTING IPC stream (no second socket, no envelope-everywhere rewrite) — AtlasLayerRequest{body_id, up_to_layer} / AtlasLayerResponse{status, layer1} as new MessagePack message types disambiguated structurally in v1; single framed response (not chunked); raster NOT streamed (client loads reliefmap.png from disk); whole Layer1Output per response (client composites additive overlays). Depends on #968 (AnalyzeBody activation). See D-225.
|
||
|
||
---
|
||
Part of the D-226 inspection harness (data-path, layer 2): the proxy is what the Atlas viewer (#960) and the agent channel (#971) read. See D-226 for the full stack: live-pause substrate (#970) -> proxy (this) -> viewer (#960) -> agent channel (#971) -> capture (#972).', 'done', 'high', NULL, 'server', 'D-225', '2026-05-23 12:24:02', '2026-05-24 16:07:21', NULL, 'cc94ed7b89238dd90e51fdf1c9fcecf1', 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 ('06FB0TNSRYEM4VSX74MS4NKQ1C', 'bug', NULL, 'Client test suite — pre-existing failures under bare run-godot', 'Surfaced 2026-05-24 running the full client suite (tests/run-godot, no server) during #960. NOT caused by #960 — verified: test_input_roundtrip fails identically at the pre-change baseline, and the rest are unrelated subsystems. Two categories to triage:
|
||
|
||
CATEGORY 1 — server-dependent (expected-fail under bare run-godot): test_e2e_connection (test_send_input_receive_snapshot), test_input_roundtrip (movement/interact/move_then_interact). They error with ''Nil snapshot'' / ''.tick on Nil'' because no sim server is spawned. They need the run-ipc-* harness or SR_LIVE=1. FIX OPTIONS: gate/skip these under bare run-godot (mark as requiring a server) OR have run-godot spawn the server for the e2e tier, so tests/run-godot
|
||
{"suite":"godot","total":2522,"passed":2482,"failed":40,"duration_ms":96836,"log":"/tmp/sr-run-godot.1737738.log"} is green without false negatives.
|
||
|
||
CATEGORY 2 — genuine logic failures in subsystems unrelated to current work: test_audio_sprint13 (test_d067_chime_duration_spec_is_300_to_400ms, line 547 ''Expecting true but is false''), test_fog_sprint22 (exploration_data_preserved_across_resize), test_fog_shader (visibility_texture_update_performance), test_dialogue_sprint18/20 (signal/audio-dip), test_monologue_display (queue_never_exceeds_max_depth), test_implant_app_lifecycle (on_insert_deactivated_closes_insert_app), test_ai_dialogue_sprint26 (settings_dialog warning label). Triage each: fix or remove/xfail with a reason.
|
||
|
||
Goal: a green (or explicitly-gated) bare `make test-client` so client regressions are detectable. Until then, run targeted suites (run-godot --filter <stem>).', 'backlog', 'medium', NULL, 'client', NULL, '2026-05-24 16:49:54', '2026-05-24 16:49:54', NULL, 'a49cafffca41636bc19123c1de5e1513', 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 ('06FB0TNSRWMZBFV1V6F79VW8S4', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Architecture-flavor pipeline — wiki to generator cultural grammar (D-232)', 'Architecture-domain completion of D-167. (a) Gemma architecture-flavor methodology doc: stage-1 register selection + stage-2 structured output {tag, allow:[ObjectTag], block:[ObjectTag], weight, trauma_decay_rate}, analogous to the D-223 naming methodology. (b) trait_templates catalog + atlas_body_trait_bias bake (see round-3 note) (GTTR+index.md). (c) allow/block weighted filter applied at chunk fill over the D-142 zone-type ObjectTag pool (dominant wins categorical; weighted-avg continuous). (d) ObjectTag vocabulary authoring (Miri+Araminta co-maintenance). Three-layer resolution body x district x era-band (era-band depth = Q-106). NOTE: source-authoring location rides on Q-107 (content consolidation); the table+filter are buildable independently. Formally retires D-104/D-105/D-101-axisA/D-107. Flavor stays purely wiki-authored; economics (D-233) is a parallel channel composing only at the filter.
|
||
|
||
Round 3 (2026-05-25): D-232 rewritten to the TRAIT-TEMPLATE model (not per-body Gemma arrays). Build: (1) trait_templates table = shared holistic catalog (~35 floor / 40-45 target); two-tier eligibility = integer-bps hard gates (bulk_class/prosperity/ubiquity) + weight mods (role/faction/age/corridor/morphology); corridor (geographic_sector) is a WEIGHT, never a gate. (2) atlas_body_trait_bias (sparse, ~30-40 hero bodies: pin/boost/suppress); RETIRE atlas_body_culture + atlas_body_culture_era. (3) Three-phase draw: body vocabulary K-draw (K=5/3/1/0 by complexity_tier, SeedChain D-224, coverage-aware, pin counts toward K) -> district-dominant by zone_affinity (one template/district, applied whole) -> within-template seed picks. (4) Deviation/swerve system + (5) visual fallback hierarchy = separate tasks. CI guardrails (Nigel): eligible pool >=5 post-gate, no template >60pct weight, bias per-body, catalog grows with corpus. Result trait_selection: Vec<String> on skeleton, re-derivable. Channel-separate from D-233 (what vs how). Era = maintenance/wear (D-217), NOT a tech ladder. Source location -> Q-107.
|
||
|
||
Scope note (2026-05-26): the catalog CONTENT authoring is split out to story #1005 (blocking). 977 is now the MECHANISM only — tables, three-phase draw, district-dominant, deviation system, fallback hierarchy. #1005 (the ~35-template content) blocks the draw/fill/visual tasks.
|
||
|
||
Refinement (2026-05-26): READY behind 1006/1005. Mechanism only. trait_templates + atlas_body_trait_bias DDL into import_economics.py MIGRATION_SQL + systems-schema.sql, integer-bps weights throughout. draw_body_vocabulary() inside the GenerateSkeleton Rayon task: hard-gate filter -> weight (mods x bias) -> SeedChain weighted draw of K (5/3/1/0 by ComplexityTier) -> trait_selection on skeleton; pin counts toward K; coverage-aware (>=1 template per present district type, else sparsity escape-hatch). pick_district_dominant() at the FillChunk head (zone_affinity-weighted). CI guardrails in importer validation (pool>=5, weight<=60pct, bias per-body). Swerve (1003) + fallback (1004) are child tasks. SeedChain complete, no change. Files: import_economics.py, generator.rs.
|
||
|
||
--- From PR #148 review (Tyre): the trait_templates.geographic_sector column is a pool-narrowing hint for baseline/heritage sub-pools and a SOFT weight (never a gate); it composes with weight_mods.geographic_sector. The draw must join both, not treat the column as a gate. (D-232 corridor = two-part pool.)', 'backlog', 'high', NULL, 'server', 'D-232', '2026-05-25 19:08:55', '2026-05-25 19:08:55', NULL, 'a0be06c9179573432230fa6f462f02e7', 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 ('06FB0TNSRWABYYB11QMJDTXE2G', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Guarantee-audit engine over step-3 tags (D-097)', 'Implement the guarantee-audit engine per the D-097 amendment. Runs after step-3 fill completes for a district; on a failed mandatory check for the district world_tier, fill regenerates with adjusted params. run_guarantee_audit(skeleton, building_tags, street_graph, seed) -> GuaranteeAuditResult. Tier-1 (all inhabited): social_hub_present, informal_zone_present, encounter_corridor. Tier-2 (full-complexity): traffic_chokepoint, institutional_space, insider_space, economic_node, breach_only_zone. Tier-3 A-1..A-4 assassin-lens: elevated_vantage (above_ground>=3 + LOS to chokepoint), egress_multiplicity (>=2 unique street connections), temporal_opacity (>=1 TemporalWindow door), non_institutional_route (Public->insider path avoiding institutional). All pure graph/geometry over building_tags + street_graph -- NO interior generation. Depends on 957 (tag schema) + the street-geometry story (D-234).
|
||
|
||
Refinement (2026-05-26): READY behind 1006/976. GuaranteeAuditResult struct replaces the String alias (14 bools). Signature run_guarantee_audit(skeleton, building_tags, street_graph, seed). Mandatory-check gate keys on ComplexityTier (T1 all-inhabited; T2/T3 Full) -- D-097 wording fixed. Each check is a graph/geometry predicate over tags + the MST arterial graph: chokepoint = articulation point; encounter_corridor = Public-node BFS crossing the district; A-1 LOS = 2D footprint occlusion; A-2 = unique perimeter street edges >= 2; A-4 = path avoiding institutional buildings. social_hub eligibility = a social_hub_eligible flag added to the zone-type RONs (D-142). Regenerate-on-fail: MAX_RETRIES const, bump the missing-guarantee zone weight, increment a SeedChain sub-key. Files: generator.rs, the audit module.', 'backlog', 'medium', NULL, 'server', 'D-097', '2026-05-25 19:08:59', '2026-05-25 19:08:59', NULL, '0ba4e7f6ed3dd2b5a5032f04afbfc95d', 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 ('06FB0TNSRYE43XRXRWS6GZK4PW', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'DoorSpec/InteriorDescriptor + condition overlay (D-231, D-198)', '(a) DoorSpec/InteriorDescriptor structs on the building tag (D-231): the step3->step4 boundary descriptor + the COMPLETE Phase-6 interior seed (zone_type_id, entry_class, floor_extent, era, flavor_ref, prosperity, layout_mode). Door-count derivation (Main always; Service/Emergency/Hidden by condition) + initial-state derivation (Public->Open, Commercial->TemporalWindow, Restricted->Locked, BreachOnly->Sealed) + mutator semantics (initial state frozen-amber, runtime changes are tile mutators). The interior FILL is Phase 6 (D-166) -- OUT OF SCOPE; only the descriptor lands here. (b) Condition overlay (D-198 two-pass amendment): BuildingConditionState{New|Maintained|Worn|Derelict|Abandoned}, OccupancyState{Full|Partial|Vacant}, VegetationEncroachment -- a SEPARATE Bevy system triggered by EconEvent (D-180), painting OVER the frozen structural fill, feeding D-100 DamageOverlay. Hard wall: overlay cannot change a BuildingTag; fill_chunk holds no PressureState reference.
|
||
|
||
Refinement (2026-05-26): READY behind 1006. Phase-4 scope = DoorSpec/InteriorDescriptor structs (defined in 1006) + derivation here; interior FILL is Phase-6, OUT of scope. Door-count: Main always; Service if logistical zone; Emergency if >=2 floors; Hidden seeded by zone (research 60/admin 20/res 5). Initial state: Public -> Open or Closed (zone decides: market Open, civic Closed); Commercial -> TemporalWindow; Restricted -> Locked + credential; BreachOnly -> Sealed. Mutations via ChunkMutations/TileOverride (exist). Condition overlay = a SEPARATE Bevy system on EconEvent (D-180), painting BuildingConditionState/OccupancyState/VegetationEncroachment (sub-biome whitelist: TropicalWet, TemperateForest, Wetland, Boreal, Savanna) over the frozen fill; refresh on EconEvent + daily. Condition is its OWN overlay layer; it does NOT feed D-100 physical-damage types (no D-100 change). Hard wall: condition system imports nothing from econ_sim::model and holds no PressureState. Files: generator.rs, economy_plugin.rs, econ-sim/src/events.rs.', 'backlog', 'medium', NULL, 'server', 'D-231', '2026-05-25 19:09:04', '2026-05-25 19:09:04', NULL, 'c1d1dd65cd217f7d6559eaac978bb2cb', 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 ('06FB0TNSRX3R6G3Y7QR4FAJPNM', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Wiki to Atlas content-set consolidation (Q-107, blocked)', 'Consolidate all wiki content (pages + heightmaps + markers + architecture-flavor) into one first-class, baked Atlas/gamedata content set with a unified bake pipeline -- instead of per-feature file conventions. Resolves where authored per-body content lives (the D-232 flavor source). BLOCKED on Q-107 (open question -- the target tree structure must be decided first). The generator-facing trait_templates + atlas_body_trait_bias tables (D-232) is invariant to this, so it does NOT block the fill seam; sequence this AFTER the fill-seam work. Jeroen: ''the wiki needs to become part of the atlas content set ... not yet another hack.''', 'backlog', 'low', NULL, 'server', 'Q-107', '2026-05-25 19:09:10', '2026-05-25 19:09:10', NULL, '4d26cd6fe611953dee1419ed91f68db0', 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 ('06FB0TNSRZQKSQQQ1T5Q696AAM', 'task', '06FB0TNSRWN78KNTHMER9HN7QR', 'BulkClass + ProductionUbiquity enums + D-184 bulk_class backfill + dominant-commodity lookup', 'Define BulkClass{BulkSolid|BulkLiquid|PrecisionDense|Perishable|NonPhysical} + ProductionUbiquity{Ubiquitous|Common|Specialist|MonopolySource}; back-fill D-184 bulk_class values; build-time lookup of the settlement dominant commodity from the systems.db catalog. Seed-independent.
|
||
|
||
Round-3 batch refinement (2026-05-26): also define the MorphologyZone enum here (closed set: Fjord, Canyon, Delta, AlluvialPlain, Island, MountainPass, Coastal, Lake, Sea, OpenOcean, MeanderReach, Other) -- it had no home and 954/976/1005 all need it. bulk_class is the 8->5 PROJECTION (size variants bulk/standard/compact/oversized -> BulkSolid; precision -> PrecisionDense; the 8 stay on commodities). Note: the bare enum/struct type DEFS now live in the foundational types task; 982 owns the projection + dominant-commodity DERIVATION logic (derived from highest-output location-bound production chain, D-178, not an authored role->commodity table).', 'in_progress', 'medium', NULL, 'server', 'D-233', '2026-05-25 19:11:05', '2026-05-25 19:11:05', NULL, '87bb3ddec0d73895d9b3d8d91cd69720', 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 ('06FB0TNSRYAE6MPE7720360WM4', 'task', '06FB0TNSRZKXHAYMT7Q6WW3XDC', 'FillChunk shell derivation <5ms (Void/Wall/FloorSlab/Roof from cached tags)', 'On-demand derive phase: read cached DistrictWorldState; per tag, shell_derive(seed, footprint, extent, z) -> Void|Wall|FloorSlab|Roof per voxel. Pre-condition: only after SkeletonGenerated; re-enqueue High if block_tags absent. Budget ~0.4-0.6ms/chunk.', 'backlog', 'high', NULL, 'server', 'D-230', '2026-05-25 19:11:17', '2026-05-25 19:11:17', NULL, '9b655956f25c1fe8db565bc46365621e', 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 ('06FB0TNSRZWSSHC2S5KPKAZ5QR', 'task', '06FB0TNSRZKXHAYMT7Q6WW3XDC', 'BuildingExteriorTag visual grammar + material vocabulary (template-filtered)', '(architecture_flavor x zone_type x era x density) -> BuildingExteriorTag{wall_material, roof_form, setback_tier, facade_rhythm, color_range}. Vocabulary: WallMaterial/RoofForm/FacadeRhythm/StreetSurface (extends D-228 FloorMaterial). 4-step derivation: flavor filter -> zone bias -> era restrict -> density setback -> interstitial type. Color flavor-bounded/era-adjusted/seed-selected.', 'backlog', 'medium', NULL, 'server', 'D-235', '2026-05-25 19:11:19', '2026-05-25 19:11:19', NULL, 'aec76699fda238b1eb3f25cba09d5dad', 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 ('06FB0TNSRX65YFYFR5RNCM9MCG', 'task', '06FB0TNSRWMZBFV1V6F79VW8S4', 'Gemma architecture-flavor methodology doc (stage1 register + stage2 structured)', 'Methodology doc analogous to the D-223 naming one: stage-1 register selection from wiki prose, stage-2 structured output {tag, allow, block, weight, trauma_decay_rate}. Defines the Gemma prompt + review at GTTR/wiki authoring.
|
||
|
||
Round 3 reframe: Gemma is a BOUNDED corpus-distillation pass (one read of all wiki -> propose catalog templates -> human-gated), NOT per-body open-vocab generation. Plus core catalog hand-authoring (Miri = cultural meaning + eligibility; Araminta = matching visual_bundle).
|
||
|
||
Round-3 refinement (2026-05-26): reframed as a FOLLOW-ON extension, not a blocker of the core catalog (1005). Runs AFTER the core hand-authored set exists, to propose additional templates (corpus-distillation, human-gated) toward the 40-45 target. Needs an architecture-flavor Gemma methodology doc (analogous to the naming one) defining the extraction prompt + structured output schema + human-review gate.', 'backlog', 'high', NULL, 'server', 'D-232', '2026-05-25 19:11:41', '2026-05-25 19:11:41', NULL, '935730c5e5b666270ff9fe4fb6b66f9d', 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 ('06FB0TNSRWYHR72SC80F5T0TBW', 'task', '06FB0TNSRWMZBFV1V6F79VW8S4', 'allow/block weighted filter at chunk fill over zone-type ObjectTag pool', 'Apply the flavor profile as a filter over the D-142 zone-type ObjectTag baseline pool: block removed, allow weighted up by weight; dominant wins categorical, weighted-avg continuous. Three-layer: body x district x era-band (depth Q-106).
|
||
|
||
Round 3: this becomes the THREE-PHASE DRAW (body K-draw [K=5/3/1/0 by complexity_tier, SeedChain, coverage-aware] -> district-dominant by zone_affinity -> within-template seed picks) + CI guardrails, per D-232 — not a flat per-body allow/block filter.', 'backlog', 'medium', NULL, 'server', 'D-232', '2026-05-25 19:11:45', '2026-05-25 19:11:45', NULL, '1cd82e145b9ba727f0e925ab6d8098f1', 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 ('06FB0TNSRZCG08B0P6PRNQV8KG', 'task', '06FB0TNSRWMZBFV1V6F79VW8S4', 'ObjectTag vocabulary authoring (Miri + Araminta co-maintenance)', 'Author the ObjectTag + exterior-material vocabulary the allow/block lists and D-235 grammar reference. Carried over from the retired generator-arch D-READY-9 requirement. Content task, Miri + Araminta.', 'backlog', 'medium', NULL, 'server', 'D-232', '2026-05-25 19:11:47', '2026-05-25 19:11:47', NULL, '391f6f2d578a8849fcd99e8a3b4d331b', 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 ('06FB0TNSRYRD6NSYM5WEMTP76C', 'task', '06FB0TNSRWABYYB11QMJDTXE2G', 'Guarantee-audit T1/T2 checks over building_tags + street_graph', 'Tier-1 (social_hub/informal_zone/encounter_corridor) + Tier-2 (chokepoint/institutional/insider/economic_node/breach_only) checks as graph/geometry queries over the step-3 tags + street graph. Populate GuaranteeAuditResult.', 'backlog', 'medium', NULL, 'server', 'D-097', '2026-05-25 19:11:49', '2026-05-25 19:11:49', NULL, '7a004fc18d209e17daf4f756d670c703', 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 ('06FB0TNSRW3PYHX4XH6T073SFC', 'task', '06FB0TNSRWABYYB11QMJDTXE2G', 'A-1..A-4 assassin-lens graph queries + regenerate-on-fail', 'A-1 elevated vantage (above_ground>=3 + LOS to chokepoint), A-2 egress multiplicity, A-3 temporal opacity (TemporalWindow door), A-4 non-institutional route. On mandatory-check fail for world_tier, regenerate fill with adjusted params.', 'backlog', 'medium', NULL, 'server', 'D-097', '2026-05-25 19:11:51', '2026-05-25 19:11:51', NULL, '74f34b6823765ba8c9fab36cdf7af55a', 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 ('06FB0TNSRZEP916TCXCDYNSVS0', 'task', '06FB0TNSRYE43XRXRWS6GZK4PW', 'DoorSpec/InteriorDescriptor structs + door-count/initial-state derivation', 'Structs on the building tag: the step3->step4 boundary + complete Phase-6 interior seed. Door-count (Main always; Service/Emergency/Hidden by condition), initial-state (Public/Commercial/Restricted/BreachOnly), mutator semantics. Interior FILL is Phase 6 -- out of scope; only the descriptor lands.', 'backlog', 'medium', NULL, 'server', 'D-231', '2026-05-25 19:11:53', '2026-05-25 19:11:53', NULL, 'ce38a6668094af5647318ef1df1867f4', 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 ('06FB0TNSRZNMBYYABFVTD36XEC', 'task', '06FB0TNSRYBG3M83M5JB4WD4NC', 'Backfill economic_tier (~97% NULL) + normalize economic_role 5 spellings', 'economic_tier NULL on ~97% of systems (gates D-199 context); economic_role has 5 variant spellings -- normalize to one canonical set. Source-canonical + regen-db.
|
||
|
||
Scope narrow (2026-05-26, /whats-next activation): economic_tier deferred to follow-up ticket #1007 (no derivation formula, not D-199-required, does not gate the cascade). This ticket now scopes to: role normalization (ALREADY in MIGRATION_SQL at import_economics.py:354-360 + validator at 859-880) -> run make regen-db, run make check-systems-db, verify with SELECT DISTINCT economic_role from bodies. Essentially a regen-and-verify task once #1000 founding_age is also in place.', 'done', 'high', NULL, 'server', NULL, '2026-05-25 19:11:58', '2026-05-25 19:11:58', NULL, '5babf9f3659347e38ef2d1dc406a2aa6', 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 ('06FB0TNSRWRCFA6P4HYWDN1XA0', 'task', '06FB0TNSRYBG3M83M5JB4WD4NC', 'Backfill behavioral_archetype', 'behavioral_archetype mostly NULL across bodies. Source-canonical + regen-db. Lower urgency than founding_age/economic_tier but needed before NPC-adjacent generation.', 'backlog', 'medium', NULL, 'server', NULL, '2026-05-25 19:11:59', '2026-05-25 19:11:59', NULL, '698384aa3d522f3f5d0b89fa0dfbe254', 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 ('06FB0TNSRWGDT3AJJE5QD0E3FR', 'task', '06FB0TNSRWMZBFV1V6F79VW8S4', 'Deviation/swerve system — closed-default + rare per-building wildcard', 'Closed vocabulary by default; a rare per-building wildcard draws a COHERENT whole foreign template (cultural-only — function still passes economic hard gates; never an axis-scramble). Two OPPOSED active drivers: foreign-import (another corridor) scaled UP by cosmopolitanism/centrality/transit/Epicenter tier; heritage-callback (the body''s own corridor heritage sub-pool) scaled UP by remoteness/isolation/conservatism. Passive past-vogue holdover from age (D-217 wear). Sparsity escape-hatch = the SAME mechanism triggered by necessity when the closed vocabulary cannot serve a district. Per D-232.', 'backlog', 'medium', NULL, 'server', 'D-232', '2026-05-25 20:36:39', '2026-05-25 20:36:39', NULL, '73394310a19c07ce43327e7de3b2c857', 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 ('06FB0TNSRZNNMZPXSEZ7HN778R', 'task', '06FB0TNSRWMZBFV1V6F79VW8S4', 'Visual-asset fallback hierarchy (specific->generic tokens, patch-upgradable)', 'Every specific texture/material token declares a generic parent it degrades to: temple_wall_wood -> generic wood_wall placeholder until the specific asset ships, then it upgrades IN PLACE. The logical token a building uses is fixed + deterministic at generation (frozen world); only render fidelity is incremental. This is where patched-in themes/textures live -> NO catalog versioning needed for art (versioning only re-enters if a NEW logical template is added post-launch). Per D-232 + D-235. Cross-refs ticket 988 (exterior visual grammar).', 'backlog', 'medium', NULL, 'server', 'D-235', '2026-05-25 20:36:42', '2026-05-25 20:36:42', NULL, '3d1c1768ec730de7795b334ec1920399', 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 ('06FB0TNSRZGAEWEXJEYRAWX4K4', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Foundation — define all D-229/D-230/D-231/D-233 shared Rust types + struct plumbing (single PR)', 'Consolidates the type-definition layer every downstream fill-seam ticket waits on (the most-repeated refinement gap). One PR that compiles with stubs/defaults, then the logic tickets fill behavior. Defines: BuildingPropertyTag, FloorExtent + FloorHeightProfile (with floor_at_voxel_z / voxel_range_for_floor, resolving Q-104), BuildingEntryClass (Public|Commercial|Restricted|BreachOnly), ConstructionEra, ZoneTypeId (Box<str>), the enums MorphologyZone / BulkClass(5) / ProductionUbiquity, DoorSpec + InteriorDescriptor structs, DistrictWorldState. Struct plumbing: add fields to CityGenerationContext (morphology_zone, trait_selection, dominant_bulk_class, dominant_production_ubiquity), add block_tags-bearing DistrictWorldState to BodyWorldState.districts, and FIX GenCompletion::SkeletonGenerated to carry DistrictWorldState (+ body_id) not just city_id. AccessTier collision: the existing 5-variant spatial AccessTier in generator.rs is RENAMED ZoneAccessTier (FloorZone/VerticalCorridorSpec); BuildingEntryClass is the new per-building-exterior type. Logic (projection/derivation/draw/fill) stays in 982/983/984/985/998 etc., which build ON these types.', 'done', 'high', NULL, 'server', 'D-229', '2026-05-26 18:13:15', '2026-05-28 21:07:48', NULL, '35e2a4e8ff6fa989cd9f9ddcf9bcb98b', 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 ('06FB0TNSRXR8C67AF3RRDXD43G', 'task', '06FB0TNSRYBG3M83M5JB4WD4NC', 'Backfill founding_age_years for 273 inhabited bodies (source-canonical)', 'founding_age_years NULL on all 273 inhabited bodies -- gates ConstructionEra (D-229) + block irregularity (D-216). Edit the TOML/JSON sources + regen-db; never direct-write systems.db.
|
||
|
||
Refinement (2026-05-26): EVENTS-FIRST derivation, not pure wave-table (avoids double bookkeeping with the existing per-system historical_events.age_years authored data, e.g. Van Maanen 180yr). MIGRATION_SQL block in import_economics.py: bodies.founding_age_years = COALESCE((SELECT age_years FROM historical_events WHERE system_id = bodies.system_id AND event_type IN (founding,first_settlement,colonization) ORDER BY sort_order LIMIT 1), wave_fallback(settlement_wave)). Canonical wave fallback (founding-edge per lore): wave_1=600, wave_2=500, wave_3=300, wave_4=100, wave_5=40. EXCLUDE Sol bodies entirely: settlement_wave=origin -> NULL (Sol is out of player scope, Atlas highest-level only, deeper Sol is future DLC). Source-canonical + regen-db.
|
||
|
||
---
|
||
Refinement (2026-05-30, /whats-next — resolves Si GAPS): EVENTS-FIRST branch uses the REAL authored founding event, not the fictional vocabulary. The named types (founding/first_settlement/colonization) match ZERO rows in historical_events; the actual founding event is event_type=\"colonial_charter\" (9 systems, age_years 480-600, aligns with wave band). civilizational_origin (12900yr = cosmic Earth origin) MUST be excluded. MIGRATION_SQL: bodies.founding_age_years = COALESCE((SELECT age_years FROM historical_events WHERE system_id=bodies.system_id AND event_type=\"colonial_charter\" LIMIT 1), CASE sh.settlement_wave WHEN \"wave_1\" THEN 600 WHEN \"wave_2\" THEN 500 WHEN \"wave_3\" THEN 300 WHEN \"wave_4\" THEN 100 WHEN \"wave_5\" THEN 40 END) -- joined to system_history sh. sort_order NOTE: sort_order=0=MOST RECENT, so do NOT ORDER BY sort_order to pick founding; filter by event_type instead. EXCLUDE settlement_wave IN (\"origin\",\"unsettled\") -> stays NULL (origin=Sol out of player scope per D-236; unsettled=24 systems, literally not settled). Source-canonical: add the UPDATE to MIGRATION_SQL in tooling/economy-db/import_economics.py, then make regen-db; never direct-write systems.db.', 'done', 'high', NULL, 'server', NULL, '2026-05-25 19:11:56', '2026-05-28 21:07:49', NULL, '560431f062525b4aa54f32b24c07f023', 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 ('06FB0TNSRXHDQ0VGR9YHTXWNRW', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Deferred: economic_tier derivation formula (not D-199-required; post-cascade)', 'Split out of #1001 during /whats-next refinement: economic_tier has no derivation formula in any D-record and is NOT one of D-199''s 6 required generation-context fields, so it does not gate the Phase-4 cascade. Defer until either (a) a derivation formula is decided (likely a population-bracketed map: <100K=1, 100K-1M=2, 1M-10M=3, >10M=4, or similar — needs design) OR (b) economic_tier earns a use case in the rolling sim. Live state: ~97pct NULL in system_economy. Not blocking #1001''s role-normalization work.', 'backlog', 'low', NULL, 'server', NULL, '2026-05-28 21:07:54', '2026-05-28 21:07:54', NULL, '1bd3e30f5bcb7fb536cce01ce8e77448', 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 ('06FB0TNSRWW7NX8R77SZ7QHTZG', 'epic', '06FB0TNSRZXCHGS16BFHSSGSV4', 'System economic specialization — authored identity layer (D-237)', 'Authored per-system identity layer: three fields (economic_specialization, cultural_specialization, dominant_faction) sourced from wiki/economics/system_specialization.toml, imported via import_economics.py, consumed by city_context_reader.rs. Authored lore wins; deterministic-varied heuristic fallback for unnamed systems. Outcome: Layer 2 generation reads GTTR-consistent system identity rather than a role+planet_class guess.
|
||
|
||
Decisions: D-237 (new — authored specialization layer schema + vocabulary + fallback algorithm); D-233 re-amended (authored field is primary driver for BulkClass x ProductionUbiquity; heuristic is fallback); D-199 amended (economic_specialization + cultural_specialization added to read-set); D-232 noted (cultural_specialization drives template pool selection); D-214 noted (authored dominant_faction is primary PoliticalArchetype input).
|
||
|
||
Workshop: docs/workshops/system-economic-specialization/ (all rounds + outcomes).', 'backlog', 'high', NULL, 'server', 'D-237', '2026-05-31 16:12:18', '2026-05-31 16:12:18', NULL, '24ad9884fbd51fb3ac70220a46342fdf', 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 ('06FB0TNSRWT2P54ZBNMZB4N9F4', 'task', '06FB0TNSRWW7NX8R77SZ7QHTZG', 'city_context_reader.rs: authored-primary + deterministic-varied fallback for all 3 specialization fields', 'Wire all three authored specialization fields into CityGenerationContext, with authored value as primary and deterministic-varied heuristic as fallback.
|
||
|
||
economic_specialization:
|
||
Non-null -> look up in specialization_vocabulary -> read bulk_class_projected + production_ubiquity_projected -> populate CityGenerationContext.dominant_bulk_class / dominant_production_ubiquity.
|
||
Null -> deterministic-varied fallback (integer basis points only, D-010):
|
||
candidate_weights: Map<specialization_id, u64>
|
||
for primary role candidates: += 8_000 bps
|
||
for secondary role candidates: += 3_000 bps
|
||
for each corp HQ in corp_presence: += 5_000 bps (map corp specialization -> vocab id)
|
||
for every vocabulary id: += 400 bps // noise term; ~5% off-primary draw across 200 unnamed systems
|
||
seed = SeedChain::root(world_seed).derive(SeedDomain::Layer1System, fnv1a_64(system_id)).seed()
|
||
weighted draw sorted alphabetically by spec_id (deterministic order)
|
||
ROLE_SPEC_MAP table: see burnelli-sheldon-round3.md §(d).
|
||
This replaces the #982 dominant-commodity derivation as PRIMARY; #982 output becomes fallback path.
|
||
|
||
cultural_specialization:
|
||
Non-null -> pass to D-232 template-pool selection (boost matching templates, dampen corridor default for divergent-heritage systems).
|
||
Null -> corridor assignment already in D-232 algorithm; no action needed.
|
||
|
||
dominant_faction:
|
||
Non-null (authored in system_factions) -> direct input to D-214 PoliticalArchetype (authored wins).
|
||
Null -> Paula''s hop/currency fallback: hop 0-5 -> concord_assembly; west_reach hop 6+ mark_primary -> compact; west_reach hop 5-6 mixed -> compact_sympathetic; hop 7+ other corridors -> independent; Tier-1 monopolist corp HQ -> syndic_dominant (flagged). Full table: paula-round3.md §2.
|
||
D-172/D-174 wiring: authored dominant_faction is the primary input; existing validation unchanged.', 'backlog', 'high', NULL, 'server', 'D-237', '2026-05-31 16:13:29', '2026-05-31 16:13:29', NULL, '92c6bd12e99a15b04789708c4f9b8990', 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 ('06FB0TNSRWRPJSYVRAG7GJBXAR', 'task', '06FB0TNSRWW7NX8R77SZ7QHTZG', 'settlement_pattern → subsurface/domed/enclosed morphology branch in D-233/D-237 fill', 'The economic-built-world fill model (D-233, re-amended by D-237) is a surface model (roofed-coverage fraction, operations-surface remainder, concentrate-vs-scatter on open ground). bodies.settlement_pattern carries non-surface morphologies (underground_concentrated e.g. Vuurkloof/GJ35c, cave, domed, underground_complex) that nothing in the chain currently reads — not in D-199 read-set, not in city_context_reader, not branched in skeleton_gen. Engine primitives exist (D-110 signed base_z, UndergroundComplex reservation, D-106 vertical scale) but no morphology switch connects settlement_pattern to the built-world layer, so enclosed-habitat bodies would generate as surface towns, contradicting lore. SCOPE: (1) add settlement_pattern to the D-199 read-set + city_context_reader; (2) add a surface-vs-enclosed branch to the D-233/D-237 fill (enclosed coverage/vocabulary reinterpretation); (3) amend D-233/D-237 records accordingly. BLOCKED ON Q-108 debate (subterranean/domed/sealed-habitat morphology design) — do not implement before that resolves. Surfaced via Vuurkloof (GJ 35) in the system-economic-specialization workshop.', 'backlog', 'medium', NULL, 'server', 'Q-108', '2026-05-31 17:07:55', '2026-05-31 17:07:55', NULL, '7a352d069d5dbc3dfb939caccb11765f', 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 ('06FB0TNSRXAXB5DEYTVABX211G', 'task', '06FB0TNSRWW7NX8R77SZ7QHTZG', 'Write D-237 + re-amend D-233, amend D-199 / D-232 / D-214', 'Write the new D-237 record to decisions/architecture.md using Burnelli''s draft from docs/workshops/system-economic-specialization/burnelli-sheldon-round3.md §(f). D-237 covers: 3-field schema, 27-value economic vocabulary, unified cultural_specialization vocabulary (12 activity + 9+ heritage values), deterministic-varied fallback algorithm, Groombridge landmark mechanism note.
|
||
|
||
Also apply these amendments:
|
||
- D-233 re-amendment: authored economic_specialization is now the primary driver for (dominant_bulk_class, dominant_production_ubiquity) in CityGenerationContext; heuristic fallback for NULL.
|
||
- D-199 amendment: add economic_specialization and cultural_specialization to the minimum read set (dominant_faction was already field 4).
|
||
- D-232 note: cultural_specialization (system_economy) is a template-pool selection signal — non-null directs which cultural tradition pool D-232 draws from; null = corridor assignment stands.
|
||
- D-214 note: dominant_faction authored values (8-value vocabulary) are the primary PoliticalArchetype input; hop/currency heuristic is fallback.
|
||
- D-237 note on Groombridge landmark mechanism: singular MonopolySource-class institution within a Specialist district → encode district as Specialist in vocabulary + D-222 multi-block reservation + D-232 atlas_body_trait_bias hero pin; not a composite vocabulary value.
|
||
|
||
Source material: burnelli-sheldon-round3.md §(f) has complete draft text. Slot in D-237 (already claimed). No new D-records needed beyond D-237.', 'done', 'high', NULL, 'server', 'D-237', '2026-05-31 16:12:34', '2026-05-31 17:33:45', NULL, '01132691e298c894ae015831d15e4f1a', 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 ('06FB0TNSRW54ARBAGAMDACG9CR', 'task', '06FB0TNSRWW7NX8R77SZ7QHTZG', 'Schema: economic_specialization + cultural_specialization columns + specialization_vocabulary table', 'Add two new columns to system_economy and create the specialization_vocabulary table.
|
||
|
||
systems-schema.sql changes:
|
||
ALTER TABLE system_economy ADD COLUMN economic_specialization TEXT;
|
||
ALTER TABLE system_economy ADD COLUMN cultural_specialization TEXT;
|
||
-- cultural_specialization avoids collision with system_culture.cultural_register (NPC-voice, wiki_sync.py pipeline, untouched)
|
||
|
||
CREATE TABLE IF NOT EXISTS specialization_vocabulary (
|
||
specialization_id TEXT PRIMARY KEY,
|
||
commodity_id TEXT NOT NULL REFERENCES commodities(commodity_id),
|
||
production_ubiquity_override TEXT, -- NULL = use catalog default
|
||
bulk_class_projected TEXT NOT NULL, -- pre-computed BulkClass for D-233
|
||
production_ubiquity_projected TEXT NOT NULL, -- pre-computed ProductionUbiquity
|
||
description TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_spec_vocab_commodity ON specialization_vocabulary(commodity_id);
|
||
|
||
import_economics.py changes:
|
||
Add both ALTER TABLE statements to COLUMN_MIGRATIONS list (idempotent).
|
||
Add CREATE TABLE IF NOT EXISTS specialization_vocabulary to MIGRATION_SQL block.
|
||
|
||
IMPORTANT: system_factions.dominant_faction ALREADY EXISTS as a column (confirmed in schema). Zero schema change for dominant_faction — the import step only upserts authored values. Do not add a new column.
|
||
|
||
Cultural vocabulary validation is a string-list check in CI code — no separate DB table needed for cultural_specialization values.
|
||
|
||
---
|
||
Refinement (Si, 2026-05-31): READY. Confirmed: system_economy at systems-schema.sql L94; dominant_faction exists L108 (populate-only); commodities PK L254 (FK valid); COLUMN_MIGRATIONS + MIGRATION_SQL idempotent patterns present in import_economics.py. Add the 2 cols INSIDE the system_economy CREATE TABLE block (not ALTER) for fresh builds, AND as COLUMN_MIGRATIONS ALTER entries for existing DBs; add specialization_vocabulary CREATE TABLE to MIGRATION_SQL. check-systems-db-stamp GENERATOR_SOURCES untouched here (belongs to #1013).', 'done', 'high', NULL, 'server', 'D-237', '2026-05-31 16:12:44', '2026-05-31 18:51:38', NULL, '4e1b63c53f89cca0c3b4827a834f2c69', 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 ('06FB0TNSRY7PQPSX5C4HNCNVYG', 'task', '06FB0TNSRWW7NX8R77SZ7QHTZG', 'Source TOMLs: specialization_vocabulary.toml (27 values) + system_specialization.toml (hero-system seeds)', 'Create two new source files consumed by import_economics.py.
|
||
|
||
wiki/economics/specialization_vocabulary.toml — 27 economic values:
|
||
Burnelli''s 26-value list from burnelli-sheldon-round3.md §(b) (agricultural x5, energy x2, extraction x5, manufacturing x6, high-tech x1, services x7) plus Miri''s addition: research_station (commission_certification, concentrated -> NonPhysical x Specialist, for Keid).
|
||
Merge resolutions applied: marine_farming absorbed into terroir_organics; military_production + military_station -> military_industrial; specialist_manufacturing -> precision_tech (identical D-233 output); alloy_hub absorbed into general_industrial.
|
||
Each entry: specialization_id, commodity_id, production_ubiquity_override (null = catalog default), bulk_class_projected, production_ubiquity_projected, description.
|
||
|
||
wiki/economics/system_specialization.toml — ~28 hero-system entries (seed for full content pass):
|
||
Format:
|
||
[GJ-144] # Ran
|
||
economic_specialization = ''breadbasket''
|
||
cultural_specialization = ''terroir_heritage''
|
||
dominant_faction = ''concord_assembly''
|
||
Use merged vocabulary labels from specialization_vocabulary.toml (not Miri''s pre-merge Round 3 labels).
|
||
Hero systems: Ran, Cygni B, Sindri, Nova Roma, Renaissance, Groombridge, Prometheus, ACB, Tessera, Sirius, Parallax, Gateway, Wolf 359, Vuurkloof, Keid, Bastion, Arbour, Lu Ban, Calloway Reach, Confluent/VGV, Braemar, Nyrheim, Ostmark, Dagat, Altmark, Dai Lo, Zenzele + east-reach lattice anchor (GJ TBD).
|
||
|
||
CONFLICT to resolve before committing Vuurkloof: Miri says dominant_faction=independent (GTTR engineering community), Paula says concord_assembly (south_reach hop-6 default). Verify against docs/workshops/system-economic-specialization/workshop-outcomes.md.
|
||
|
||
cultural_specialization accepts both activity-type values (scholarly, agrarian, industrial_heritage, etc.) and heritage-type values (scottish, vietnamese, afrikaans_cape, zulu, chinese, italian_northern, tagalog, norse_compact, french_provencal, etc.). Heritage takes precedence when both apply. Full combined vocabulary list in miri-round3.md §2.
|
||
|
||
---
|
||
Refinement (Si + lead, 2026-05-31): GAP1 RESOLVED — TOML stanza keys use SPACE format [GJ 35], not hyphen [GJ-35]; every wiki/economics TOML + the star_systems PK use spaces (the workshop §1 example was illustrative/wrong). GAP3 RESOLVED — keep lattice_material_source in specialization_vocabulary.toml with NO system stanza yet (east-reach anchor GJ pin is a content-pass item, documented-intentional). GAP2 VUURKLOOF (GJ 35) — author dominant_faction = independent as a PROVISIONAL PLACEHOLDER; flagged OPEN for human decision: harshness/guild-self-governance leans independent vs Assembly wanting a strategic fusion-fuel source leans concord_assembly. Filed D-237 workshop-outcomes §7 currently says concord_assembly — left as-is pending the call; live TOML will carry independent + a # PROVISIONAL comment. Do not treat Vuurkloof faction as final.', 'done', 'high', NULL, 'server', 'D-237', '2026-05-31 16:13:02', '2026-05-31 18:51:38', NULL, 'fa5f97a82ff8dd593cd1f0b5dffd8e90', 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);
|