fix(client): PR #212 review fixes — true on-screen footprint_px, self-describing shot coverage

Tyre finding 2: _log_atlas_view_transform's footprint_px now logs the
real on-screen pixel footprint (StepCanvasTransport.canvas_footprint_px
* canvas_scale — the same public pure function the terrain layer uses),
with the old cell-count field kept as canvas_cells. Live-verified the
divergence the fix exposes: Global logs footprint_px=(1528, 760) vs
canvas_cells=191x95 — the T-1192 fit-multiplier class the log exists to
root-cause, previously invisible under the mislabel.

Tyre finding 3: atlas_shots.json's one_shot_per_body note replaced by
rung_coverage stating the true distribution — 13 goldens across 7
bodies (per-rung coverage map, GJ380c's 3 shots as the invariance-proof
body, curated-subset rationale per T-1121). Corrects the prior commit
message's '12 new goldens' miscount: the true count everywhere is 13,
verified against shots array, visual.json entries, and PNGs on disk.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-25 22:36:03 +02:00
co-authored by Claude Fable 5
parent 28a0b3e2af
commit feef7aa1c5
2 changed files with 34 additions and 4 deletions
+33 -3
View File
@@ -294,6 +294,27 @@ func _settle_atlas_viewer_if_pending(tree_root: Node) -> void:
## mismatch is root-causable (PR #204's own precedent: this exact log shape
## identified an edge-scroll drift bug by its PAN_SPEED_PX_S*frame_time
## fingerprint) instead of a bare "pixels don't match".
##
## PR #212 review (Tyre finding 1): `footprint_px` previously sourced
## canvas_width/canvas_height off get_current_canvas_summary() — those are the
## held canvas's CELL dimensions (gridunits), not its on-screen PIXEL
## footprint, which is exactly the wrong quantity for a log whose whole job is
## catching a fit-scale-multiplier bug (the T-1192 Global integer-fit ratio,
## PR #204's own drift class). The real on-screen footprint is
## StepCanvasTerrainLayer's own `_footprint_px` — private to that node, so
## rather than reach into it (this cluster's own "no private-field reach"
## discipline — get_current_canvas_summary()'s doc makes the same call for
## `_canvas_ref`), this recomputes the identical value from the SAME public,
## pure function the terrain layer itself calls to produce it
## (StepCanvasTransport.canvas_footprint_px(rung, extent) —
## step_canvas_terrain_layer.gd's own rebuild_from_canvas():
## `_footprint_px = StepCanvasTransport.canvas_footprint_px(rung, new_size)`),
## then multiplies by the SAME canvas_scale already logged here (the T-1192
## Global integer-fit multiplier, 1.0 elsewhere) — matching
## _centered_view_offset()'s own `raw_footprint * scale` pattern for the
## identical "true on-screen size" quantity. canvas_cells is kept alongside
## it (relabeled from the old footprint_px name) since the cell count is
## still useful log context, just correctly named now.
func _log_atlas_view_transform(tree_root: Node, scenario_name: String) -> void:
var viewer: Variant = _get_atlas_regional_viewer(tree_root)
if viewer == null:
@@ -302,18 +323,27 @@ func _log_atlas_view_transform(tree_root: Node, scenario_name: String) -> void:
var canvas_node: Node2D = viewer.get_node_or_null("StepCanvas")
var canvas_pos: Vector2 = canvas_node.position if canvas_node else Vector2.ZERO
var canvas_scale: Vector2 = canvas_node.scale if canvas_node else Vector2.ONE
var rung: String = str(summary.get("rung", ""))
var held_extent_raw: Variant = summary.get("held_extent", [0, 0])
var extent_cells := Vector2i(int(held_extent_raw[0]), int(held_extent_raw[1]))
var StepCanvasTransport := load(
"res://ui/implant/apps/atlas/step_canvas/step_canvas_transport.gd"
)
var raw_footprint_px: Vector2 = StepCanvasTransport.canvas_footprint_px(rung, extent_cells)
var on_screen_footprint_px: Vector2 = raw_footprint_px * canvas_scale
print(
(
"visual_capture: view-transform[%s] rung=%s world_center=%s held_extent=%s "
+ "canvas_position=%s canvas_scale=%s footprint_px=%dx%d"
+ "canvas_position=%s canvas_scale=%s footprint_px=%s canvas_cells=%dx%d"
)
% [
scenario_name,
str(summary.get("rung", "")),
rung,
str(summary.get("world_center", [])),
str(summary.get("held_extent", [])),
str(held_extent_raw),
str(canvas_pos),
str(canvas_scale),
str(on_screen_footprint_px),
int(summary.get("canvas_width", 0)),
int(summary.get("canvas_height", 0)),
]
+1 -1
View File
@@ -69,7 +69,7 @@
"veg": ["gen_dw_veg"]
},
"matrix_rules": {
"one_shot_per_body": "each body gets ONE golden shot at a rung chosen to exercise a different depth of the ladder across the set (Global-heavy for the orbital opener, deeper rungs for a few bodies) — the full 6-rung x 7-body cross product (42 shots) is deliberately NOT curated here, matching T-1121's 'curated subset, not the full matrix' precedent; the full cross product remains reachable ad hoc via AtlasAgentInterface jump_to intents, not as a golden."
"rung_coverage": "13 goldens across the 7 bodies above (NOT one-shot-per-body): most bodies (GJ144e, GJ338Bd, GJ820Bc, GJ251c) get 2 shots — the Global opener plus one deeper rung — so every fixed rung below Global is exercised at least once across the set (Region: GJ380c/GJ251c; District: GJ380c/GJ820Bc; Quarter: GJ144e; Block: GJ338Bd; Chunk: GJ445c-m1). GJ380c gets 3 (Global/Region/District) since it is also the PR #212 cache-invariance-proof body (Hoshe's cold-vs-warm check on both the NEAREST/Global and LINEAR/District terrain-layer draw branches). GJ244Ad and GJ445c-m1 get 1 each (Global and Chunk respectively) — the curated pick, not an exhaustive per-body sweep. The full 6-rung x 7-body cross product (42 shots) is deliberately NOT curated here, matching T-1121's 'curated subset, not the full matrix' precedent; the full cross product remains reachable ad hoc via AtlasAgentInterface jump_to intents, not as a golden."
},
"shots": [
{ "body_id": "GJ380c", "rung": "Global", "overlays": ["gen_dw_temp"], "filename": "atlas_GJ380c_Global.png" },