Commit Graph
3 Commits
Author SHA1 Message Date
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 51fe35d00d fix(ui): harden step-canvas disk cache — PR #204 review round (T-1183)
Atomic index writes (tmp+rename), orphan-payload reconciliation sweep
folded into the background sweep, payload shape guard mirroring the
protocol's own width/height discriminator, size_bytes via get_position()
instead of a full payload re-read, and a 64-bit SHA-256 payload filename
(String.hash()'s 31-bit space made a silent wrong-map filename collision
a ~1-in-16k event per cap-full body; migration self-heals via the orphan
sweep). Tier-3 class doc rewritten to name the real D-253 seam — the
glaciation/flooded_q wire fields exist but carry static values and no
staleness signal crosses the wire; T-1190 tracks threading a wire TTL
into put(sim_ttl_sec) when the driving clock lands — replacing the false
'no sim-state wire field exists' premise. Four new tests plus a
_stub_canvas fixture helper centralizing the canvas shape contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 11:36:21 +02:00
jpmschweitzerandClaude Fable 5 6b76e365bb feat(ui): client disk cache — FileAccess tiers beneath the LRU (D-255, T-1183)
step_canvas_disk_cache.gd: the Tier 2/3 store per D-255(d) and the
round-2 three-tier spec. Payload is the WIRE, pre-decode — store_var/
get_var round-trips the PNG-encoded PackedByteArrays natively, and
Image.load_png_from_buffer never runs in this file. One composite key
shared verbatim with Tier 1 (hash filenames for filesystem safety);
per-body index.json with malformed-index recovery (rebuild-or-discard,
never crash).

Three independent eviction mechanisms, exactly as ruled: rung-0 Global
carries a retention floor no sweep touches (now also threaded into
Tier 1 per the T-1182 handoff); Tier 2 geometry is byte-valid forever
and evicts only by time-since-last-visit (14d starting tunable, on
body-open) and LRU byte budget (256 MiB/body, 5-min coarse timer) —
two separate sweeps; Tier 3 sim-state TTL is wired and tested but has
no production caller yet (no sim-state field exists on
EncodedStepCanvas — the D-253 stub inheritance, documented).

Hardening per D-255(d), both mandatory: per-body deep-rung cap
(512 Block+Chunk entries, enforced synchronously in put(), floor- and
budget-independent — the ticket sanctions count-or-quota; count chosen
as the direct D-226(d) information-content proxy) and a schema/version
tag on every entry (project.yaml version via the existing
loading_screen line-scan idiom — D-192 co-ship makes the client
version the wire-schema version; exact-inequality mismatch = miss +
drop, NEVER decode, checked in both has() and get_canvas()).

Integration: request_now() checks Tier 2 on a Tier-1 miss (synchronous
promote), Ready responses write through to both tiers, Pending never
writes; viewer runs the visit sweep on body-open + the background
sweep on a 5-min timer.

30 new disk-cache tests + 7 request-integration + 3 sweep-wiring tests
(restart persistence, sweep independence both directions, cap
semantics, version-mismatch never-decode, corrupt-index recovery).
Full client suite 3,440/3,440, 0 orphans; cold-parse clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 11:08:48 +02:00