fix(client): median-of-5 timing in fog perf test — kills load flake (T-1092)

test_visibility_texture_update_performance asserted a single wall-clock
sample against the 0.5ms budget and blocked two pushes while a live session
shared the machine (0.704ms / 0.623ms; 46/46 green in isolation). Median of
5 runs preserves the D-059 budget intent while absorbing load spikes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 20:18:01 +02:00
co-authored by Claude Fable 5
parent 6372537f2f
commit 72f88dae1d
3 changed files with 14 additions and 6 deletions
+1
View File
@@ -5,3 +5,4 @@ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FKCPBF41RWK9PW9M22Q7961C', 'T-1089', '2026-07-06 07:34:18.657', '2026-07-06 07:34:18.657', NULL, '7283f875610cbd67d7dd0d6bc949d3cf', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FKE0EW2617K9VE4QHSYSR9HW', 'T-1090', '2026-07-06 10:38:16.595', '2026-07-06 10:38:16.595', NULL, '38d331606c3d8de414dec0c2c971ad71', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FKE0J4B8GQ17NFFV8N7D45BW', 'T-1091', '2026-07-06 10:38:43.290', '2026-07-06 10:38:43.290', NULL, 'da0796307c06acd6609ac466d6ea48c3', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FKH8SJRMXTP6XQNBXHRD4CQ0', 'T-1092', '2026-07-06 18:14:07.303', '2026-07-06 18:14:07.303', NULL, 'e34fe437eac3bdbd6a73f8d98bc871a9', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash);
+1
View File
@@ -694,3 +694,4 @@ Animation supply resolved (2026-07-06): user purchased UAL1[Source+Pro] (120 cli
Live-session feedback (user, 2026-07-06): (1) Corridor cutaway verdict — two minds: ''extremely trippy, could be the game''s own look'' vs ''player cannot see what is in the room unless close''. Resolution: cutaway MODES, toggled live in the sandbox (corridor / bottom-walls-low / both) — bottom-wall rule is data-driven (wall drops to stub when a KNOWN floor tile sits on its camera-far side; camera-facing directions derived from WorldRoot basis at runtime, not hand-derived). Default picked by feel during the session; the trippy corridor stays available as a signature-look option. (2) NEW: mouse-over move-here marker on the hovered tile + optimal path line — client-side A* over the never-evict KNOWN tile store (info-boundary-honest: the character plans only through known tiles; fog is unpathable), 8-dir with diagonal step cost 1 (time-optimal per the no-sqrt2 wire), terrain-cost provider seam (uniform today, Phase-4 terrain later), click executes by streaming ordinary Move* step commands through the existing throttle (zero protocol change, server validates every step), cancelled by WASD override / path invalidation / arrival. Settles more of Q-084 (click-to-move half).
RMB gesture vocabulary (user, live session 2026-07-06, added to the path-preview feature): single right-click = walk there (current stance); DOUBLE right-click = sprint there (ladder ToggleStanceUp burst to Sprint via the ordinary command queue, pre-sprint stance RESTORED on arrival; a double upgrades the already-started follow in place); LONG-PRESS right-click (~0.4s, commit on release) = ''take cover at location'', prototyped as go-there-then-Crouch-on-arrival (no restore — crouching was the point). Real cover mechanics (wall adjacency, directional protection) are future combat design; the gesture is the input-vocabulary prototype. WASD always cancels any follow without stance restore (player override is deliberate).', 'backlog', 'high', NULL, 'client', NULL, '2026-07-06 07:01:06.475', '2026-07-06 17:37:13.480', NULL, '6a60bee830c86a4c53c735ec17087499', 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 ('06FKH8SJRMXTP6XQNBXHRD4CQ0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'test_fog_shader perf assertions flake under machine load — make budget load-tolerant', 'test_visibility_texture_update_performance asserts wall-clock < 0.5ms and failed at 0.704ms during a pre-push while a live game session + capture harness shared the machine (2026-07-06); 46/46 green re-run in isolation. Fix options: median-of-N timing, a generous multiplier, or gating perf assertions behind an env var so functional coverage always runs but timing only gates on a quiet machine.', 'backlog', 'low', NULL, 'client', NULL, '2026-07-06 18:14:07.301', '2026-07-06 18:14:07.301', NULL, '1a1f4e07550e0c8834184ffec0816848', 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);
+12 -6
View File
@@ -192,15 +192,21 @@ func test_visibility_texture_update_performance() -> void:
# a rare amortized event (8-tile padding), not part of the per-frame budget.
fog_state.update_from_state()
# Measure the steady-state per-frame update (same positions, no resize)
var start := Time.get_ticks_usec()
fog_state.update_from_state()
var elapsed_us := Time.get_ticks_usec() - start
var elapsed_ms := elapsed_us / 1000.0
# 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.
var samples: Array[float] = []
for _i in range(5):
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]
# D-059: Visibility texture upload budget: 0.1ms
# Allow margin for test environment overhead
assert_that(elapsed_ms).is_less(0.5)
assert_that(median_ms).is_less(0.5)
GameState.visible_positions.clear()