diff --git a/.pql/changelog/ticket_history/2026-07.sql b/.pql/changelog/ticket_history/2026-07.sql index 41f2ce707..a2468a061 100644 --- a/.pql/changelog/ticket_history/2026-07.sql +++ b/.pql/changelog/ticket_history/2026-07.sql @@ -3152,3 +3152,8 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSP3GEJYTA966BSSR9354YC4', 'status', 'backlog', 'in_progress', NULL, '2026-07-26 12:33:36', '2026-07-26 12:33:36.687', '2026-07-26 12:33:36.687', NULL, '5c62d31cdde3da8bba4160924929d6c7', 2) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSWCYA60VHFK44J09WW78FY0', 'assigned_to', NULL, 'dudley', NULL, '2026-07-26 12:33:41', '2026-07-26 12:33:41.592', '2026-07-26 12:33:41.592', NULL, 'c08a8b496d3a91055577832000605428', 2) ON CONFLICT(hash) DO NOTHING; INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSP3GEJYTA966BSSR9354YC4', 'assigned_to', NULL, 'stig', NULL, '2026-07-26 12:33:42', '2026-07-26 12:33:42.082', '2026-07-26 12:33:42.082', NULL, 'c401604d7344f97f2aaf943be53f48eb', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSP3GEJYTA966BSSR9354YC4', 'status', 'in_progress', 'review', NULL, '2026-07-26 12:46:59', '2026-07-26 12:46:59.992', '2026-07-26 12:46:59.992', NULL, 'f82201a615351e0dccc4a585bbdb32ee', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSWYQA1XKYKEQ114CZKEDAFW', 'description', 'test_fog_shader.gd::test_visibility_texture_update_performance asserts <0.5ms wall-clock and flaked TWICE on 2026-07-26 gate runs on the shared dev box (0.549ms during a heavily contended run racing live captures; 0.503ms — a 0.6% miss — during a lightly loaded run), passing 46/46 solo immediately after both times. A wall-clock assertion with sub-1% headroom cannot be trusted on a machine that runs cargo builds, godot imports, and live capture servers alongside gates — each flake costs a full gate re-run (~3-4 min plus diagnosis). Fix options, pick at pickup: (a) median-of-N (e.g. best-of-5 or median-of-9) sampling inside the test so a single scheduler hiccup cannot fail it — preferred, keeps the budget honest; (b) a modest budget raise with a comment recording the two incidents; (c) an environment-aware multiplier (worst option — hides regressions). Whatever lands must keep the test able to catch a REAL 2x regression. The companion test_full_fog_update_under_1ms has 2x the headroom and has never flaked — evidence the budget, not the code, is the problem. Gate logs: /tmp/sr-run-godot.638004.log (0.549), /tmp/sr-run-godot.1028571.log (0.503).', 'test_fog_shader.gd::test_visibility_texture_update_performance asserts <0.5ms wall-clock and flaked TWICE on 2026-07-26 gate runs on the shared dev box (0.549ms during a heavily contended run racing live captures; 0.503ms — a 0.6% miss — during a lightly loaded run), passing 46/46 solo immediately after both times. A wall-clock assertion with sub-1% headroom cannot be trusted on a machine that runs cargo builds, godot imports, and live capture servers alongside gates — each flake costs a full gate re-run (~3-4 min plus diagnosis). Fix options, pick at pickup: (a) median-of-N (e.g. best-of-5 or median-of-9) sampling inside the test so a single scheduler hiccup cannot fail it — preferred, keeps the budget honest; (b) a modest budget raise with a comment recording the two incidents; (c) an environment-aware multiplier (worst option — hides regressions). Whatever lands must keep the test able to catch a REAL 2x regression. The companion test_full_fog_update_under_1ms has 2x the headroom and has never flaked — evidence the budget, not the code, is the problem. Gate logs: /tmp/sr-run-godot.638004.log (0.549), /tmp/sr-run-godot.1028571.log (0.503). + +FIXED (2026-07-26, direct on main): the test already used median-of-5 (T-1092''s earlier mitigation) and still flaked three times in one day (0.549/0.503/0.638) when concurrent cargo builds inflated all five samples together. Superseded with MINIMUM-of-7: the assertion asks whether the CODE meets the D-059 budget, and load can only inflate wall time, never deflate it — the minimum is the least-noise estimator of code capability while a real regression shifts the minimum too. Budget unchanged at 0.5ms (regression-catching power preserved). Verified 46/46. Closing.', NULL, '2026-07-26 13:17:28', '2026-07-26 13:17:28.575', '2026-07-26 13:17:28.575', NULL, '130fa8e2d5fc4d4925eb0911c0dd8c21', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSWYQA1XKYKEQ114CZKEDAFW', 'status', 'backlog', 'done', NULL, '2026-07-26 13:17:35', '2026-07-26 13:17:35.790', '2026-07-26 13:17:35.790', NULL, '4320a9e32c27bc27bb28a71b3bf909ce', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/tickets/2026-07.sql b/.pql/changelog/tickets/2026-07.sql index a6c056d97..016e55061 100644 --- a/.pql/changelog/tickets/2026-07.sql +++ b/.pql/changelog/tickets/2026-07.sql @@ -5337,3 +5337,11 @@ INSERT INTO tickets (record_id, type, parent_record_id, title, description, stat INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FSP3GEJYTA966BSSR9354YC4', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Atlas header readout ghosted in Quarter capture — rung-transition alpha artifact', 'Araminta''s T-1196 secondary observation (first GJ1002b captures, 2026-07-25): the ''ATLAS - CAPARICA / QUARTER'' header readout above the legend rendered faded/ghosted in the Quarter frame (scratchpad t1196/gj1002b_quarter.png), while the District and Region frames from the same session and capture path rendered it fully legible. Suspect a z-order or alpha transition state caught mid-render on rung change (the capture settles on StepCanvasRequest.is_pending() then waits 2 frames — a header fade animation may outlast the data settle). Reproduce with a T-1157-harness jump_to capture at any Quarter rung and inspect header alpha across post-settle frames; if it is a fade animation racing the capture, decide whether the fix is harness-side (settle until animations idle) or UI-side (no fade on rung change). Likely cosmetic; the only frame of the three with a legibility defect.', 'in_progress', 'low', NULL, 'client', NULL, '2026-07-25 20:53:37.559', '2026-07-26 12:33:36.687', NULL, '61c09dcec6f2765796beb7a85fa45550', 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 ('06FSWCYA60VHFK44J09WW78FY0', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Synthetic-overflow settlement placement has no ocean-mask guard — can land in open water', 'Found during the PR #215 review fix round (T-1116, Tyre finding 3 follow-through): attractor_matching.rs::synthetic_attractor (the D-211 Phase-4 overflow path, PlainCenter at min-spacing) takes no heightmap/TerrainAnalysis argument — it derives positions by pure grid arithmetic (grid_h/2, grid_w/4, spacing-walk) with zero ocean_mask check. Every EXTRACTED attractor type is land-guaranteed (features.rs::extract_attractors filters !ocean_mask, D-209), but a synthetic-overflow settlement can be placed in open water — visible as an ocean-stranded settlement marker on the Atlas. T-1116''s routing relaxation degrades this case gracefully (surrogate anchor within ring 3, else an isolated unrouted node — never a panic or a water road), but the placement guarantee itself is the gap. Documented in road_graph.rs''s anchor comment and the D-210 amendment (PR #215). Fix shape: thread the ocean mask (or TerrainAnalysis) into synthetic_attractor and nudge/reject water candidates deterministically — mind D-211''s seed-derived-position promise (any nudge must be a pure function of seed + terrain, no RNG state change). Verify by hunting a real body whose synthetic overflow currently lands in water (none observed yet — GJ251c/GJ380c placements are all extracted attractors) or a synthetic fixture.', 'in_progress', 'medium', 'dudley', 'server', NULL, '2026-07-26 11:33:42.064', '2026-07-26 12:33:41.587', NULL, 'f5e116e6900eaad013ca4a2200586e35', 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 ('06FSP3GEJYTA966BSSR9354YC4', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Atlas header readout ghosted in Quarter capture — rung-transition alpha artifact', 'Araminta''s T-1196 secondary observation (first GJ1002b captures, 2026-07-25): the ''ATLAS - CAPARICA / QUARTER'' header readout above the legend rendered faded/ghosted in the Quarter frame (scratchpad t1196/gj1002b_quarter.png), while the District and Region frames from the same session and capture path rendered it fully legible. Suspect a z-order or alpha transition state caught mid-render on rung change (the capture settles on StepCanvasRequest.is_pending() then waits 2 frames — a header fade animation may outlast the data settle). Reproduce with a T-1157-harness jump_to capture at any Quarter rung and inspect header alpha across post-settle frames; if it is a fade animation racing the capture, decide whether the fix is harness-side (settle until animations idle) or UI-side (no fade on rung change). Likely cosmetic; the only frame of the three with a legibility defect.', 'in_progress', 'low', 'stig', 'client', NULL, '2026-07-25 20:53:37.559', '2026-07-26 12:33:42.081', NULL, '125ff7ed1722e7e21e2c98d8817c1d25', 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 ('06FSP3GEJYTA966BSSR9354YC4', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Atlas header readout ghosted in Quarter capture — rung-transition alpha artifact', 'Araminta''s T-1196 secondary observation (first GJ1002b captures, 2026-07-25): the ''ATLAS - CAPARICA / QUARTER'' header readout above the legend rendered faded/ghosted in the Quarter frame (scratchpad t1196/gj1002b_quarter.png), while the District and Region frames from the same session and capture path rendered it fully legible. Suspect a z-order or alpha transition state caught mid-render on rung change (the capture settles on StepCanvasRequest.is_pending() then waits 2 frames — a header fade animation may outlast the data settle). Reproduce with a T-1157-harness jump_to capture at any Quarter rung and inspect header alpha across post-settle frames; if it is a fade animation racing the capture, decide whether the fix is harness-side (settle until animations idle) or UI-side (no fade on rung change). Likely cosmetic; the only frame of the three with a legibility defect.', 'review', 'low', 'stig', 'client', NULL, '2026-07-25 20:53:37.559', '2026-07-26 12:46:59.991', NULL, 'c427777602f2f1ed6b898b6d172b913c', 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 ('06FSWYQA1XKYKEQ114CZKEDAFW', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Fog visibility-texture perf test flakes under machine load — 0.5ms budget has no headroom', 'test_fog_shader.gd::test_visibility_texture_update_performance asserts <0.5ms wall-clock and flaked TWICE on 2026-07-26 gate runs on the shared dev box (0.549ms during a heavily contended run racing live captures; 0.503ms — a 0.6% miss — during a lightly loaded run), passing 46/46 solo immediately after both times. A wall-clock assertion with sub-1% headroom cannot be trusted on a machine that runs cargo builds, godot imports, and live capture servers alongside gates — each flake costs a full gate re-run (~3-4 min plus diagnosis). Fix options, pick at pickup: (a) median-of-N (e.g. best-of-5 or median-of-9) sampling inside the test so a single scheduler hiccup cannot fail it — preferred, keeps the budget honest; (b) a modest budget raise with a comment recording the two incidents; (c) an environment-aware multiplier (worst option — hides regressions). Whatever lands must keep the test able to catch a REAL 2x regression. The companion test_full_fog_update_under_1ms has 2x the headroom and has never flaked — evidence the budget, not the code, is the problem. Gate logs: /tmp/sr-run-godot.638004.log (0.549), /tmp/sr-run-godot.1028571.log (0.503).', 'backlog', 'medium', NULL, 'client', NULL, '2026-07-26 12:51:23.279', '2026-07-26 12:51:23.279', NULL, '0d7374a5cdc7058a66e734fdaaf246db', 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 ('06FSWYQA1XKYKEQ114CZKEDAFW', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Fog visibility-texture perf test flakes under machine load — 0.5ms budget has no headroom', 'test_fog_shader.gd::test_visibility_texture_update_performance asserts <0.5ms wall-clock and flaked TWICE on 2026-07-26 gate runs on the shared dev box (0.549ms during a heavily contended run racing live captures; 0.503ms — a 0.6% miss — during a lightly loaded run), passing 46/46 solo immediately after both times. A wall-clock assertion with sub-1% headroom cannot be trusted on a machine that runs cargo builds, godot imports, and live capture servers alongside gates — each flake costs a full gate re-run (~3-4 min plus diagnosis). Fix options, pick at pickup: (a) median-of-N (e.g. best-of-5 or median-of-9) sampling inside the test so a single scheduler hiccup cannot fail it — preferred, keeps the budget honest; (b) a modest budget raise with a comment recording the two incidents; (c) an environment-aware multiplier (worst option — hides regressions). Whatever lands must keep the test able to catch a REAL 2x regression. The companion test_full_fog_update_under_1ms has 2x the headroom and has never flaked — evidence the budget, not the code, is the problem. Gate logs: /tmp/sr-run-godot.638004.log (0.549), /tmp/sr-run-godot.1028571.log (0.503). + +FIXED (2026-07-26, direct on main): the test already used median-of-5 (T-1092''s earlier mitigation) and still flaked three times in one day (0.549/0.503/0.638) when concurrent cargo builds inflated all five samples together. Superseded with MINIMUM-of-7: the assertion asks whether the CODE meets the D-059 budget, and load can only inflate wall time, never deflate it — the minimum is the least-noise estimator of code capability while a real regression shifts the minimum too. Budget unchanged at 0.5ms (regression-catching power preserved). Verified 46/46. Closing.', 'backlog', 'medium', NULL, 'client', NULL, '2026-07-26 12:51:23.279', '2026-07-26 13:17:28.575', NULL, '6095c1a7e7642d50530d6389f5833a48', 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 ('06FSWYQA1XKYKEQ114CZKEDAFW', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Fog visibility-texture perf test flakes under machine load — 0.5ms budget has no headroom', 'test_fog_shader.gd::test_visibility_texture_update_performance asserts <0.5ms wall-clock and flaked TWICE on 2026-07-26 gate runs on the shared dev box (0.549ms during a heavily contended run racing live captures; 0.503ms — a 0.6% miss — during a lightly loaded run), passing 46/46 solo immediately after both times. A wall-clock assertion with sub-1% headroom cannot be trusted on a machine that runs cargo builds, godot imports, and live capture servers alongside gates — each flake costs a full gate re-run (~3-4 min plus diagnosis). Fix options, pick at pickup: (a) median-of-N (e.g. best-of-5 or median-of-9) sampling inside the test so a single scheduler hiccup cannot fail it — preferred, keeps the budget honest; (b) a modest budget raise with a comment recording the two incidents; (c) an environment-aware multiplier (worst option — hides regressions). Whatever lands must keep the test able to catch a REAL 2x regression. The companion test_full_fog_update_under_1ms has 2x the headroom and has never flaked — evidence the budget, not the code, is the problem. Gate logs: /tmp/sr-run-godot.638004.log (0.549), /tmp/sr-run-godot.1028571.log (0.503). + +FIXED (2026-07-26, direct on main): the test already used median-of-5 (T-1092''s earlier mitigation) and still flaked three times in one day (0.549/0.503/0.638) when concurrent cargo builds inflated all five samples together. Superseded with MINIMUM-of-7: the assertion asks whether the CODE meets the D-059 budget, and load can only inflate wall time, never deflate it — the minimum is the least-noise estimator of code capability while a real regression shifts the minimum too. Budget unchanged at 0.5ms (regression-catching power preserved). Verified 46/46. Closing.', 'done', 'medium', NULL, 'client', NULL, '2026-07-26 12:51:23.279', '2026-07-26 13:17:35.789', NULL, '3f5c596053a4f615e65b192cb0887a3a', 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); diff --git a/client/tests/test_fog_shader.gd b/client/tests/test_fog_shader.gd index 1818f7466..8bdae98f9 100644 --- a/client/tests/test_fog_shader.gd +++ b/client/tests/test_fog_shader.gd @@ -193,20 +193,24 @@ func test_visibility_texture_update_performance() -> void: fog_state.update_from_state() # Measure the steady-state per-frame update (same positions, no resize). - # Median of 5 runs: a single wall-clock sample flakes when the machine is - # loaded (T-1092 — the pre-push gate shares the box with live sessions); - # the median keeps the D-059 budget intent while absorbing load spikes. + # MINIMUM of 7 runs (T-1210, superseding T-1092's median-of-5): the + # assertion asks whether the CODE meets the D-059 budget, and wall-clock + # load can only inflate a sample, never deflate it — so the minimum is + # the least-noise estimator of code capability, while a real regression + # shifts the minimum too. Median-of-5 still flaked three times on + # 2026-07-26 when a cargo build saturated every core and inflated all + # five samples together (0.549/0.503/0.638 vs the 0.5 budget). var samples: Array[float] = [] - for _i in range(5): + for _i in range(7): var start := Time.get_ticks_usec() fog_state.update_from_state() samples.append((Time.get_ticks_usec() - start) / 1000.0) samples.sort() - var median_ms: float = samples[2] + var best_ms: float = samples[0] # D-059: Visibility texture upload budget: 0.1ms # Allow margin for test environment overhead - assert_that(median_ms).is_less(0.5) + assert_that(best_ms).is_less(0.5) GameState.visible_positions.clear()