fix(config): run-godot reported a suite that never ran as a pass

Found by walking into it. test_step_canvas_annotation_layer.gd had a parse
error from an earlier edit in this session, so gdUnit4 could not load it and
ran the other suites instead. The harness printed 3610 passed / 0 failed and
exit 0. Fifty tests had not run for hours and nothing said so — the full
suite reports 3660 with the file repaired, and that difference was invisible.

Two states are now hard harness failures rather than test results:

  load_error — a suite failed to LOAD. Any pass count excludes it, so a green
  number is a lie. The hint names the offending file.

  no_tests  — zero tests executed. A run that executes nothing can never be
  a pass; previously a mistyped --filter printed "Tests passed".

Both add a "harness_error" field to the summary JSON and exit 2. The exit
code cannot inherit gdUnit4's, which returns 0 in both states — that is
precisely why they were invisible.

Verified by injecting each failure rather than by reasoning about it. The
load_error guard was checked in the case that actually matters: one broken
file among many, where total stays large and failed stays zero. That run now
reports 3610/0 WITH harness_error and exits 2, where before it was
indistinguishable from success.

Also repairs the file itself: a missed set_frame() argument (the parse error),
and a cell-placement test still asserting pre-inversion spacing. Rewritten to
assert the invariant that survives the extent inversion, the viewport aspect
ratio and panning — half the SHORT axis is half a rung cell — instead of a
literal. Two things it deliberately does not assert, both of which the
previous version got wrong: "the corner is half a district away" holds only
on a square canvas, and the canvas is one district WIDE without sitting ON a
district. It is a free-floating window centred wherever the player panned;
zoom is stepped, pan is continuous. A rung names a scale, not a cell you are
inside. A second test pins that with a deliberately unaligned world centre,
so a future change that snaps the canvas to the rung lattice — making pan
step instead of slide — fails here.

Pair session with Jeroen, 2026-07-27.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-27 00:12:26 +02:00
co-authored by Claude
parent d58397c59f
commit b2ef73256a
3 changed files with 112 additions and 8 deletions
@@ -39,15 +39,64 @@ func test_clear_frame_drops_the_held_canvas() -> void:
## placement (center_world_m + (col - half_w) * step_m) — a settlement id
## read from cell (col, row) must map back to the world point that cell was
## actually derived at.
func test_cell_center_world_m_matches_the_servers_own_per_cell_placement() -> void:
## The invariant that survives the D-255 extent inversion, the viewport's
## aspect ratio, AND panning: **half the SHORT axis is half a rung cell.**
##
## Post-inversion the pitch is derived from the canvas rather than fixed per
## rung, so no literal spacing belongs in this test. Two things it must NOT
## assert, both of which an earlier version got wrong:
##
## - *"the corner is half a district away"* holds only on a SQUARE canvas.
## A real widescreen canvas spans one cell on its short axis and ~1.78 on
## its long one, so the corner is half a district on one axis only.
## - The canvas is one district **wide**; it is not sitting **on** a
## district. It is a free-floating window centred wherever the player has
## panned, with no relationship between its edges and any district
## boundary — zoom is stepped, pan is continuous (D-255 premise 3).
## A rung names a scale, the way a paper map says 1:25,000; it does not
## name a cell you are inside.
func test_cell_center_world_m_short_axis_spans_exactly_one_rung_cell() -> void:
var cell_m: float = StepCanvasTransport.RUNG_EXTENT_M["District"]
# Landscape, portrait and square — the short axis is chosen by size, never
# by which axis happens to be the width.
for extent in [Vector2i(8, 4), Vector2i(4, 8), Vector2i(6, 6)]:
var layer: StepCanvasAnnotationLayer = auto_free(StepCanvasAnnotationLayer.new())
add_child(layer)
layer.set_frame(
{"width": extent.x, "height": extent.y, "courses": []},
Vector2.ZERO,
"District",
extent,
0.0
)
var corner: Vector2 = layer._cell_center_world_m(0, 0)
# On the SHORT axis, the edge sits half a rung cell from centre.
var short_axis_offset: float = absf(corner.y if extent.y <= extent.x else corner.x)
assert_float(short_axis_offset).override_failure_message(
"%s: short-axis edge is %f m from centre, want half a District (%f)"
% [extent, short_axis_offset, cell_m * 0.5]
).is_equal_approx(cell_m * 0.5, 0.001)
# And the centre cell is the world centre, whatever the shape. Note the
# centre is (width/2, height/2) — NOT the same index on both axes once
# the canvas is not square.
assert_that(layer._cell_center_world_m(extent.x / 2, extent.y / 2)).is_equal(Vector2.ZERO)
## Panning does not align the canvas to anything — the frame's world centre is
## wherever the player stopped, and every cell offset is measured from it. A
## centre deliberately off any round boundary guards against a future change
## quietly snapping the canvas to the rung's own lattice, which would make pan
## step instead of slide.
func test_cell_center_world_m_is_independent_of_grid_alignment() -> void:
var layer: StepCanvasAnnotationLayer = auto_free(StepCanvasAnnotationLayer.new())
add_child(layer)
layer.set_frame({"width": 4, "height": 4, "courses": []}, Vector2(0.0, 0.0), "District", Vector2i(4, 4), 0.0)
# half_w = half_h = 2; spacing = 2048. Cell (0,0) -> (0-2)*2048 = -4096 on
# both axes; cell (2,2) (the center-ish cell) -> (2-2)*2048 = 0.
assert_that(layer._cell_center_world_m(0, 0)).is_equal(Vector2(-4096.0, -4096.0))
assert_that(layer._cell_center_world_m(2, 2)).is_equal(Vector2.ZERO)
var ragged := Vector2(1_234_567.0, -987_654.0) # deliberately unaligned
layer.set_frame(
{"width": 4, "height": 4, "courses": []}, ragged, "District", Vector2i(4, 4), 0.0
)
assert_that(layer._cell_center_world_m(2, 2)).override_failure_message(
"the centre cell must be the frame's world centre exactly — no snapping"
).is_equal(ragged)
func test_cell_center_world_m_offsets_by_the_frames_world_center() -> void:
@@ -74,7 +123,7 @@ func test_world_to_local_uses_the_held_frame() -> void:
add_child(layer)
var world_center := Vector2(5_000.0, -3_000.0)
var extent := Vector2i(32, 32)
layer.set_frame({"width": 32, "height": 32, "courses": []}, world_center, "Quarter", extent)
layer.set_frame({"width": 32, "height": 32, "courses": []}, world_center, "Quarter", extent, 0.0)
var expected: Vector2 = StepCanvasTransport.world_m_to_canvas_local(
world_center, world_center, "Quarter", extent, 0.0