Commit Graph
2664 Commits
Author SHA1 Message Date
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
jpmschweitzerandClaude Fable 5 df33e9f2fb fix(simulation): per-body TerrainAnalysis LRU + full-path determinism test (PR #187 C1/C3)
C1 (Tyre): the DeriveWindow branch re-ran the ~45ms run_layer1 for
EVERY uncached window — the dominant pan-around-one-body path paid
~52ms per new window while the doc claimed one-time-per-body.
TerrainAnalysisCache: private per-body LRU (capacity 8, ~2MB/entry,
true access-recency eviction — which body the player keeps panning IS
a recency signal) held as Arc<Mutex<>> on GenerationQueue itself, the
in_flight field pattern, because run_work_item executes on a Rayon
worker where the main-thread caches are unreachable. DeriveWindow now
calls get_or_derive; the variant doc states the real model (first
window per body pays ~45ms once; subsequent windows any center/n hit
the LRU; eviction re-pays). End-to-end test proves two windows on one
body via two connections share exactly one cache entry.

C3 (Tyre): the determinism test reused one TerrainAnalysis — proving
the packer, not the derivation. New test runs run_layer1 twice
independently, asserts field-by-field analysis agreement, then
byte-identical packed windows end to end (D-227 save-critical proof).
Packer-only test kept alongside.

atlas:: 564/564; full lib 1778/1778; timing-sensitive suites 3x stable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:56:58 +02:00
jpmschweitzerandClaude Fable 5 ec3b429316 chore(meta): T-1137/T-1138 to review — PR #187 up (regional-window batch)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:36:16 +02:00
jpmschweitzerandClaude Fable 5 15aea9c450 chore(meta): file T-1141 — regional-window header label + doc-line follow-ups (T-1138 flags)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:32:36 +02:00
jpmschweitzerandClaude Fable 5 9e1e6db614 feat(ui): T-1138 regional map screen — click-through descent, fixed planetary view, windowed composite (D-226 T-1124 SS5)
Entry per Jeroen's 2026-07-21 revision: planetary heightmap is now
FIXED — all drag-pan/wheel-zoom input removed (set_view/get_view_*
capture API survives for the golden harness); hover shows a
not-to-scale bracket reticle with the real extent labeled (a true
n=32 rectangle is sub-pixel on the planetary canvas — the honest
representation given the morph transition is deferred), and a click
that misses every city marker descends (city-click wins — one
gesture, two contextual reads, no modifier). Descent pushes a new
'district' nav screen centered on the click point's DistrictPos via
atlas_descend_geometry.district_pos_at (the pixel-to-district inverse
of the server mapping, verified against scale.rs).

Regional mode: atlas_window_viewer draws the composite (morphology x
elev_q lightness base; temp/moisture/veg toggles — temp reuses the
region-ramp colorizer exactly; Marine=6 transparent; glaciation
always-on tint matching apply_ice_tint's REAL gate, None|Light no-op,
over the amendment's looser prose — documented); pan-on-held-composite
with edge-crossing refetch + border-fade during the queue-based
derive wait; zoom never refetches. atlas_window_cache: LRU keyed
(body_id, center, n), touch-on-read, evict-only, no freshness (D-227).
atlas_window_request mirrors the generation-proxy pending-retry shape
for None-until-derived. Codec: window params omitted from the wire
when absent — byte-identical for every existing caller.

Live-verified against the T-1137 server in-worktree: real round-trip
on a GJ380c coastal district (6 fields x 1024 cells), echo staleness
guard, genuine ~1.4s background-derive wait, pan-edge refetch to an
adjacent window, cache-hit on re-descent with zero network. Full
client suite 3194/3194; gdlint clean on all 18 files.

Open follow-ups flagged in-code: header location label always falls
back to coordinates (nearest-settlement needs a join the district
window does not carry); atlas_standalone.gd's 'atlas_app.gd is never
modified' doc line is now imprecise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 13:32:06 +02:00
jpmschweitzerandClaude Fable 5 172ce124c8 feat(simulation): T-1137 windowed district layer — queue-served, coalesced, determinism-tested (D-226 T-1124 SS1-SS4)
AtlasLayerRequest gains window_center/window_n (serde-default, absent
= whole-body, wire back-compat; demux untouched — up_to stays the
discriminator). DistrictWindowLayer echoes center/n + six parallel
arrays (morphology, elev_q, temp_dc i16 with the region sentinel,
moisture_q, vegetation incl Marine=6, glaciation).

Serving per the amendment's binding model: NEVER inline —
GenWorkItem::DeriveWindow rides the Rayon queue, completion drain
caches into DistrictWindowCache (bounded FIFO 256; no staleness by
D-227 purity, capacity bound only), serve_district_window polls the
cache and returns Pending-shaped None until derived. Per-connection
coalescing: submit_window supersedes a still-pending item for the
same (ConnectionId, body) — the surviving item is the newer one,
proven by dedicated tests.

TerrainAnalysis decision (option b, numbers in ticket/PR): re-derive
via run_layer1 in the DeriveWindow branch rather than caching ~1.5MB
x 50 LRU slots (~100MB permanent, the exact D-203 bloat T-1044's own
text guarded against); ~45ms one-time on the Rayon path, invisible to
the tick thread. T-1044 confirmed within-cascade-only (cascade.rs:358
still drops the analysis before BodyWorldState) — the fork was open.

Window derive loop promoted from aliveness_probe::render_window_panels;
determinism promoted from probe-only proof to a real test (two passes
byte-identical). New fixture atlas_response_ready_with_window
exercises all six arrays incl. the airless sentinel and Marine; three
existing fixtures gain district_window: None. Server clamps window_n
to 1..=DISTRICT_WINDOW_MAX_N=64 (never trust the wire).

1774/1774 lib + 19/19 bridge_tcp green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 12:13:59 +02:00
jpmschweitzerandClaude Fable 5 bb4506213a chore(meta): activate regional-window batch — T-1137/T-1138 in progress (atlas-regional-window worktree; Dudley serving + Stig screen)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 11:53:33 +02:00
jpmschweitzerandClaude Fable 5 f6db47f4a1 docs(config): sweep retired .internal names — Gitea at git.schweitz.net, connectors by IP
Jeroen confirmed the .internal-to-.net proxy migration was intentional
(2026-07 weekend maintenance): git.schweitz.internal's vhost is gone,
git.schweitz.net is live with a LE cert and AdGuard LAN hairpin.
tea-cli.md + local-services.md repointed (tea's own config already
switched). tooling/db/config.json: the bare tower-of-joy hostname has
no DNS entry since the migration — Stable Audio/Trellis endpoints now
by IP. Workshop archives under docs/workshops/ keep their historical
.internal mentions (records, not operative config).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 11:51:09 +02:00