Commit Graph
100 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Fable 5 7c5dc35b38 docs(meta): D-226 two-waterline note (T-1172 — Tyre's rung-indexed-coast ruling)
The drawn coastline is a family of curves indexed by rung (warp cutoff
admits more octaves at finer rungs), so no single authoritative server-
side waterline exists — reconciliation is a presentation-frame
operation at the draw site; the skeleton stays rung-independent. Clip
retires into T-1170's coast-terminating courses.

Tickets: T-1172

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 10:19:08 +02:00
jpmschweitzerandClaude Fable 5 48340cb6f6 chore(meta): T-1172 filed — river skeleton draws over drawn ocean (two-waterline disagreement, Jeroen's hands-on report)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 10:14:07 +02:00
jpmschweitzerandClaude Fable 5 ee5ed4e08a chore(meta): close T-1156 wave 1 — PR #195 merged (rivers/basins/attractors on the ladder, triple review)
Tyre APPROVE after one fix round (attractor stroke-width compensation,
D-226 visibility-direction capture); Hoshe APPROVE after one fix round
(named default-visibility pins; execution-grade verification incl. own
golden structural diff and independent revert-tests; full gate
3770/3770 at final tip); Araminta APPROVED all four captures after her
District trunk-dot objection was fixed to her exact ask. Cold
re-verified on MERGED main (.cache/screenshots/rivers-main/). Wave 2
(civilizational overlays) stays deferred on the re-scoped T-1156...
wave-2 notes ride the ticket. Unblocked: T-1168 riparian contract,
T-1170 course invention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:35:46 +02:00
jpmschweitzer e8149d011e Merge remote-tracking branch 'origin/rivers-ladder' 2026-07-23 09:33:53 +02:00
jpmschweitzerandClaude Fable 5 c1cae7c9b5 test(ui): named default-visibility pins for nature overlays (PR #195 Hoshe finding)
RVR-on-by-default is the single most player-visible behavior wave 1
ships (rivers appear with no toggle hunt) and was only exercised by
live captures; gen_basins' default was pinned incidentally inside the
toggle-redraw spy test and gen_attractors not at all. One named test
now asserts all three fresh-construction defaults per Araminta's
ruling (RVR on, BAS off, ATR off). Revert-verified: flipping the
gen_rivers init line fails exactly this test by name (1 failure total
in the 78-test suite). Suite 78/78; gdlint clean.

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:26:55 +02:00
jpmschweitzerandClaude Fable 5 273a1634be chore(meta): PR #195 review captures — T-1171 pole-entry wobble filed; T-1170 per-basin note; T-1156 wave-2 sibling-layer note
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:16:25 +02:00
jpmschweitzerandClaude Fable 5 8a747e332c fix(ui): PR #195 review round — attractor stroke widths zoom-compensated (Tyre I1/I2/I3)
I1: _draw_attractor_shape's three stroke-width args (Confluence arc,
Coastal/NaturalHarbor arc, Oasis spokes) were raw screen-space literals
— Godot multiplies stroke widths by canvas scale exactly like radii, so
at the Region orbital fit zoom the outlines rasterized at ~0.01px, the
identical sub-pixel class the dot/ring compensation fixed, missed on
glyph internals (and attractors are Region-only — precisely where it
bites). Widths now arrive pre-compensated via a px_w param, keeping the
primitive pure. Regression pin: a source-scan test asserting no
draw_arc/draw_line in the function carries a bare numeric width (the
draw-smoke suite documents its own vacuous-pass mode, so source-scan is
the environment-independent gate); revert-verified by name. I2: D-226
visibility-direction sentence — Araminta's fade-down inversion recorded
as pre-T-1170 with its single revisit point named. I3: class-header
call-site claim corrected (enter() funnels through _enter_at_rung).

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:14:47 +02:00
jpmschweitzerandClaude Fable 5 0366e8286f fix(ui): District trunk dot 2.0px/80% — Araminta's PR #195 capture objection
At 1.6px/60% the trunk dot under the mouth ring read as 'mouth glyph
over plain terrain' — invisible without knowing where to look,
underselling the ruling's own 'a major river crosses near here'
intent. 2.0px/80% preserves the fade-down ladder vs Region's
2.2px/100% without reading as accidentally-erased. Doc comment
records the revision provenance.

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:06:38 +02:00
jpmschweitzerandClaude Fable 5 f4711d631d chore(meta): T-1156 wave 1 to review — PR #195 up (rivers-ladder)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 09:03:15 +02:00
jpmschweitzerandClaude Fable 5 5a382c2e56 style(simulation): cargo fmt — assert message wrap in drainage tests
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 08:59:48 +02:00
jpmschweitzerandClaude Fable 5 60faf667a5 fix(ui): T-1156 live rounds — zoom-compensated marker sizes; toggle-redraw regression pin
Live round 2 (the real bug): every nature-overlay marker size was a raw
screen-space constant drawn inside _canvas, whose scale IS view_zoom —
at Lendel's orbital fit zoom (0.0063) a 2.2px trunk dot rendered at
~0.014px, invisible; the same code at District's 3.75 zoom produced the
correctly-visible mouth ring, which is why one capture worked and the
headline rung didn't. Fixed via AtlasWindowGeometry.zoom_compensated_
size() (pure, floor-guarded) wired through every radius/line-width;
basin FILL points are positions and correctly stay unscaled. Suspect
tile-mode-rung-detection was ruled out live (granularity_v2=Region
confirmed in tile mode) but pinned with a named regression test anyway.
+8 pure-function tests incl. a numeric pin of the pre-fix magnitude
(<0.02px at orbital zoom); revert-verified by name. Draw-smoke suite
documented as supplementary (the shared SubViewport background harness
can pass vacuously under X11 BadMatch — the pure suite is the gate).

Live round 3 (drive-script bug, no product change): the lead's scratch
drive passed the button LABEL to set_overlay_visible() and the unknown-
id guard silently no-op'd — but the chase banked a real pin:
test_set_overlay_visible_gen_basins_flips_gate_and_redraws_nature_
overlay (draw-counting spy per the cold-start precedent; is_queued_for_
redraw does not exist in this build). Revert-verified.

Basins verified live: 7 Lendel watershed boundaries render at the
ruling's alphas. Suites: viewer 76/76, geometry-nature 42/42, nature-
overlay 22/22, zoom-ladder 50/50, no regressions across the cluster.

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 08:55:29 +02:00
jpmschweitzerandClaude Fable 5 0d22e50e66 feat(ui): T-1156 — rivers/basins/attractors re-hosted onto the zoom ladder (nature overlay node)
New AtlasWindowNatureOverlay (Node2D on the viewer canvas, above
terrain): self-connects to the shared atlas_layers_received broadcast
(the established one-signal-N-consumers shape) and consumes the whole-
body layer1 skeleton per Tyre's carrier ruling — no windowed wire
touched. Coordinate chain layer1_pixel_to_world_m -> world_m_to_
district -> canvas-local lives in atlas_window_geometry as pure tested
functions; vertical convention (row 0 = North pole, wy increases
south) verified against the server's own pixel_to_world_m, pinned by
pole tests and revert-verified (sign flip fails them by name).
Araminta's per-rung presentation table implemented exactly: Region
full skeleton (radii 0.9/1.4/2.2, confluence 3.5, mouth double-ring),
District trunk-only 1.6px at 60% with mouths at full landmark styling,
Quarter off until T-1170 course invention; retired palette reused
verbatim; RVR on / BAS off / ATR off defaults; missing river_class
falls back to trunk. 58 new tests (34 geometry, 22 lifecycle, 2 real-
driver draw smoke actually rendered); 11 existing atlas suites
regression-free. atlas_window_viewer.gd runs 16 lines past the
advisory 1000-line cap on trivial wiring — accepted, rides T-1158's
decomposition.

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 08:23:59 +02:00
jpmschweitzerandClaude Fable 5 ff98a10d42 feat(simulation): T-1156 — quantized river_class on RiverNetwork (trunk/tributary/stream)
The one additive server change of wave 1 per Tyre's carrier ruling:
river_class: Vec<u8> parallel to river_cells, serde-default-safe, no
new wire field. Log-scaled binning between RIVER_THRESHOLD and the
RIVER-RESTRICTED max accumulation (max over cells passing the is_river
elevation filter — NOT the grid-wide max, which peaks past the
coastline on wet large-ocean bodies and would starve the trunk class
exactly where Araminta's District-shows-trunk-only table needs it;
caught in lead review of round 1, fixed round 2). Log not linear
because accumulation grows combinatorially downstream. By construction
every body with rivers has trunk cells — pinned by a non-synthetic
regression on the committed GJ1c heightmap at the golden's exact
downsample. cascade_layer1.json regenerated: every pre-existing field
byte-identical (python-verified), only the new river_class arrays
added — GJ1c distribution stream 72 / tributary 18 / trunk 3.
drainage 16/16 (+10), layer1 3/3, layer_proxy 50/50, build --tests
clean; revert-verified (non-monotonic binning fails the monotonicity
test by name).

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 08:10:00 +02:00
jpmschweitzerandClaude Fable 5 365b044e79 docs(meta): D-226 wave-1 nature-overlay carrier note (T-1156 — Tyre's ruling)
Rivers/basins/attractors ride the existing whole-body layer1 field —
neither AtlasLayerResponse ceiling touched, no tagged-envelope
migration. Per-rung refinement is client-side class filtering on the
additive river_class (distinct from T-1162's server-side Nyquist
cutoff: a fixed finite graph has nothing to truncate). General rule:
discrete map features ride the whole-body overlay family filtered
client-side; continuous per-metre fields ride the windowed per-cell
arrays — wave 2's roads/settlements inherit this unchanged. Riparian
vegetation response is the named T-1168 forward contract, deferred.

Tickets: T-1156

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 08:04:12 +02:00
jpmschweitzerandClaude Fable 5 5155474d14 chore(meta): T-1156 wave-1 design pass captured — T-1168 riparian forward contract, T-1169 labels split-out, T-1170 river-course invention (all gated behind wave 1)
Tyre's carrier ruling: rivers ride the EXISTING whole-body layer1 field
(no new wire field, neither ceiling touched); per-rung refinement is
client-side class filtering (river_class quantized from flow
accumulation — the one additive server change); discrete-geometry-vs-
continuous-field carrier rule established for wave 2. D-226 note added
on the rivers-ladder branch. Si's audit: skeleton is 512x256 heightmap-
resolution dot data (~76 km/cell) — planetary courses real now, sub-
heightmap course geometry named as T-1170, labels split to T-1169
(three dormant pieces, not free).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 07:54:41 +02:00
jpmschweitzerandClaude Fable 5 64a65f52e1 chore(meta): activate T-1156 wave 1 — rivers/basins onto the ladder (rivers-ladder worktree)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 07:49:17 +02:00
jpmschweitzerandClaude Fable 5 825ea9749f chore(meta): close nature-first batch — T-1162/T-1161 done (PR #194 merged, triple review), T-1155 cancelled as superseded
Tyre APPROVE after one fix round (I1 rung-floor dependency direction
implemented as his stronger ask + drift guard; I2 comment cites; I3
governance captures in his exact text; I4 golden body coverage; all
non-blocking follow-ups swept, none parked). Hoshe APPROVE (empirical
revert checks; his one nit refuted with the diff hunk and formally
retracted). Araminta APPROVED the T-1161 acceptance captures. Cold
eyeball re-verified on MERGED main (.cache/screenshots/nature-octaves-
main/): Region NEAREST crisp, Quarter coast crinkle intact, filters
runtime-verified. T-1155 cancelled: superseded by T-1161's two-axes
outcome per Tyre's Q4 ruling.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:39:37 +02:00
jpmschweitzer 153b4113b5 Merge remote-tracking branch 'origin/nature-octaves' 2026-07-22 23:37:30 +02:00
jpmschweitzerandClaude Fable 5 972842c320 style(simulation): cargo fmt — const assert line wrap
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:36:11 +02:00
jpmschweitzerandClaude Fable 5 e5a68f4445 docs(simulation): sweep the last pre-I1 floor-framing comment (Tyre's non-blocking follow-up)
DISTRICT_MIN_WL_M's doc in window_derivation_golden.rs still carried
the 'NOT 2×DISTRICT_M by coincidence alone' framing the I1 fix
inverted everywhere else — now states the rung authors the floor and
the terrain-octave coincidence is guard-pinned, matching the rewritten
MIN_WL_BANDS_M and coast_invention docs.

Tickets: T-1162

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:34:53 +02:00
jpmschweitzerandClaude Fable 5 f50c93b2c8 docs(meta): PR #194 I3 — §8 step 6 erratum + D-226 filter-axis note (T-1161 two-axes supersedes COMPOSITE_SMOOTH retirement)
Tyre's exact capture: the design pass's 'retire COMPOSITE_SMOOTH /
crisp draw_rect as the only path' is superseded — the const survives
as the compile-time pipeline axis, the crisp path stays as debug/
compare, and crispness-at-sparse-rungs is delivered by the per-rung
sampling-filter policy instead. T-1155's retirement framing is
cancelled (ticket closes on merge). Also records the R2 softening:
the T-1162 relief band adds sub-district elevation variance at
Quarter cutoff, so temperature no longer steps strictly at the
district there — intended, noted so nobody is surprised later.

Tickets: T-1161, T-1162

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:31:31 +02:00
jpmschweitzerandClaude Fable 5 3368891976 fix(simulation): PR #194 review round — rung-floor dependency direction, golden body coverage, doc honesty
Tyre's I1 (his ruling: the cutoff's job is Nyquist, a property of the
RUNG): MIN_WL_BANDS_M's District band now derives from 2*DISTRICT_M
directly, decoupled from OCTAVE_WAVELENGTHS_M[3] — a detail_scatter
retune can no longer silently redefine the Atlas rung floor. Direction-
agnostic const assert pins the coincidence so drift on either side
breaks the build for a deliberate human decision; golden_cutoffs_match_
the_scale_ladder now pins the District coupling too. I2: D-226
paraphrase replaced with cites to the T-1150 wire-contract note +
T-1162 refinement resolution (2), plus a self-found stale 2048m claim
fixed in the same comments. I4: golden extended with airless/dry
(ceiling_q==0 short-circuit) and volcanic-coast (ridged warp) body
rows via body_sweep_samples() — fixture regen verified 510 insertions,
0 deletions (existing rows byte-identical, purely appended). Q2 nit:
vegetation_invention module doc now states majority-preservation as
the coherence guarantee, not per-cell class stability (a boundary
cell's flip IS the clearing mechanism). Forward-contract for T-1156:
0x5EED_C0DE promoted to named WINDOW_RELIEF_SALT const. 158 focused
tests green; cargo check --tests clean.

Tickets: T-1162, T-1161

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:31:14 +02:00
jpmschweitzerandClaude Fable 5 918855c878 chore(meta): T-1162/T-1161 to review — PR #194 up (nature-octaves); T-1167 gdlint-debt ticket filed
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:13:04 +02:00
jpmschweitzerandClaude Fable 5 a5b9c28e74 style(simulation): cargo fmt — gate bounce on T-1162 files
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 23:09:48 +02:00
jpmschweitzerandClaude Fable 5 d33256a8ba test(simulation): regenerate believability golden — deliberate T-1162 output change
The octave extension changes derived window output by design (coast
crinkle below 16384m, voxel relief at Quarter, vegetation moisture
perturbation) — this regen records the sanctioned new baseline per the
ticket's part (d) discipline. The pre-existing BELIEVABILITY_STRICT=1
'vegetation present' advisory failure predates this change (Q-123-
tracked debt) and is unaffected.

Tickets: T-1162

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 22:56:48 +02:00
jpmschweitzerandClaude Fable 5 5cb63b6867 feat(simulation): T-1162 — invention octaves into the Atlas window path (coast crinkle, quarter relief, vegetation patchiness)
Coast: WARP_OCTAVE_WAVELENGTHS_M 5->9 entries (262144m down to 1024m,
Quarter's Nyquist floor) with new min_wavelength_m cutoff plumbing in
coast_warp_px/warp_fbm (the warp previously had no cutoff at all).
Relief: invent_primitives feeds the VOXEL band (1024-128m, salted) into
elev_q/slope_q under the same envelope/cutoff discipline. Vegetation:
new vegetation_invention module — two-tier (BodyParams+latitude envelope
ceiling; single blended fBm field, never-gated 100-400km massif tier at
70% + cutoff-gated district/voxel texture at 30%) perturbing moisture_q
OUTPUT so precipitation/glaciation/vegetation shift as one world-fact;
wire format unchanged. MIN_WL_BANDS_M 5->6 (adds 1024m band).

Mid-implementation correction caught by tests: District's quantized
floor is 4096m (OCTAVE_WAVELENGTHS_M[3]), not 2x DISTRICT_M — the 8192m
and 4096m coast octaves are legitimately District-admitted enrichment;
only 2048/1024m coast + the voxel band are Quarter-exclusive. Docs and
golden cutoffs corrected to match.

New golden: tests/window_derivation_golden.rs + fixture (derivation_
harness pattern, UPDATE_GOLDEN=1 regen) with structural guards pinning
Quarter/District divergence. Bench (zoom_ladder_bench, release): no
regression — all rungs at or below baseline (District c0 3.54->~3.0
us/cell, Quarter 2.10->1.77, orbital 1.48->1.42, n=6400 window
0.86->0.59 ms). Revert-verified voxel_relief cutoff exclusion. Server
lib 1840 passed; new module 11 tests; district_profile 84 (+6, 1
noise-fragile pre-existing test properly fixed via 8-district
latitude-band averaging).

Tickets: T-1162

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 22:56:34 +02:00
jpmschweitzerandClaude Fable 5 c9028af77e feat(ui): T-1161 — per-rung composite filter policy (Region NEAREST, District/Quarter LINEAR)
Araminta's ruling (PR #192 follow-up): filter keyed on rung IDENTITY via
the window's own echoed granularity_v2 — Region (incl. the orbital tile
mosaic, whose tiles are all Region-rung requests) samples NEAREST because
GPU bilinear at 204.8 km/cell reads as smoothing-over-absence; District/
Quarter keep LINEAR where cell density earns the blend. One shared helper
(_filter_for_granularity_v2) at both draw call sites; unknown/missing
wire tags fall back to LINEAR (never trusted into NEAREST). COMPOSITE_
SMOOTH survives as the independent compile-time pipeline axis — the
two-axes split is documented in the file header. Washes/border fades
untouched per the ruling. Focused suite 44/44; revert-verified (helper
hardcoded LINEAR -> exactly the three Region-NEAREST tests fail).

Tickets: T-1161

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 22:36:05 +02:00
jpmschweitzerandClaude Fable 5 ffc24b7312 chore(meta): T-1162 refinement resolutions — bench-baseline-first, window-derivation golden as explicit scope, vegetation invention net-new mirroring coast_invention
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 22:28:01 +02:00
jpmschweitzerandClaude Fable 5 e41a8dcc8d chore(meta): activate nature-first batch — T-1162 + T-1161 in progress (nature-octaves worktree)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 22:25:39 +02:00
jpmschweitzerandClaude Fable 5 bbe9099e22 chore(meta): close T-1163 — PR #193 merged (cold-launch starvation fix); review captures T-1164/T-1165/T-1166 filed
Tyre + Hoshe both APPROVE at 8bb09abad (one Hoshe fix round: wrong-body
Pending regression + comment dedupe, both revert-verified independently).
Cold acceptance re-verified on MERGED main: fresh release server, first
connection, Lendel converged mosaic inside 2s, stable while unattended,
legend one-legend-tall (.cache/screenshots/cold-start-main/). Review
tickets: T-1164 tiled terminal-recovery, T-1165 repaint-edge root-cause,
T-1166 scripted cold-launch test tier (both under T-1037 where noted).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 21:30:03 +02:00
jpmschweitzer 6d80936b65 Merge remote-tracking branch 'origin/ladder-cold-start' 2026-07-22 21:22:34 +02:00
jpmschweitzerandClaude Fable 5 8bb09abad0 test(ui): wrong-body Pending must not touch retry state (PR #193 Hoshe finding 1)
Pins on_response()'s guard ordering: body_id check BEFORE the status
branch, so another body's cold Pending can never burn one of our 30
retries or reschedule our timer (multi-body browsing / shared-broadcast
tile fan-out). Revert-verified: reordering the guards makes this test
fail; final own-body Ready assertion proves the request is genuinely
untouched, not just un-retried. 44/44 in the file.

Tickets: T-1163

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 21:15:47 +02:00
jpmschweitzerandClaude Fable 5 4c34327b41 docs(ui): PR #193 review capture — D-226 pending-shape protocol note + stagger comment dedupe
Tyre's APPROVE items (T-1163): record the two-legal-wire-shapes-for-one-
logical-state protocol invariant (whole-response Pending AND Ready+null
district_window both mean 're-poll'; only NotFound/Error are terminal) as
a D-226 note under the T-1124 §4 amendment area, so a future server
refactor of the asymmetry must migrate every consumer in the same change.
Drop the duplicated 5-line stagger comment in atlas_window_tile_set.gd.

Follow-up tickets filed on main: T-1164 (tiled terminal-recovery),
T-1165 (queue_redraw edge root-cause), T-1166 (cold-launch test tier).

Tickets: T-1163

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 21:11:22 +02:00
jpmschweitzer cf1733cdd6 chore(meta): T-1163 — cold-launch starvation bug (ladder-cold-start branch, in review) 2026-07-22 20:59:22 +02:00
jpmschweitzer 3891c83206 fix(client): cold-body Pending responses reach the retry path — the launch-shape starvation root cause
The true cause of the black first launch, server-confirmed after four
disproven theories: a stone-cold body answers the FIRST window request
with a whole-response status 'Pending' (only the whole-body cache-hit
branch sets Ready), and on_response()'s very first check — status !=
Ready -> return — swallowed it before the retry machinery could run.
retries stayed 0 forever; the DERIVING state never resolved. Second
connections worked by luck (the first request warms the whole-body
cache, so they read Ready and take the healthy path). Both tile fan-out
AND single-window first-descents were affected — one shared function,
one fix: branch on the outer status first (the atlas_generation_proxy
reference shape): Pending -> retry, Ready -> existing null-window retry,
NotFound/Error -> give up immediately (the principled give-up policy,
replacing the elapsed-retries ceiling).

Hardening in the same round: deterministic exponential backoff (0.5s
doubling, 4s cap) + per-tile stagger (0.1s * index — six tiles retry at
0.5/0.6/0.7/0.8/0.9/1.0s, strictly-increasing asserted, not jittered);
MAX_RETRIES 20->30 (~110s horizon under backoff).

Regressions are wire-accurate by construction: whole-response Pending
(body_id only, no center/n/granularity — verified against the server's
own response construction) delivered through the REAL fan-out
(tile_set._on_atlas_layers_received, never tile.on_response directly),
mirrored at single-window level. Two first-draft tests that passed with
the bug reverted were caught and strengthened before reporting; every
fix and hardening piece revert-verified independently (7+1 failing
tests without them).
2026-07-22 20:56:46 +02:00
jpmschweitzer ddc4483462 test(simulation): connection-zero district_window delivery regression (bridge_tcp)
Dudley's audit of the suspected ConnectionId(0) starvation: exhaustive
trace of the delivery path (bridge/mod.rs insert/lookup/send paths,
atlas plugin serve/drain, gen_queue coalescing) found NO sentinel or
default-value collision — ConnectionId doesn't even derive Default, and
every id path is a plain monotonic allocation with linear lookup. The
real gap was coverage: every existing window test used ConnectionId(1).

New connection_zero_window_delivery module replicates main.rs's actual
bootstrap (blocking first-accept -> BridgeResource -> accept loop) and
pins: the first-ever connection receives a district window; the exact
six-tile entry shape delivers all six to connection 0; connection 1
keeps working. 5/5 repeated runs, single- and parallel-threaded.

The live 'starvation' itself was client-side (pending responses never
re-requested on the tile path — separate fix in flight); these tests
stay as the server half's permanent pin.
2026-07-22 20:32:09 +02:00
jpmschweitzer dd13760d62 fix(client): cold-start round 2 — DERIVING TERRAIN state, legend re-fit, release server for make atlas
Item 1: while zero tiles have arrived, the viewer draws a centered
screen-space 'DERIVING TERRAIN…' label (text_dim role, no new hue),
dropping the instant the first tile lands — a cold wait now reads as
loading, not broken. New has_any_tile_arrived() predicate (distinct
from has_pending_tiles(): both true mid-arrival, tested exactly there).

Item 2: legend re-fit root-caused empirically, two plausible fixes
disproven by trace before the real one: a manually-positioned Control's
size NEVER tracks a shrinking minimum in this parenting shape, and
RichTextLabel.fit_content reports degenerate minimums until laid out at
real width once — so reset must be DEFERRED and run after refill, not
inside clear(). ImplantPanel.reset_to_content_size() (call_deferred),
wired into both legend refresh()es. The load-bearing test compares
size.y to get_minimum_size().y — a size-to-size comparison passed
trivially with both numbers equally stuck (caught on first draft).

Item 3: make atlas now builds the RELEASE server and passes
SR_SERVER_BIN (a cold DEBUG server delivers zero tiles for >10s on a
new body — live-measured — vs 210ms warm; release serves cold in well
under a second). atlas_standalone._server_binary_path() honors the env
override per the SR_PORT two-tier precedent, debug path unchanged
when unset.

All fixes revert-verified; nine suites green collateral-checked;
gdlint clean.
2026-07-22 19:51:12 +02:00
jpmschweitzer d4526e51ff fix(client): cold-start black screen — self-healing tile repaint, legend re-entry root cause, pending-tile wash
Jeroen hit a black mosaic zooming into a body from a fresh make-atlas
spawn. Live diagnosis showed all six tiles held with colored textures
and no repaint; the original line-specific diagnosis (unpaired
queue_redraw in _on_tile_ready) turned out WRONG — the pairing already
existed (lead's truncated grep misread the function; Stig verified via
git log -p before acting). Rather than chase the exact dropped signal
edge, _process() now self-heals: both viewer and overlay redraw every
frame while the tile set has pending tiles (has_pending_tiles(), new) —
a strict superset that closes the black regardless of which edge drops,
pinned by a _draw()-counting real-subclass spy test.

Legend stacking root cause found by trace, not guess: ImplantApp.
_on_screen_changed() re-runs enter() unconditionally on repeat
same-screen pushes — each re-entry tore down and rebuilt all six tile
requests (the round-6 orphaning fingerprint via a new trigger) and
stacked another legend (~10 deep, full-height dark panel). Fixed both
ends: ImplantPanel.clear() frees immediately (same-frame re-entrant
refresh can never observe stale children — protects every implant app),
and RegionalScreen.enter() no-ops for the same body (different body
still re-enters fresh). The load-bearing regression asserts an ARRIVED
TILE'S DATA survives a repeat push — node identity would not catch the
teardown (the tile-set Node is a fixed field; only its internals reset).

Cold-start UX: pending tiles now draw the single-window path's
COLOR_BORDER_FADE wash instead of raw background — a deriving mosaic
reads as loading, not broken.

Suites green (zoom_ladder 48, viewer 74, tile_set 20, overlay 30,
overlays 46 + 2 new files), gdlint clean, revert-verified throughout.
2026-07-22 19:05:15 +02:00
jpmschweitzer 74662470c6 chore(meta): nature-layer scope ruling — T-1162 gains vegetation patchiness, T-1156 split into nature-first waves (cities uncolored for now, per Jeroen + D-166 outside-in) 2026-07-22 18:33:11 +02:00
jpmschweitzer 0a69710ca5 chore(meta): T-1162 — extend invention octaves into the window path (Jeroen's flatness/coastline feedback; content floor 4km/16km vs 512m transport) 2026-07-22 18:30:52 +02:00
jpmschweitzer 41017166aa chore(meta): zoom ladder shipped — T-1152/T-1153 closed (PR #192 merged, triple review, six live rounds, eight integration bugs pinned) 2026-07-22 17:40:55 +02:00
jpmschweitzer 919660c5ae Merge remote-tracking branch 'origin/zoom-ladder-continuous' 2026-07-22 17:40:20 +02:00
jpmschweitzer da15261276 fix(client): PR #192 review round — per-rung legend, Region coalescing + clamp boundary tests, halving-loop honesty
All Hoshe/Araminta findings addressed (Tyre approved outright), none
retracted — plus a Dudley stop-and-flag discovery that improved on the
asked-for fix:

- Legend 100x lie (Araminta, blocking): subtitle computed via
  spacing_for_rung() and refreshed at all three _held_granularity_v2
  write sites. Region test asserts 204.800 km/cell; the District
  direction needed a stale-header-aware helper — a District-only test
  spuriously passes against the old literal by coincidence.
- Region coalescing coverage (Hoshe 1): both directions tested
  (Region-vs-District separate slots; Region-vs-Region coalesces).
- Clamp boundary tests + dangling citations (Hoshe 2): writing the
  requested halving-loop-fires test surfaced that the loop is PROVABLY
  UNREACHABLE at current constants (per-axis clamp forecloses it —
  brute-forced independently on both server and client sides). Ruling:
  the loop stays as defensive code; the test became a property sweep
  pinning both the wire-cap invariant and the loop's no-op status (a
  future constant change breaks it loudly); doc comments on both sides
  drop the load-bearing framing and state the truth; the old client
  mirror test that claimed the loop fires (passing on the per-axis
  clamp alone) is replaced the same way. Client citations now name the
  real server tests verbatim.
- Governance (Tyre): D-226 amendment note — progressive cross-rung
  refinement EXTENDS T-1124 §4 (not supersedes); legacy u32 field
  scheduled for retirement (T-1159).

Server: 1818 lib tests green, clippy/fmt clean. Client: zoom_ladder
48/48, window_request 26/26, viewer 74/74; gdlint clean. Every fix
revert-verified.
2026-07-22 17:24:07 +02:00
jpmschweitzer 15f0b6936d chore(meta): PR #192 review follow-ups — T-1158 (viewer decomposition), T-1159 (legacy u32 retirement), T-1160 (orbital coastline audit), T-1161 (per-rung filter policy) 2026-07-22 17:05:18 +02:00
jpmschweitzer ab41ea07f9 chore(meta): T-1152/T-1153 to review — PR #192 up (zoom ladder); T-1157 smoke-scenario migration note (Stig) 2026-07-22 16:51:06 +02:00
jpmschweitzer 8517cae66f fix(client): draw smoke — guarded early-return instead of fuzzer-arg skip (gdUnit leaks one internal Node per skipped test, exit 101 bounced the gate at 0 failures) 2026-07-22 16:48:21 +02:00
jpmschweitzer 8414b0fd18 fix(client): T-1153 round 6 — zoom floor at the canonical frame; reset guard purely edge-triggered
The round-5 per-tick zoom comparison inside the reset guard was level-
triggered: at the canonical frame every continued zoom-out tick drifted
_view_zoom a hair below fit, read as 'not there', and re-fired
enter_orbital — tile set torn down/recreated per tick, in-flight
responses orphaned (black entry), server flooded (889 of 897 responses
in one drive phase). The drift concern now lives in _zoom_at as a ZOOM
FLOOR (once at the canonical frame, zoom-out clamps at fit); the guard
keys only on fields that never drift (_held_center/_held_granularity_v2/
_tile_mode) — genuinely edge-triggered. Three shared helpers keep the
guard and the floor on one definition of 'canonical frame'.

Anti-storm regression drives 100 real _zoom_at ticks past the first
reset and asserts tile-set child node identities never change; the
black-entry repro interleaves Lendel's six wire-accurate tile responses
with continued ticks and asserts all six held. Both revert-verified with
the exact live symptoms. Round-5 reset tests pass unchanged. Live-
verified twice: exactly 6 requests at entry and at reset, no storm.
2026-07-22 16:21:31 +02:00
jpmschweitzer ccedba4f24 fix(client): T-1153/T-1152 round 5 — nearest-wrap-image tile draw placement; canonical reset restores the fit zoom and re-fires
The wrapped tile column (Lendel: -6400 canonicalized to 12739) drew at
its canonical column — off-canvas right — leaving the mosaic's left
third black. nearest_wrap_image() re-expresses a tile column as the
wrap-image closest to held_center for DRAWING only (requests/cache keys
stay canonical). The draw-position test asserts overlap FRACTION, not
bare intersects() — the buggy placement still clipped ~2px of viewport
edge at Lendel scale, so intersects() alone would false-pass.

The full-zoom-out reset restored center but not the fit zoom, and its
'already there' guard keyed on a lagging field so it could only ever
fire once. The guard now also matches tile mode and compares _view_zoom
against the freshly computed fit — restoring the FULL canonical
transform (center, offset, fit zoom) and re-firing as a continued
gesture keeps zooming out (Jeroen's hard condition, both live shapes).

+8 revert-verified tests incl. the continued-gesture reset repro; smoke
stub gained get_body_radius_km (crash confirmed real under a real
driver before fixing). Suites 286 green; gdlint clean.
2026-07-22 15:32:04 +02:00
jpmschweitzer 493a7345d3 fix(client): T-1153/T-1152 round 4 — mosaic canvas-local frame, offset recompute on rung crossing, tile texture RID lifetime; real-driver draw smoke
Three live-found rendering bugs, all invisible to green unit suites:
- _draw_tile_mosaic placed tiles from absolute district (0,0); canvas-
  local (0,0) is held_center - held_n/2 everywhere else, and tile-mode
  held_n is the whole-body extent — the entire mosaic drew tens of
  thousands of px off-canvas. New pure district_to_canvas_local() +
  viewer accessors route every tile through the shared frame.
- _maybe_reselect_rung updated held_n across crossings without
  recomputing _view_offset — the single-window composite landed off-
  canvas the moment any crossing happened (why District/Quarter were
  black too). New pure recompute_offset_for_held_n_change().
- _build_tile_texture created an unstored ImageTexture per _draw,
  racing the RenderingServer's deferred upload — CPU pixels correct,
  screen white. Per-tile-index texture cache, same reference-identity
  discipline as the single-window _cached_texture.

Structural close of the twice-bitten 'nothing asserts pixels' gap:
test_atlas_window_overlay_draw_smoke.gd renders overlay output into a
SubViewport and asserts visible pixels for both modes — runs under a
real driver (invocation documented in DEVOPS.md, visual_capture
precedent; migration to the T-1157 harness noted on that ticket), skips
loud-but-green under the gate's headless run (verified green-with-skips
AND genuinely red with detection forced off). +7 geometry/crossing
tests, all revert-verified. Targeted suites 270 green; gdlint clean.
2026-07-22 14:41:00 +02:00
jpmschweitzer 9ffda88e57 docs(docs): §5 erratum superseded — unified coverage-ceiling rung model + tile mode as merged (T-1153 round 3) 2026-07-22 13:04:07 +02:00
jpmschweitzer 6195fd28b3 fix(client): T-1153/T-1152 round 3 — unified rung coverage model, reselect clamp mirror, orbital tile-set mosaic
Bug A (zoom reselection dead): select_rung() redesigned from the two-gate
split to a unified per-rung coverage-ceiling walk (MAX_COVERAGE_M,
finest-first) — which also restores District as a reachable rung
(33-131km extent band; the two-gate model had made it structurally
unreachable). Plus the THIRD instance of the PR #191 C1 clamp-mirror bug
class: _maybe_reselect_rung fed the old rung's _held_n raw into the new
rung's request — the server clamped, the held value didn't, every
cross-rung response stale-dropped. Re-clamped at the boundary; the
leaving_tile_mode flag also fixes a stale request-granularity edge case.

Bug B (orbital = whole body): genuine tile-set model. compute_tile_grid
composes ceil-divided Region-tile centers (canonicalized column wrap,
row clamp, Dictionary-set dedup; Lendel = 3x2 = 6 tiles);
AtlasWindowTileSet owns one AtlasWindowRequest per tile (reusing all
tested request/cache/debounce machinery), fans responses out, per-tile
tile_ready — genuinely progressive; the overlay draws arrived tiles as a
mosaic under the one view transform. enter_orbital branches to tile mode
when >1 tile; single-window path unchanged below the coverage ceiling.
E/W wrap at tile seams live-confirmed (col -6400 wraps to 12739). Pole-
row dedup verified correct but flagged honestly as currently-unreachable
defensive logic (no real radius triggers row collision).

All fixes + fallout verified via revert/confirm-fails/restore. Targeted
suites 256/256; gdlint clean; new 20-test tile-set suite.
2026-07-22 13:03:38 +02:00
jpmschweitzer 11f7927f24 fix(client): T-1153 — v2 granularity is authoritative in the staleness guard; legacy compared only when v2 absent
Second live-round blocker: the T-1150 legacy granularity comparison
stayed armed alongside the v2 check, and the server ALWAYS sends the
u32::MAX Region sentinel in the legacy slot — which can never equal the
client's pinned legacy value, so every Region response was stale-dropped
after the v2 check passed. _echoed_granularity_matches() now branches on
PRESENCE of granularity_v2: present -> v2 is the only comparison; absent
(old server) -> legacy fallback.

Mock-fleet audit while fixing: three tests had responses diverging from
the real wire — the oversized-orbital round-trip omitted the legacy
sentinel (passed for the wrong reason), the Region-accept test used
legacy=1, and the mismatch-drop test left v2 at a masking default that
would have inverted under the new rule. All wire-accurate now with a
named SERVER_LEGACY_GRANULARITY_REGION_SENTINEL const; +2 tests (legacy-
only old-server acceptance; v2-wins-regardless-of-legacy precedence
proof). All three verified to fail against the reverted fix. Full suite
3524/3524.
2026-07-22 12:07:33 +02:00
jpmschweitzer 1c87b6a712 fix(client): T-1153 — clamp _held_n at the viewer's single write site (live eyeball round blocker)
The live round against a real server caught what 3518 unit tests missed:
enter_orbital stored the UNCLAMPED n (Lendel: 19139 raw circumference
cols) into _held_n while AtlasWindowRequest clamped independently to
6400 before sending — every orbital response on a real-sized body was
dropped by the viewer's own w_n != _held_n staleness check. Permanently
blank ladder. The PR #191 C1 clamp-mirror lesson, one layer up: the
mirror must apply wherever held/expected state is recorded, not only at
the request layer.

_enter_at_rung now clamps via _clamp_window_n_mirror_v2 before storing
(the file's only _held_n write site — reselect/refloat read and forward).
Regression closes the coverage hole: the oversized-orbital RESPONSE
round-trip (enter_orbital on GJ380c -> deliver echo n=6400 Region ->
assert accepted). Both new tests verified to fail against the reverted
fix before trusting green. Full suite 3520/3520.
2026-07-22 11:54:06 +02:00
jpmschweitzer 5aa3a84263 chore(meta): T-1156 (overlay port onto the ladder) + T-1157 (capture-harness redesign) — T-1153 deferral follow-ups 2026-07-22 11:42:59 +02:00
jpmschweitzer 55a2909386 docs(docs): §5 erratum — rung-selection rule's literal form has no District band; two-gate split as implemented (T-1153) 2026-07-22 11:42:22 +02:00
jpmschweitzer ce90d69ae8 feat(client): T-1153 + T-1152 client half — continuous cursor-anchored zoom ladder, Region-rung orbital entry, click-through retired
The atlas 'regional' screen now opens the LADDER at the canonical orbital
frame (Region granularity, whole body fitted and centered) and wheel zoom
descends continuously — cursor-anchored, unclamped across rungs, with
progressive refinement (held composite keeps drawing, finer rung swaps in
place on arrival; no blank frame, no mode flip). Full-zoom-out resets to
the canonical planetary frame per Jeroen's HARD condition
(is_fully_zoomed_out = extent >= body circumference, not a zoom-value
heuristic). The district_screen nav hop is deleted — D-013 restored:
descent is a zoom gesture, not a nav push. AtlasViewer's heightmap-texture
path is unreachable from nav (code intact; overlay surface deferred, see
report/tickets).

Rung selection: design doc §5's literal formula has NO legal District band
at any real viewport (visual-tolerance band and n=64 coverage ceiling
never overlap — pinned by executable boundary tests at 1600x900);
select_rung() splits it into a coverage ceiling (decides Region) then the
2x visual tolerance (District vs Quarter), documented at the function.
In practice the ladder steps Region -> Quarter directly.

Wire: window_granularity_v2 encoded (omitted at District for byte-compat),
granularity_v2 echoed value keyed + staleness-guarded end to end; Region
clamp mirror replicates the server's bounded halving loop (no closed
form). MIN/MAX_ZOOM widened to [0.0005, 64] — the old 0.5 floor would
have clamped a real body's canonical fit zoom, violating the reset
condition.

Real pre-existing bug fixed in atlas_window_overlay.gd: the draw path used
echoed n as both cell-grid dimension and district extent — only
coincidentally correct at District granularity; Quarter/Region would have
read wrong array offsets. cell_grid_side_for_window() now mirrors the
server's WindowGranularity::cell_grid_side.

Tests: +26 pure-function geometry tests, new 30-test zoom-ladder suite,
extensions across the window cache/request/overlay/delivery suites.
Full suite 3518 green; cold-parse clean.
2026-07-22 11:41:37 +02:00
jpmschweitzer d356b09926 feat(simulation): T-1152 server half — WindowGranularity enum, derive_orbital_at_metres, Region rung on the same carrier
R1 measured first: a capped Region tile through the real production path
(build_district_window_layer + T-1151 par_iter) at the 64x64 wire cap
costs 0.40-0.48ms — faster than the shipped district n=64 window, so
Jeroen's progressive capped-density tiling ruling is comfortably
interactive on-demand. Raw orbital derive ~0.9µs/cell (~2.3x faster than
full derive; region_baseline dominates, not invent_primitives).

R5 redesign: WindowGranularity enum (Quarter/District/Region), serde
named-variant per the RoadNodeKind precedent, spacing from D-243 scale::
constants — the single source of truth. Additive serde-default
window_granularity_v2 request field (None = legacy u32 path; v2 wins when
Some); DistrictWindowLayer.granularity_v2 always echoed. Legacy u32 echo
for Region uses reserved WINDOW_GRANULARITY_REGION_KEY = u32::MAX (never
a legal input) so the old slot cannot lie about aliasing. Cache and
coalescing keys carry the enum itself (Ord by declaration order, D-010).

n stays district-extent at every rung; Region's cell grid is a DIVISION
(round(n/100), min 1) with its own per-axis ceiling
DISTRICT_WINDOW_MAX_N_REGION=6400 and a bounded halving-loop clamp (no
closed form under the rounding division — the client mirror must
replicate the loop).

derive_orbital_at_metres: bilinear envelope reads + region_baseline
temperature, NO invent_primitives (proven by test — slope_q pinned 0),
routed through the shared build_district_profile classification tail so
the existing colorizer family renders orbital cells unchanged. R2
stepped-categorical behavior documented at the function, not implied.

Region aliasing + clamp/echo tests mirror the T-1150 discipline. 1813
lib tests green; clippy clean; fixture regenerated (254->278 bytes, new
echoed field).
2026-07-22 10:35:37 +02:00
jpmschweitzer 2a4597e108 chore(meta): activate zoom-ladder-continuous batch — T-1152/T-1153 in_progress 2026-07-22 10:01:06 +02:00
jpmschweitzer 896c923d35 chore(meta): zoom-ladder foundations done — T-1149/T-1150/T-1151 closed (PR #191 merged, double review + fix round); T-1152/T-1153/T-1154 now unblocked 2026-07-22 00:54:42 +02:00
jpmschweitzer d02754f6cc Merge remote-tracking branch 'origin/zoom-ladder-foundations' 2026-07-22 00:54:14 +02:00
jpmschweitzer 1ce4085901 style(simulation): cargo fmt on the fix round + governance amendment typo (Hoshe nit) 2026-07-22 00:51:22 +02:00
jpmschweitzer 0159a63cc2 fix(simulation): PR #191 review round — n-clamp mirror, min_wl band quantization, coalescing coverage, fixture consumer
All seven Hoshe/Tyre findings addressed, none retracted:
- n-clamp/echo/staleness triangle (Tyre C1): client _clamp_window_n_mirror
  (bit-for-bit twin of the server clamp, canonicalize_district_center
  precedent) applied before _n is stored/sent; server test pins the
  quarter n=32 -> echo 16 contract.
- min_wl band quantization (Hoshe 1/Tyre C3): quantize_min_wl_m snaps to
  MIN_WL_BANDS_M {0, 32768, 16384, 8192, 4096} before cache key and echo
  (design doc §5's unbounded-key fix), reusing the one true
  OCTAVE_WAVELENGTHS_M array; docstrings now state the server-quantizes/
  client-sends-raw split; same-band cache-sharing test.
- coalescing granularity axis (Hoshe 2): two tests pin different-
  granularity requests as separate in-flight slots and same-granularity
  coalescing unchanged.
- orphaned fixture (Hoshe 3): test_protocol.gd consumer decodes
  atlas_response_ready_with_window.msgpack through the real IPC path and
  asserts the new fields.
- atlas_window_request coverage (Hoshe 4): new test file — stale-drop on
  granularity mismatch, old-server-shape defaults accepted, clamp mirror
  formula + wiring. First draft's quarter-via-request_now test would have
  passed for the wrong reason (request_now resets granularity by design
  until T-1153) — split into formula pin + reachable-path wiring proof.
- granularity type seam (Tyre C2): field + resolver docstrings state
  finer-only integer multiples with resolve_window_granularity as the
  single widening point; matching contract note added to the D-226
  T-1143-rulings amendment.

cargo --lib 1807/1807; goldens bit-identical; gdlint clean.
2026-07-22 00:47:53 +02:00
jpmschweitzer fdd529f576 chore(meta): T-1149/T-1150/T-1151 to review — PR #191 up (zoom-ladder foundations) 2026-07-22 00:28:55 +02:00
jpmschweitzer 3e87fd5b4f feat(simulation): T-1151 window par_iter + T-1150 granularity carrier (five touch points + aliasing tests)
T-1151: build_district_window_layer dispatches one Rayon task per row
(pure derive_window_cell via derive_at_metres), scattered row-major into
the flat arrays; a cfg(test) serial path backs the bit-identical
parallel-vs-serial golden.

T-1150: serde-default window_granularity (1=district, 4=quarter) +
window_min_wl_m on AtlasLayerRequest — additive, no sixth demux shape,
old frames decode unchanged (tested). Quarter mode = full
reclassification at 512m spacing over the same world rect ((4n)x(4n)
cells); WIRE_CAP_CELLS=4096 enforces n*granularity <= cap (quarter
clamps n to 16, the design doc's worked example). Granularity + min_wl
key ALL five touch points: DistrictWindowLayer echo, server FIFO-256
cache key (now a 5-tuple), per-connection coalescing key, client
request codec (omitted-at-default wire fields), client LRU key.

Mandatory aliasing regressions on both ends: identical (body, center, n)
at granularity 1 vs 4 produce distinct cache entries and correct
per-granularity payload shapes (server, 3-thread queue to avoid the
AnalyzeBody thread contention found while writing it) and distinct
client cache keys (gdUnit). Replay fixture regenerated — the layer
struct grew two echoed fields (231->254 bytes, content verified).

Client requests stay district-granularity by default — quarter requests
arrive with T-1153's rung selection.
2026-07-22 00:27:40 +02:00
jpmschweitzer afff859a2c feat(simulation): T-1149 derive_at_metres extraction + min_wavelength octave cutoff
Extract derive_district's fractional-metres interior into the metres-
addressable derive_at_metres(seed, body, params, ta, wx, wy, climate,
min_wavelength_m) — the zoom ladder's keystone (design doc §8 step 1).
derive_district is now a thin DistrictPos-quantizing wrapper calling it
with cutoff 0.0; all four golden/believability/derivation harnesses pass
byte-identical.

enveloped_fbm/terrain_detail/voxel_relief gain min_wavelength_m: octaves
below the cutoff are hard-truncated (amp still advances so surviving
octaves keep relative weight; norm==0 guarded). Amplitude-fade-near-
cutoff is documented as a seam, not built — the pop-risk A/B needs the
client ladder (T-1153). Cutoff 0.0 is bit-identical to pre-change
output, asserted by test.

Measured (release, 4096-cell sweeps, zoom_ladder_bench.rs): district
spacing 1.200µs/cell (cutoff 0) / 1.201µs (cutoff 2048m — all octaves
survive, plumbing check); quarter spacing 1.165µs/cell (cutoff 512m).
Matches the design doc's ~1.2-1.4µs/cell release estimate.
2026-07-22 00:27:21 +02:00
jpmschweitzer 43323e88d2 chore(meta): activate zoom-ladder-foundations batch — T-1149/T-1150/T-1151 in_progress 2026-07-21 23:50:55 +02:00
jpmschweitzer 143d6381ca docs(meta): T-1143 rulings — D-226(d) floor opened, progressive-tiling planetary carrier, continuous seam zoom; implementation chain T-1149..T-1155
Jeroen's three rulings on the zoom-ladder design pass, recorded as a
D-226 amendment: (1) 'we set a new BHAG so old restrictions are up for
debate' — the item-(d) ceiling opens for the Atlas windowed viewport
(below-quarter rungs gated on the T-1154 measurement pass; chunk/tile
still never a whole-body planetary layer); (2) planetary rung ships as
progressive capped-density tiling on the generalized district_window
carrier; (3) planetary->regional entry becomes continuous cursor-anchored
zoom with full-zoom-out resetting to the canonical orbital frame (D-013
zoom-owns-descent restored; click-through cut superseded).

Design doc stamped with the resolved rulings. T-1143 closed. Implementation
chain: T-1149 (derive_at_metres + octave cutoff) -> T-1150 (granularity
carrier + aliasing test) / T-1151 (window par_iter) -> T-1152 (derived
planetary rung) / T-1153 (client continuous ladder) -> T-1155 (smoothing
retirement); T-1154 below-quarter measurement gate.
2026-07-21 21:52:55 +02:00
jpmschweitzer c8d3fe6560 docs(docs): T-1143 Atlas zoom-ladder design pass — rung table, serving model, planetary rung, migration path
Tyre/Dudley/Araminta design round with Troblum adversarial critique and
completeness audit folded in (9-agent pass). Recommends: generalize the
district_window carrier with serde-default granularity + min-wavelength
params (no sixth demux shape); quarter rung as full reclassification at
512m; derive_at_metres extraction from derive_district's interior as the
keystone step; planetary rung as progressive capped-density tiling.
Carries measured-vs-estimated cost discipline and six explicit risks.
Decisions reserved for Jeroen: the D-226(d) floor question (stop at
quarter recommended), the planetary wire carrier, and the planetary-seam
interaction ruling.
2026-07-21 21:30:40 +02:00
jpmschweitzer a292e2d2ef chore(meta): T-1143 in_progress — zoom-ladder design pass running (Tyre/Dudley/Araminta + Troblum critique) 2026-07-21 21:12:46 +02:00
jpmschweitzer bc204262be docs(meta): D-166 amendment corollary — heightmap PNGs demoted to invisible derivation input; planetary level fully derived at canvas resolution
Jeroen's same-day corollary to the zoom-ladder condition: no zoom level
displays the authored heightmaps directly — even the orbital/planetary map
is derived output, sampled at canvas resolution (continuous field, not
fixed rasters). Kills zoom over/undersampling by construction and makes
the map viewport-adaptive. import_heightmaps survives as input storage
only; AtlasViewer's texture display path retires when the derived
planetary rung lands. T-1143 design pass extended with items (e)-(g).
2026-07-21 21:06:46 +02:00
jpmschweitzer 51c8cb86cd docs(meta): D-166 amendment — seamless Atlas zoom ladder is a hard Phase-4 deliverable condition
Jeroen's ruling from the Groombridge/Lendel zoom-ladder captures: the BHAG
stays 'a Reach a character can travel through'; the Phase 4 exit bar now
additionally requires a continuous Atlas zoom ladder (planetary map -> tile
scale, each level deterministically derived at native granularity, never
magnified interpolation). Evidence in the record: the 16-district window is
sub-pixel vs its heightmap source at Lendel scale, so everything below fit
zoom is D-227 invented detail that must be derived, not smoothed.

CLAUDE.md Phase-4 row carries the condition; T-1143 (the ladder design
pass) appended + raised to high — it and the D-226(d) floor question are
now phase-gating.
2026-07-21 21:02:06 +02:00
jpmschweitzer aa8dfe948b chore(meta): T-1146 done — PR #190 merged (implant input gate, double review + fix round) 2026-07-21 20:02:53 +02:00
jpmschweitzer 0fd744c7a5 Merge remote-tracking branch 'origin/implant-input-gate' 2026-07-21 20:02:32 +02:00
jpmschweitzer 32a7b1e425 fix(client): T-1146 review round — gate the T-1088 seams, kill the settle fallback tautology, neutralize AutoPause leak
PR #190 review (Hoshe + Tyre), all five findings addressed:
- Tyre: queue_move_step/queue_stance_toggle (the T-1088 click-to-move seams)
  now share the full suppression predicate — all three input_queue producers
  in the module are gated, making the header's 'every action this file can
  produce' claim true (previously the seams relied on the sandbox caller's
  own freeze). +3 regression tests.
- Hoshe: the live suite's settle=baseline timeout fallback compared baseline
  to itself, vacuously passing the no-movement claim — a timeout now fails
  loudly (both tests).
- Hoshe: the unit suite's real open_app/close_app transitions fire the
  global auto-pause handler; with ambient SimBridge.state left CONNECTED by
  earlier suites (test_hub_teleport has no after_test) each transition
  silently appended AutoPause/AutoResume to the shared _outbound_buffer.
  before_test now forces DISCONNECTED (restored in after_test) and clears
  the buffer.
- Hoshe: documented why the live suite's reset_test_state() call is inert
  but still correct.

Full suite: 3374/3374.
2026-07-21 20:00:18 +02:00
jpmschweitzer 629b9082b3 chore(meta): T-1146 to review — PR #190 up (implant input gate) 2026-07-21 19:52:21 +02:00
jpmschweitzer 196ecb8a98 chore(meta): T-1148 — hunt leaked gdUnit scene-tree pollers (T-1146 fix-round evidence) 2026-07-21 19:50:52 +02:00
jpmschweitzer 4af3dd2607 test(client): T-1146 — full-suite isolation for the occlusion-gate suites
Unit suite: pin facing to North via the T-1088 facing_angle_provider seam.
D-054 makes movement facing-relative, and _update_facing_from_mouse() derives
facing from engine/session globals (viewport mouse position vs the
GameState.player_position anchor) — in full-suite order 'press W' resolved to
MOVE_NORTHWEST (the gate failure at line 187).

Live suite, three independent leaks from the shared autoloads, each of which
passed in isolation and failed in gate order:
- snapshot starvation: poll_snapshot() is consume-and-clear; a node leaked
  into the gdUnit tree by an earlier suite steals every snapshot during our
  awaits. Capture snapshot_received (fires on every consume, ours or theirs)
  alongside a direct poll + explicit SimBridge._process pump.
- tick poisoning: SimBridge left test_mode=true + CONNECTED lets the leaked
  poller apply TestHarness mock snapshots (~tick 15+) into
  GameState.current_tick during our spawn awaits; the fresh server's own
  ticks (1..5) then stamp backward and its InputQueue panics ('tick ordering
  violated', last=16 new=3). Neutralize SimBridge before the first await,
  zero current_tick, clear _last_snapshot/_outbound_buffer both directions.
- crash-on-assert-failure: gdUnit asserts don't halt; guard the player-entity
  dereferences so a missing Player reports cleanly instead of a runtime error.

Full suite: 3368/3368.
2026-07-21 19:49:42 +02:00
jpmschweitzerandClaude Fable 5 cd52fe8843 fix(client): T-1146 gameplay input gated while an implant screen occludes gameplay
InputMapper polled the D-054 move_* actions (and queued discrete
gameplay actions) unconditionally — WASD with a fullscreen implant
open walked the character blind. Poll-site gate (both _process and
_unhandled_input, the file's existing dialogue/free-camera early-return
idiom): nothing is enqueued while occluded, so no backlog can flush on
close.

Gate signal is HudGroups.gameplay_occluded, deliberately NOT
is_implant_active(): that flag is also true for INSERT mode (economics
monitor panel), where gameplay stays visible and playable by design —
the naive gate would have broken WASD there. Local _gameplay_occluded
mirror via the existing signal; regression tests pin the INSERT
distinction.

Held-state semantics: open-while-held stops on the next poll;
close-while-held requires release-then-repress (a
_suppress_move_until_release latch armed on the close transition,
cleared only when EVERY movement key is released — one-of-two released
does not clear, tested). Facing exempt from the latch (re-sync, not
lurch).

Audited action set: movement/facing-send/INTERACT/perception/pause/
stance/teleport/quicksave-load gated; OPEN_MENU exempt (Esc must close
the implant), BUG_REPORT/OPEN_JOURNAL exempt (client-only, never reach
send_input); dialog-driven direct SimBridge sends (settings, dialogue
pause, quit-to-menu save) out of scope by design. The pre-existing
server-side AutoPause defense observed firing correctly alongside.

Drive-by: pre-existing gdlint class-definitions-order violation in
input_mapper.gd fixed (public/private var ordering) — file lint-clean
for the first time.

Tests: 16 unit/state (real autoloads, real open_app/close_app
transitions, Input.action_press engine state) + 2 LIVE against a real
spawned server through the REAL client pipeline (position frozen for
20 held-W ticks while occluded; still frozen 10 ticks after close
without re-press; resumes on re-press) — port-retry/wall-clock/
COOLDOWN_TICKS conventions reused from test_input_roundtrip. 12-suite
regression sweep of every InputMapper consumer green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 19:16:12 +02:00
jpmschweitzerandClaude Fable 5 94990ec910 chore(meta): T-1143 — Jeroen's LoD ruling (sub-district pixels over gradients; seamless zoom-LoD; D-226(d) floor question flagged)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 19:00:51 +02:00
jpmschweitzerandClaude Fable 5 cdc5396c21 chore(meta): activate T-1146 — implant-open input leak fix
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 18:56:08 +02:00
jpmschweitzerandClaude Fable 5 aa06bc9fca chore(meta): close T-1145 — PR #189 merged (round-2 polish, zero review findings)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 17:09:15 +02:00
jpmschweitzer 8910182d92 Merge remote-tracking branch 'origin/atlas-regional-polish' 2026-07-21 17:07:58 +02:00
jpmschweitzerandClaude Fable 5 c906a9df00 chore(meta): T-1145 to review — PR #189 up (regional polish round 2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 17:03:51 +02:00
jpmschweitzerandClaude Fable 5 fd7d8fcfde chore(meta): file T-1147 — margin-less fog-shader perf ceiling flaked the gate (0.501 vs 0.500ms)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 17:01:15 +02:00
jpmschweitzerandClaude Fable 5 372ce37bb6 feat(ui): T-1145 round-2 polish — cover-fit, WASD+edge-scroll pan, smoothed composite (Jeroen rulings)
Cover-fit: fit_window_view zooms from the viewport's LARGER dimension,
no margin factor (any factor under 1.0 leaves a long-axis gap — checked
numerically) — the composite fills edge to edge, overhanging the short
axis into pan-space; the refloat center-equality early-return already
prevents refetch churn at rest (proved, not just tested).

Input model (Jeroen: drag breaks click semantics with map objects):
LMB-drag pan REMOVED from the regional window; clicks are
object-reserved. Pan = held WASD/arrows polled in _process (delta- and
zoom-scaled, camera-pans-toward-key convention verified numerically)
plus edge-scroll within 24px of the viewport border; both suppressed
over UI and on OS focus loss; both set _user_adjusted; wheel zoom and
Esc unchanged. Reads RAW physical keycodes deliberately — independent
of the shared D-054 move_* InputMap actions bound to the same keys
(whose occlusion-leak is pre-existing and now ticketed as T-1146).
Pole wall + east-west wrap unchanged, re-driven through the new
inputs; drag tests replaced, not kept.

Smoothed composite (interim pending T-1143): per-cell colors bake into
an n x n Image/ImageTexture (exact existing colorizer incl. overlay +
ice tint) drawn once with LINEAR filtering — GPU bilinear reads as
terrain, the planetary heightmap's own treatment. Crisp per-cell path
preserved behind COMPOSITE_SMOOTH for T-1143 A/B. Rebuild only on
reference-identity change of window/toggle (is_same — verified true
reference equality; value-equal distinct dicts DO rebuild).

Governance: T-1145 amendment paragraph on D-226 T-1124 SS5 (all three
supersessions); pql decisions validate ok.

Suites: window_viewer 74/74, window_geometry 32/32, window_overlay
(new) 16/16; gdlint clean on all six files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 16:51:24 +02:00
jpmschweitzerandClaude Fable 5 256f259a17 chore(meta): file T-1146 — gameplay movement leaks to server while implant open (T-1145 finding)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 16:50:43 +02:00
jpmschweitzerandClaude Fable 5 848fa12003 chore(meta): file+activate T-1145 (round-2 friction: cover-fit, WASD pan, smoothing); expand T-1143 with sub-district sampling design
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 16:17:55 +02:00
jpmschweitzerandClaude Fable 5 9bfd86309a chore(meta): close T-1142 — PR #188 merged (descent fixes, live full-chain verified)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:27:10 +02:00
jpmschweitzer af07672c5b Merge remote-tracking branch 'origin/atlas-descent-fixes' 2026-07-21 15:25:53 +02:00
jpmschweitzerandClaude Fable 5 7ce6cc08fd test(ui): pin the _user_adjusted resize guard both ways; fix coalescing doc overstatement (PR #188 review)
Hoshe's finding: the flag introduced so auto-fit never fights a manual
view had zero coverage on exactly that branch. Two tests drive the
REAL _gui_input path (synthetic drag), then fire NOTIFICATION_RESIZED:
user-adjusted view survives a resize untouched (zoom AND offset);
an unadjusted view re-fits to the new viewport. 52/52.

Non-blocking doc note also taken: layer_proxy's normalization comment
claimed the twins would otherwise 'coalesce independently' — the
coalescing key is (ConnectionId, body_id) and never carried center;
rewritten to say what normalization actually buys on that path (the
work item derives and echoes the canonical center).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:22:24 +02:00
jpmschweitzerandClaude Fable 5 d426059cb6 chore(meta): T-1142 to review — PR #188 up (descent fixes, live full-chain verified)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:12:04 +02:00
jpmschweitzerandClaude Fable 5 ce71abec28 chore(meta): file T-1144 — atlas_viewer.gd structural extraction (at gdlint cap two rounds running)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:53:58 +02:00
jpmschweitzerandClaude Fable 5 831625019a fix(ui): T-1142 client — descent bounds gate, fit-and-center, pole wall, east-west wrap, body-name header
Bounds gate: AtlasDescendGeometry.is_on_texture() — ONE helper feeding
both the reticle guard and the click fall-through (the T-1140 lesson:
the visible affordance always matches the click); half-open
[0,tex_w)x[0,tex_h) boundary pinned at the exact edge. Letterbox
clicks no longer show a reticle or descend.

Fit-and-center: pure fit_window_view() (new atlas_window_geometry.gd)
wired into enter(), the FIRST window arrival, and NOTIFICATION_RESIZED
— gated by a _user_adjusted flag so the fit never fights manual
zoom/pan (flag clears only on a fresh enter). Found-own-bug: RESIZED
can fire mid-_ready() before _canvas exists — null-guarded like the
sibling panels.

Pole wall (Jeroen's ruling): clamp_pan_offset_to_pole_wall() clamps
the WINDOW EDGE, not the center, in screen space from the fitted
transform — Y only; wired into the drag handler and every fit (a
fresh fit can itself need the wall on a tiny body — the
window-taller-than-planet case is handled and tested). Three numeric
hand-traces preceded the code; a first-draft test using GJ380c's huge
radius silently never exercised the clamp — replaced with a synthetic
small radius.

East-west wrap (Jeroen's ruling): canonicalize_district_center() —
posmod column wrap (verified against a live Godot process to match
Rust rem_euclid bit-for-bit), clamped row; district_extent() shares
the exact formula (incl. .max(1)) with the server's
normalize_window_center so echoes and cache keys agree on canonical
form. Canonicalization applies only to the FINAL refetch center — the
edge-crossing decision stays in absolute district space (first-pass
math error caught by hand-trace). Seam-adjacent cache-key sharing
tested. Pan offset itself has no x wall — circumnavigation is
seamless.

Header: body proper_name/body_id ahead of the coordinates (the cheap
half of T-1141, noted in code). Drag-pan verified through the REAL
DistrictScreen-to-viewer chain and pinned by test (no fix needed).

140 tests across three suites, 0 failures; 94 sibling tests no
ripple; gdlint clean (atlas_viewer.gd at the 1000-line cap a second
round — structural extraction flagged for maintenance).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:53:32 +02:00
jpmschweitzerandClaude Fable 5 4a65bb210d fix(simulation): normalize window_center before cache and coalescing keys (T-1142 server half)
The server clamped window_n but trusted window_center — the letterbox
bug's impossible (12276, 3021) was derived at clamped-garbage latitude
and CACHED under its raw key. normalize_window_center mirrors the
forward map exactly (column rem_euclid against the body's district
circumference, row clamped to +/-half-meridian; constants from
scale::DISTRICT_M, no new magic numbers; no-radius test bodies
identity). Applied in serve_district_window BEFORE the window-cache
key and the coalescing key, so an insane request and its sane twin
share one entry — proven end-to-end with the literal bug values on a
500km fixture body resolving to canonical (4, 383), byte-identical.

Echo contract: DistrictWindowLayer.center now carries the NORMALIZED
value. Reconciled by design with the client half in this same branch —
the client canonicalizes before sending (bit-identical math, posmod ==
rem_euclid verified), so request and echo agree from the first
round-trip; server normalization is defense-in-depth for buggy or
modified clients.

6 new tests incl. the twin-cache proof and the echo pin; atlas::
570/570, lib 1784/1784, timing-sensitive tests 3x stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:52:50 +02:00
jpmschweitzerandClaude Fable 5 7ac3335d77 chore(meta): activate T-1142 — descent bounds/fit fix round (atlas-descent-fixes worktree)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:21:04 +02:00
jpmschweitzerandClaude Fable 5 e7319cf322 chore(meta): file T-1142 (descent bounds + fit bugs, Jeroen hands-on) + T-1143 (quiet-interior legibility)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:19:31 +02:00
jpmschweitzerandClaude Fable 5 4ad3b1b352 chore(meta): close regional-window batch — T-1137/T-1138 done (PR #187 merged, triple review, 6 findings fixed incl. the off-equator descent bug)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 14:04:05 +02:00
jpmschweitzer 64d26995fc Merge remote-tracking branch 'origin/atlas-regional-window' 2026-07-21 14:02:42 +02:00
jpmschweitzerandClaude Fable 5 96f6baa930 docs(meta): D-226 T-1124 prose corrections — real TerrainAnalysis cost model + glaciation gate (PR #187 C1/C4)
SS4: the 7/29ms per-window figures now state their warm-analysis
assumption — the first window on a body additionally pays one ~45ms
run_layer1 into the lazy per-body LRU on the GenerationQueue
(capacity 8, browsed-bodies-only, recency eviction, eviction re-pays);
subsequent windows any (center, n) hit the LRU. SS5: the glaciation
tint gate corrected from >= Light to >= Moderate, matching
apply_ice_tint's reference gate (Light is erosion signatures, not
visible ice) — code stood, prose was wrong.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:57:45 +02:00
jpmschweitzerandClaude Fable 5 4eed3bccb2 fix(ui): latitude-inverse denominator + reticle city-hover gate (PR #187 findings)
Hoshe's blocking find: district_pos_at divided the latitude axis by
tex_h where the server forward map uses ta.h.saturating_sub(1)
(district_profile.rs:1436; ground-truth inverse aliveness_probe.rs:511)
— every off-equator click descended into the wrong district, up to
~20km drift, live-repro'd at 10.2km. Fixed to /(tex_h - 1.0) with the
reference implementation's degenerate-texture guard; verified against
the repro (row 50: old formula recovered 41, fixed recovers 50 exact).
Columns were already correct (longitude wraps — the asymmetry the
docstring documented but the code didn't implement).

Regression tests transcribe the server forward formula (source cited)
and round-trip three off-equator rows — one per hemisphere plus
near-pole — asserting EXACT recovery; a dedicated drift guard is
framed as Tyre's C2 (a client-side twin of a server mapping owns its
own round-trip proof). Root-caused the coverage hole: the old
equator test sampled tex_h*0.5 believing it was the equator pixel —
the true equator is (tex_h-1)*0.5, so the test never verified what it
claimed; corrected with the why documented.

Araminta's find: the descend reticle drew unconditionally on hover —
over a city the marker flared white (city-click signal) while the
reticle+extent label promised descent, though the click correctly
resolved to city data. Extracted _should_draw_descend_reticle() with
the missing _hovered_city.is_empty() clause; three state tests pin
shows-over-map / hides-over-city / hides-when-idle.

test_atlas_descend_entry 32/32; adjacent clusters no ripple; gdlint
clean (atlas_viewer.gd at exactly the 1000-line cap).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:57:28 +02:00