feat(client): Atlas screenshot capture matrix + goldens + set_view API (T-1120) #180

Closed
jpmschweitzer wants to merge 0 commits from atlas-screenshot-goldens into main
Owner

Summary

T-1120 (T-1037 test infra): programmatic Atlas screenshot capture + the first Atlas golden set. Delivered to Jeroen as 42 captures + contact sheet; 12 curated shots promoted into the existing golden machinery.

What

  • AtlasViewer gains a public set_view(zoom, offset) / get_view_offset() API (clamped; the review-flagged alternative to poking _view_zoom/_view_offset from harnesses) + a gdUnit suite.
  • visual_capture.gd gains an atlas_matrix scenario: ONE Godot boot loops tests/atlas_shots.json (7 DB-verified bodies x zoom {fit,2.0,4.0} x overlay sets A/B/C, ~42 shots in ~90s), with signal-gated waits (atlas_layers_received Ready + city_names_received, 15s timeout fallback). 12 individually-addressable golden scenarios registered in tests/visual.json.
  • 12 golden PNGs in client/tests/golden/visual/ (+.import sidecars force-added per the existing convention), self-consistency 12/12 exact pixel match on this box.
  • Root-level settings.db* gitignored (capture-spawned servers write their settings store to cwd).

Bodies

GJ380c, GJ144e, GJ338Bd, GJ820Bc (Metropolis + Cygni yard visible), GJ251c (deliberate T-1116 water/no-roads exhibit), GJ244Ad (frozen, most cities of its class), GJ445c-m1 (inhabited moon).

Bugs found by building this

  • GDScript lambdas capture value-type locals BY VALUE — the layer-ready wait flag silently never flipped; moved to an Array carrier (team-note-worthy gotcha).
  • RegionalScreen.enter() no-ops when the screen id is unchanged — body #2+ would silently show body #1; harness calls enter() directly per body.
  • Test-infra: three new gdUnit tests initially skipped scene-tree entry (nil _canvas) — caught by the push gate, fixed.

Out of scope / follow-ups

T-1121 filed: all 19 PRE-EXISTING goldens fail 12-14% on this box (cross-machine font/AA/GPU baseline drift; fog_live_hub stalls without xvfb) — portability investigation, unrelated to the new set.

Verification

Full gate green (GDScript parse, client suite 2956 incl. the new suites, JSON). Captures verified by eye by the lead before delivery; goldens are exact-match self-consistent on the capture box.

## Summary T-1120 (T-1037 test infra): programmatic Atlas screenshot capture + the first Atlas golden set. Delivered to Jeroen as 42 captures + contact sheet; 12 curated shots promoted into the existing golden machinery. ### What - AtlasViewer gains a public set_view(zoom, offset) / get_view_offset() API (clamped; the review-flagged alternative to poking _view_zoom/_view_offset from harnesses) + a gdUnit suite. - visual_capture.gd gains an atlas_matrix scenario: ONE Godot boot loops tests/atlas_shots.json (7 DB-verified bodies x zoom {fit,2.0,4.0} x overlay sets A/B/C, ~42 shots in ~90s), with signal-gated waits (atlas_layers_received Ready + city_names_received, 15s timeout fallback). 12 individually-addressable golden scenarios registered in tests/visual.json. - 12 golden PNGs in client/tests/golden/visual/ (+.import sidecars force-added per the existing convention), self-consistency 12/12 exact pixel match on this box. - Root-level settings.db* gitignored (capture-spawned servers write their settings store to cwd). ### Bodies GJ380c, GJ144e, GJ338Bd, GJ820Bc (Metropolis + Cygni yard visible), GJ251c (deliberate T-1116 water/no-roads exhibit), GJ244Ad (frozen, most cities of its class), GJ445c-m1 (inhabited moon). ### Bugs found by building this - GDScript lambdas capture value-type locals BY VALUE — the layer-ready wait flag silently never flipped; moved to an Array carrier (team-note-worthy gotcha). - RegionalScreen.enter() no-ops when the screen id is unchanged — body #2+ would silently show body #1; harness calls enter() directly per body. - Test-infra: three new gdUnit tests initially skipped scene-tree entry (nil _canvas) — caught by the push gate, fixed. ### Out of scope / follow-ups T-1121 filed: all 19 PRE-EXISTING goldens fail 12-14% on this box (cross-machine font/AA/GPU baseline drift; fog_live_hub stalls without xvfb) — portability investigation, unrelated to the new set. ### Verification Full gate green (GDScript parse, client suite 2956 incl. the new suites, JSON). Captures verified by eye by the lead before delivery; goldens are exact-match self-consistent on the capture box.
jpmschweitzer added 4 commits 2026-07-16 20:36:22 +02:00
AtlasViewer gains public set_view(zoom, offset)/get_view_offset (clamped, review-flagged API gap) + gdUnit suite. visual_capture.gd gains an atlas_matrix scenario (one boot, tests/atlas_shots.json-driven: 7 verified bodies x zoom x overlay sets, signal-gated waits on atlas_layers_received/city_names_received with timeout fallback). 12 individually-addressable golden scenarios registered in tests/visual.json. Root-level settings.db* gitignored (capture-spawned servers write their settings store to cwd). Fixes found live: GDScript lambdas capture value-type locals BY VALUE (wait-flag moved to Array carrier); RegionalScreen.enter() no-ops when the screen id is unchanged (direct enter() per body after the first).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Curated from the 42-shot matrix, one per body spanning all zoom levels and overlay sets; self-consistency verified 12/12 at exact pixel match on this box. .import sidecars force-added per the existing golden convention. Bodies: GJ380c, GJ144e, GJ338Bd, GJ820Bc (Metropolis + Cygni yard), GJ251c (T-1116 water/no-roads exhibit), GJ244Ad (frozen), GJ445c-m1 (moon).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three of the four new tests skipped scene-tree entry, so _ready() never resolved _canvas and set_view crashed _apply_transform. Mirrors the fourth (passing) test. Targeted suite green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jpmschweitzer added 3 commits 2026-07-16 21:32:49 +02:00
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Second distinct flake in this suite today (gate run: MoveEast observed mid-move at the 5s window). The old accounting accrued elapsed only on empty polls — load-dependent effective window. Wall-clock deadline via Time.get_ticks_msec; ceiling 5s->10s (exit-on-arrival, costs nothing when healthy). Targeted suite 6/6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Root-caused with server trace logs: Walk stance throttles 1 move per 2 ticks and SILENTLY discards early moves (movement.rs apply_move -> try_move, TRACE-only) — under load the test's MoveEast landed exactly 1 tick after MoveNorth and was consumed. Server behavior is correct, deliberate D-053, pinned by Rust tests; production clients re-send while keys are held. Fix: COOLDOWN_TICKS=3 post-ack spacing, same as test_sprint2_proof.gd (T-1068) whose fix never reached this file due to helper copy-paste. Pre-fix repro at run 17/30 under load; post-fix 30/30 stress green + full suite 2956/2956.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jpmschweitzer added 1 commit 2026-07-16 21:42:03 +02:00
The _comment_atlas_goldens key inside scenarios{} hit _print_list's .get() on a bare String (reproduced: Invalid call on String at visual_capture.gd:699). Moved to a top-level key alongside resolution/golden_dir; _print_list now also skips _-prefixed and non-Dictionary entries so future comment keys cannot crash it. Verified: --list runs clean, JSON valid.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Owner

Re-review verdict: APPROVED — Tyre: T1 provenance resolved on both surfaces, commits 2-3 clean (the wall-clock fix repairs a real latent unbounded-timeout bug; the cooldown pacing makes the test respect a genuine D-053 gameplay contract). Hoshe: APPROVE with one condition — the provenance key crashed visual_capture --list (reproduced live) — fixed exactly as prescribed on fcf913a41 (key moved top-level + iterator hardened, repro verified gone, gate green). Root-cause note for the record: the movement flake was NOT a bridge bug — the D-053 Walk stance cooldown silently discards a move landing 1 tick after the previous one; test now paces past it (T-1068 fix ported; T-1122 filed for the shared-harness extraction that would have prevented the drift). Merging.

## Re-review verdict: APPROVED — Tyre: T1 provenance resolved on both surfaces, commits 2-3 clean (the wall-clock fix repairs a real latent unbounded-timeout bug; the cooldown pacing makes the test respect a genuine D-053 gameplay contract). Hoshe: APPROVE with one condition — the provenance key crashed visual_capture --list (reproduced live) — fixed exactly as prescribed on fcf913a41 (key moved top-level + iterator hardened, repro verified gone, gate green). Root-cause note for the record: the movement flake was NOT a bridge bug — the D-053 Walk stance cooldown silently discards a move landing 1 tick after the previous one; test now paces past it (T-1068 fix ported; T-1122 filed for the shared-harness extraction that would have prevented the drift). Merging.
jpmschweitzer closed this pull request 2026-07-16 21:46:42 +02:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#180