Commit Graph
11 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 5 8eb5cb9ff7 feat(ui): the Atlas ladder bottoms out at Quarter (D-255, T-1213)
Quarter becomes the deepest navigable rung. Block and Chunk leave the ladder.

The rule, from the amendment: the deepest Atlas rung is the one at which a
screen pixel shows one subtile. At the uniform 2x2 px display ratio a
3440x1440 window gives 540 gridunits on the short axis, so Quarter's 512 m
extent draws 0.948 m per gridunit -- about one voxel per gridunit and one
0.5 m subtile per pixel. Block (0.237) and Chunk (0.119) magnify beneath the
finest datum that can exist, and measured as exactly that on Ferrath: one
morphology zone, one vegetation class, an unbroken colour field. They were not
missing a feature; there was nothing left to show them.

CHUNK ITSELF IS UNTOUCHED. It remains D-243's 64 m stream/derive unit and is
where Phase 5 derives first-person walkable content -- D-012's
load-around-the-player is expressed in chunks. Block remains the 128 m
generator planning unit. Both keep their enum variants, their extent_m answers
and their wire vocabulary. What was retired is the claim that a MAP of one is
worth looking at.

DEEP_RUNGS moved with the floor, and this is the part worth reading twice. It
is a mandatory D-255(d) hardening: a per-body retention cap bounding how much
ground an exhaustive pan can hold resident at fine spacing. Left as
[Block, Chunk] it would have guarded rungs no client can request -- dead code
-- while the accumulation gap silently re-opened under Quarter, now the finest
navigable rung at ~0.95 m per gridunit. It is now [District, Quarter]. A
control that names its targets by rung has to follow the ladder when the
ladder moves.

Six tests pinned the old floor and were updated rather than deleted, since
each was protecting a real property: the clamp tests now clamp at Quarter, and
the disk-cache tests use Region for "shallow" (District is capped now) and
Quarter for "deep". One new test pins the distinction the change turns on --
the retired rungs are absent from RUNG_LADDER but still present in
RUNG_EXTENT_M, because viewability was retired, not vocabulary.

Also removes the four capture scenarios for the retired rungs, including the
two blank goldens that had been passing against blank captures.

1838 client tests, 0 failed. Server clippy clean, step_canvas suite green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 14:38:47 +02:00
jpmschweitzerandClaude Opus 5 c91096a3c9 test(client): retire the top-down visual suite, aim the Atlas ladder at land
The visual gate had stopped measuring anything: 30 of 32 scenarios
failed, and the two that passed were the worst result of the lot.

Deleted the 15 top-down scenarios (fog, HUD, dialogue, NPC, minimap,
cursor) and their goldens. They all failed at a near-uniform ~12%, and
that uniformity across unrelated scenes is one global cause -- the
ultrawide UI stretch moved every element. They cover the renderer the
cascade freezes until Phase 5, which will need its own tests anyway, so
re-baselining would only have blessed a deprecated layer nobody is
reviewing. Jeroen's call.

The remaining problem was the goldens that PASSED. atlas_GJ338Bd_Block
and atlas_GJ445c-m1_Chunk matched at 0.0% because capture and golden
were both blank -- the same "goldens have been measuring nothing" trap
e024cfb3f caught at Global, still live at the bottom of the ladder. The
cause is that every below-Global golden descends at jump_to(ZERO), and
world-metre zero is merely the origin of the region grid, not anywhere
chosen. So _setup_atlas_golden_shot now takes an optional world_center
(default ZERO -- existing goldens are untouched), and a new
atlas_GJ820Bc_land_* set walks Region through Chunk at ONE land point,
so the rungs can be read as a descent instead of five unrelated frames.

aliveness_probe prints the placement's world metres alongside its pixel
and survey cell, since that is the coordinate the Atlas actually
navigates in.

Recorded because it will be asked again: the ladder is anchored via a
CityPlacement, but that is a match record -- a pixel, an archetype, an
orientation -- not built geography. No settlement exists anywhere yet
and none is due before T-1207, so the empty deep rungs are the expected
state. What the ladder judges is the nature layer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 16:33:57 +02:00
jpmschweitzerandClaude e024cfb3f9 test(client): the Atlas Global goldens have been measuring nothing
Every atlas capture scenario built its body dict without body_radius_km.
Radius is Global's ONLY spacing input (2*pi*R / width), so every Global
golden has been a degenerate block since these scenarios were created — the
map rendered at 0.000 km/gridunit. The fixed rungs were unaffected, since they
derive spacing from the rung's own cell size rather than the body.

That means the "eyeball check against .cache/screenshots baselines"
discipline has been hollow at Global specifically: a baseline that is a solid
rectangle diffs clean against a new solid rectangle. It is how a 2x1 canvas
survived in front of two verification layers.

Adds the real radii to all ten scenarios (Lendel 6238.4, Vethis 6959.3,
Arbour 6711.0, Ferrath 6062.0, Threshold 5503.5), and makes the capture log
course and settlement counts alongside canvas_cells — an empty annotation
layer was previously indistinguishable from a populated one in the log, which
is exactly the signal needed to tell "no rivers" from "rivers not drawn".

Also updates three suites to the corrected Global cache contract: the key now
honours extent (collapsing it meant a resize could never miss), so the shared
_land_global_canvas helper must cache under the extent the viewer will
actually request, and the two make_key tests now assert the real rule —
centre collapsed, extent honoured — instead of the retired sentinel.

Client suite 1830 total / 1804 passed / 0 failed / 26 skipped.

Pair session with Jeroen, 2026-07-27.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-27 20:52:54 +02:00
jpmschweitzerandClaude Fable 5 a45d4a5f58 feat(client): capture harness redesigned for the stepped Atlas — (body, rung) goldens (T-1157)
_setup_atlas_golden_shot and _run_atlas_matrix rebuilt on the real D-255
surface: nav.push('regional') through AtlasApp's own body-selection tail,
then StepCanvasViewer.jump_to at a fixed center (inventory item 5) — no
shim over the retired continuous-zoom API. is_pending()-aware bounded
settle (mirroring atlas_agent_driver.gd) and view-transform logging
(inventory item 3) wired into both capture paths. The 12 z2_0/z4_0/zfit
goldens are replaced by 12 (body, rung) goldens captured live against
fresh --test-mode servers; atlas_shots.json/visual.json re-keyed;
atlas_gen_open's stale gen_l1_* overlay ids fixed to gen_dw_temp.

Verification: two consecutive District runs byte-identical, and a
cold-vs-warm disk-cache invariance proof on both terrain draw branches
(Global/NEAREST, District/LINEAR) — byte-identical either way, so
capture output does not depend on the shared user://atlas_cache state.
DEVOPS.md's real-rendering exception note now records the fold-target
mapping for the smoke file T-1182 already deleted (Global + District
goldens exercise its two real-pixel draw branches). Old legacy-tracked
.import sidecars go with their PNGs; new goldens ship bare per
.gitignore's client/**/*.import rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 22:13:37 +02:00
jpmschweitzerandClaude Fable 5 799156b140 feat(client): Atlas screenshot capture matrix + set_view API (T-1120)
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>
2026-07-16 20:29:14 +02:00
jpmschweitzerandClaude Opus 4.7 89596dbb87 test(client): live atlas generation-overlay inspection scenario (#960)
atlas_gen_open opens the real atlas app via HudGroups, navigates to GJ71c's
regional screen, and enables the Layer-1 overlays — exercising the production
opener + the live request→cascade→render pipeline against a --test-mode server
(SR_LIVE=1). Capture with: tests/run-visual --screenshot atlas_gen_open.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 10:09:48 +02:00
jpmschweitzerandClaude Opus 4.7 c3bcf09c72 chore(client): gdformat visual_capture + visual_scenarios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:54:51 +02:00
jpmschweitzerandClaude Opus 4.7 6bb21db2cb test(client): implant_pending visual scenario (#960)
Ad-hoc capture scenario that overlays the ImplantPending "generating" indicator
on the booted scene for visual sign-off — `tests/run-visual --screenshot
implant_pending`. No golden committed; this is an inspection scenario, not a
regression gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 22:53:57 +02:00
jpmschweitzerandClaude Opus 4.6 4eb54a6f7a fix(client): resolve all gdlint warnings — zero warnings policy
Fix 354 gdlint warnings across 65 files: 194 class-definitions-order
(reorder declarations), 138 max-line-length (split long lines),
22 code issues (unused args, no-else-return, naming). Update .gdlintrc
to exclude addons/ and raise max-public-methods for test files.
No logic changes — declaration order, whitespace, and naming only.

Ticket: #783

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 09:59:56 +02:00
jpmschweitzerandClaude Opus 4.6 ac763fef97 feat(engine): live server visual tests and gauntlet snapshot replay
Add live server lifecycle to tests/run-visual (start/stop server per
scenario, parse LISTENING:{port}). Add MessagePack snapshot replay to
visual_capture.gd via Protocol.decode_snapshot() — exercises the full
client pipeline from wire bytes to rendered fog. Three replay scenarios
(hub_spawn, fog_theater, hub_after_movement) plus one live scenario
(fog_live_hub). Add gen_gauntlet_fixtures.rs to produce .msgpack fixtures
from the Gauntlet test world. Add max_diff_pct threshold to visual-diff.
Makefile: add fixtures-gauntlet target, fix build-client double-import,
preserve .godot cache in clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 08:41:09 +01:00
jpmschweitzerandClaude Opus 4.6 6bcdc48412 feat(client): add visual test harness with golden regression
Gives Claude eyes: `make screenshot` captures a rendered frame,
`make test-visual` compares against golden PNGs, `make visual-update`
regenerates goldens. Built to debug the Sprint 22 fog regression and
prevent future visual regressions across fog, HUD, dialogue, and UI.

Config-driven via tests/visual.json (11 scenarios, 2 flows).
Capture engine boots main.tscn with real GPU rendering (not --headless),
waits for NoiseTexture2D async gen, uses deterministic shader time.

Components:
- visual_capture.gd: SceneTree capture engine (scenario + movie modes)
- visual_scenarios.gd: per-scenario setup hooks
- tooling/visual-diff: pixel comparator (PIL primary, struct fallback)
- tooling/visual-thumbnail: contact sheet + crop tool
- tests/run-visual: suite script (xvfb wrapping, golden workflow)
- fog_state.gd: override_time for deterministic captures
- fog_shader.gd: fog_noise_ready signal for settle sequencing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:33:55 +01:00