Commit Graph
2636 Commits
Author SHA1 Message Date
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
jpmschweitzerandClaude Fable 5 5e21aa8935 chore(meta): close T-1140 — PR #186 merged (companion friction round 1)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:30:56 +02:00
jpmschweitzer b7d58c0bcc Merge branch 'atlas-companion-friction' 2026-07-21 09:30:09 +02:00
jpmschweitzerandClaude Fable 5 d149803405 chore(meta): idmap re-export after branch switch preserves T-1140 mapping
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:30:01 +02:00
jpmschweitzerandClaude Fable 5 6db63d033b chore(meta): T-1140 to review — PR #186 up
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:28:51 +02:00
jpmschweitzerandClaude Fable 5 872aea041f fix(ui): overlay bar empty flow area must not eat map input (PR #186 review)
Hoshe's finding: the wrap fix gave the bar container the full
header-adjacent width, and with ALIGNMENT_END + the pre-existing
MOUSE_FILTER_STOP that left a ~700px dead strip (1920px screens) left
of the chips silently swallowing map clicks/drags near the top edge —
a regression the wrap change introduced by widening the rect without
revisiting the filter. Two edits: the container is now
MOUSE_FILTER_IGNORE (the legend-panel/header/empty-notice idiom; chip
Buttons STOP their own events so toggles and tooltips are unaffected),
and _is_over_ui() no longer checks the bar rect (with IGNORE, chip
events never reach the viewer — checking the wide rect would recreate
the dead strip). Regression test pins both: filter mode + an
empty-strip point not registering as UI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:26:02 +02:00
jpmschweitzerandClaude Fable 5 69123904a5 docs(meta): D-226 T-1124 SS5 entry revision — fixed planetary map + rectangle-cursor click-through (Jeroen, companion hands-on)
The regional-map entry changes from zoom-threshold LOD swap to
explicit click-through: the planetary heightmap view becomes FIXED
(pan/zoom removed together with its replacement in T-1138, never
before); hovering shows a rectangle cursor representing the
regional-mode bounds; click descends centered on the click point's
derived DistrictPos. DISTRICT_WINDOW_MIN_ZOOM retired before ever
being built; D-013's zoom-owns-descent superseded for this seam only
(click owns descent). In-mode behavior unchanged (pan-only refetch,
debounce, cache, border-fade). Morph transition explicitly deferred.
Open at T-1138: the rectangle is an affordance, not to scale — n=64
is ~131 km = a few px on a planetary canvas; resolve the honest
representation in the screen design. T-1138 description updated;
T-1140 filed for the two companion UI defects fixed alongside.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 08:59:30 +02:00
jpmschweitzerandClaude Fable 5 b56f6b0bc8 fix(ui): T-1140 overlay bar wraps instead of overflowing; strip dev ids from tooltips
Jeroen's first make atlas hands-on: 17 overlay chips in a single
HBoxContainer row ran off the right screen edge (positioning also
guessed the bar's width with a 520px fallback). The bar is now an
HFlowContainer with ALIGNMENT_END; the viewer gives it everything
right of the header (OVERLAY_BAR_HEADER_RESERVE) and rows wrap
right-aligned — verified via live capture, all 18 chips visible.

OVERLAY_DEFS tooltips leaked dev provenance into player-facing text —
ticket ids (#960, T-960, T-1046, T-1118, T-1119) and decision ids
(D-181, D-226, D-243) mean nothing in-game. Stripped to plain
language; the visibility-ladder semantics (public signal / observable
/ needs corporate contact / needs insider access) stay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 08:59:08 +02:00
jpmschweitzerandClaude Fable 5 9d2e9a4cf1 chore(meta): close Atlas depth batch — T-1124/T-1118/T-1119 done (PR #185 merged, triple review incl. Troblum adversarial pass); D-226 synced; T-1137 now unblocked
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:48:34 +02:00
jpmschweitzer 37c776703e Merge remote-tracking branch 'origin/atlas-depth' 2026-07-18 12:46:59 +02:00
jpmschweitzerandClaude Fable 5 c20c175af1 docs(meta): D-226 T-1124 amendment — PR #185 Troblum findings (windowed-family ceiling, queue-based serving, comment reconciliation)
All five findings applied, none touching the option-(c) carrier choice:
(1) SS2 gains a binding windowed-family ceiling — exactly ONE
windowed-query field; a second windowed query is a dedicated response
message by rule (two concurrent windowed payloads would need the
per-field request-correlation that IS the tagged framing — that is the
trigger to build it); symmetric with the request side's five-hard cap.
(2) SS1 gains a binding serving model — window derives ride the same
Rayon queue + Pending pattern as whole-body cache misses, never inline
in the PreInput drain (which the codebase deliberately keeps expensive
work off); per-connection coalescing recommended; SS4's 7/29ms figures
reframed as worker latency, not tick-thread cost. (3) The
layer_proxy.rs growth-ceiling comment (comment-only diff) now records
the T-1124 ruling as RESOLVED — scoped to the dense whole-body family,
district_window outside it, second windowed field = dedicated-message
migration — instead of deferring to an open design question. (4) SS2
documents that body scoping rides the enclosing AtlasLayerResponse
envelope (cache key body_id+center+n; echo disambiguates within-body).
(5) SS5 entry clarified: zoom threshold alone triggers the swap
(works over open ocean), first window centers on the pan-center's
derived DistrictPos; downstream settlement-anchoring phrasing
reconciled.

pql decisions validate clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:44:35 +02:00
jpmschweitzerandClaude Fable 5 f2b9cdb2b2 chore(meta): T-1137 — queue-based window serving + windowed-family ceiling (PR #185 Troblum findings)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:38:37 +02:00
jpmschweitzerandClaude Fable 5 29259e4b64 chore(meta): T-1124/T-1118/T-1119 to review — PR #185 up (Atlas depth batch)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:30:30 +02:00
jpmschweitzerandClaude Fable 5 05c3f8b894 chore(meta): file T-1139 — msgpack Vec-u8 decode gap (T-1118/T-1119 finding, maintenance)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:26:14 +02:00
jpmschweitzerandClaude Fable 5 e41cca2ded feat(ui): T-1118 climate overlay + T-1119 quarter glyphs — client halves, with file-size extractions
T-1118: gen_region_grid overlay (label TMP) — _draw_gen_region_grid
copies _draw_gen_district's self-contained mapping (dims from the
layer dict); mean-temp cold-to-hot ramp over -50..+50 C;
REGION_TEMP_NONE_DC airless sentinel = skip-cell (undrawn, never an
invented color); legend entry.

T-1119 (touch points 3-6): quarter_footprints protocol passthrough;
gen_l4_quarters overlay (label QTR) — density-scaled glyph anchored
on the L3 settlement dot joined by city_id, shape = dominant district
type (corner-tab/diamond marks for Commercial/Industrial/
Administrative), color = density ramp on the settlement-gold family,
zoom-gated at SETTLEMENT_LABEL_MIN_ZOOM; landmark/corridor counts
never drawn (D-226(d) tooltip-only ceiling); legend entry.

Structure: atlas_viewer.gd and protocol.gd were over gdlint's
1000-line cap before this batch; cleanly-separable responsibilities
extracted on existing precedent — atlas_generation_state.gd (per-layer
data + accessors), atlas_generation_proxy.gd (polling/retry/pending
machinery), atlas_overlay_colors.gd (pure ramp/shape lookups),
atlas_map_protocol.gd (atlas/starmap/citynames codec, the
browse_protocol.gd delegate pattern). Public APIs preserved exactly;
_gen_state stays a field default (RefCounted, pre-_ready safe) because
_ready()-construction breaks every bare AtlasViewer.new() test —
documented inline.

Tests: registration + round-trip for both overlays; pure-function
suites for the temp ramp (endpoints/midpoint/clamp/sentinel) and
quarter glyph (scaling, zoom gate, ramp, notch across all 9
DistrictTypes); Tier-2 replay asserts exact literals from the real
server-generated fixture incl. the airless sentinel. Color.lerp(a,b,
1.0) is not bit-exact to b — endpoint assertions use per-component
is_equal_approx. Full suite 3094/3094; gdlint zero warnings incl. the
two previously-over-cap files. Live capture: legend grows to 7
sections, TMP/QTR toggles clean against a live server.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:25:47 +02:00
jpmschweitzerandClaude Fable 5 8165c61186 feat(simulation): T-1119 QuarterFootprintLayer — server half (touch points 1-2) + populated wire fixtures
ZoningType gains PartialOrd/Ord (DistrictType T-994 mirror) for the
dominant_zoning declaration-order tie-break. layer_proxy:
QuarterFootprintEntry/QuarterFootprintLayer (BTreeMap keyed by
city_id; density_avg_pct floor-mean, dominant_* mode with
declaration-order tie-break, landmark/corridor counts) +
build_quarter_footprint_layer gated None on empty state.quarters;
sixth AtlasLayerResponse field wired into all construction sites;
growth-ceiling doc updated to say the whole-body budget is consumed
(what carries a seventh is T-1124's design, resolved in the same
branch's amendment). Placements whose derived Layer4Quarter id is not
yet in state.quarters are SKIPPED (skeleton gen is async Low-priority
— entries may be a proper subset; client decodes defensively). Stale
TODO(#957) removed (premise predates T-957 landing).

Tie-break bug caught by its own test: Iterator::max_by_key over a
BTreeMap returns the LAST max on ties — backwards from
declaration-order-first; replaced with an explicit forward walk that
replaces only on strictly-greater count.

gen_fixtures: populated RegionGridLayer (T-1118 replay coverage) +
QuarterFootprintLayer literals in the ready fixture; msgpack fixtures
regenerated via make fixtures. Note: landmark_count is inert on real
data today (BlockSkeleton.landmark hardcoded None until landmark
placement lands); fixtures use non-zero counts to exercise the logic.

5 new unit tests + populated round-trip; atlas:: 549 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:03:28 +02:00
jpmschweitzerandClaude Fable 5 3f7851895c chore(meta): file T-1137/T-1138 — regional-map wiring follow-ups from the T-1124 design (blocked on batch merge; zoom-headroom note on T-1138)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:02:53 +02:00
jpmschweitzerandClaude Fable 5 67bd0ec294 docs(meta): D-226 T-1124 amendment — windowed district-resolution regional map design (T-1124)
Five sections, Tyre data shape + Araminta screen/encoding (T-1112
pattern): (1) request = serde-default window_center/window_n ON
AtlasLayerRequest (five-shape demux cap honored); (2) response carrier
RULING — district_window is a windowed viewport query keyed
(body, center, n) with echoed-center staleness guard, deliberately
OUTSIDE the dense whole-body layer family whose growth ceiling is
re-scoped (not busted) to that family; (3) six per-cell fields incl.
glaciation_grade (T-1127 deferral accepted) and Marine-exhaustive
vegetation; (4) binding budget — 7 bytes/cell, MAX_N=64 (~28 KiB),
DEFAULT_N=32, temp shares the T-1118 region-ramp colorizer across zoom
levels (D-243 continuity), pan-only re-request (zoom never refetches),
D-227-determinism client cache; (5) screen — zoom-threshold LOD swap
in the existing AtlasViewer, morphology base with elev_q lightness,
gen_dw_* toggles, glaciation as always-on tint modifier, Marine
transparent, implant chrome discipline.

Validated via pql decisions validate. Implementation is follow-up
ticket scope (server wiring must resolve the named TerrainAnalysis
transience decision; client screen).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 12:01:05 +02:00
jpmschweitzerandClaude Fable 5 05b2b7aff1 chore(meta): activate Atlas depth batch — T-1124/T-1118/T-1119 in progress with Si refinements + lead rulings (request-cap closed, response-budget fork to design pass)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 11:47:18 +02:00
jpmschweitzerandClaude Fable 5 8c7a0d6f3d chore(meta): close companion wave 2 — T-1131/T-1133 done (PR #184 merged, both reviewers approved; demux ceiling ruling recorded in bridge doc)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:57:23 +02:00
jpmschweitzer 7d310997af Merge remote-tracking branch 'origin/atlas-companion-browser' 2026-07-17 10:55:56 +02:00
jpmschweitzerandClaude Fable 5 132915a4e5 test(engine): browse-inclusive union-frame rejection cases (PR #184 review)
Hoshe's finding: the H1 union-rejection mechanism correctly counts the
new browse discriminator, but ambiguous_union_frame_is_rejected was
carried over from PR #176 without a browse-inclusive case — a future
demux/ShapeProbe refactor could drop the fifth shape from the union
check with nothing to catch it. Adds browse+star_map and
browse+city_names union frames, both asserting rejection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:53:36 +02:00
jpmschweitzerandClaude Fable 5 51b6147037 chore(meta): T-1131/T-1133 to review — PR #184 up (companion wave 2)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:44:57 +02:00
jpmschweitzerandClaude Fable 5 7111cea549 fix(engine): clippy items_after_test_module — tests mod to end of main.rs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:42:06 +02:00
jpmschweitzerandClaude Fable 5 2509624577 fix(engine): resolve systems.db exe-anchored, not cwd-relative — spawn-mode DB access
PathBuf::from("data/systems.db") was cwd-relative, and a spawned
server inherits GODOT's cwd — which is client/ (Godot's --path client
chdirs), so CultureResolver, CityContextReader, BodySourceResolver and
BrowseReader all silently failed in every make atlas / make game
spawn. Wave 1 masked it: the star map serves from star_map_data.json,
so 'renders 301 systems' never touched the DB; T-1133's browser was
the first DB-backed consumer to hit it live (Stig, /proc/PID/cwd).

resolve_systems_db_path(): exe-anchored <exe_dir>/../../data/systems.db
first (cwd-independent — the actual fix), then cwd-relative
data/systems.db (cd server && cargo run), then server/data/systems.db
(repo-root invocations); first existing candidate wins, info-logged.
Pure systems_db_candidates() split out as the testable seam (5 unit
tests — incl. pinning Path::parent() of a bare filename = Some(""),
not None). world_root now derives from the resolved ABSOLUTE path so
its ancestors().nth(3) arithmetic holds unconditionally instead of
silently falling back to ".." when canonicalize failed.

Verified all three launch styles; make atlas spawn shows 5 reader fds
open on server/data/systems.db via /proc/PID/fd.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:37:15 +02:00
jpmschweitzerandClaude Fable 5 90c562a6a3 feat(ui): T-1133 data browser — implant/browser app, six index+detail screens (D-254 SS4)
New implant app (app_path implant/browser, key B, fullscreen), sibling
to the Atlas per Jeroen's IA ruling: kind picker -> generic filterable
index (live search-mode typing) -> generic detail, parameterized per
kind, composed entirely from D-169 components. available_in_companion
left unset (default true) — the app appears in the companion shell
automatically via the generic-host seam, zero companion-side wiring.

browser_adapter.gd is the sole home of literal wire field names: maps
Oscar's BrowseResponse contract ({id, primary, secondary} index rows;
BrowseDetail enum-as-single-key-map) to view models for all six kinds,
folding join partners (system economy/factions/culture, corporation
presence, commodity production chains with nested Leontief inputs).
browse_protocol.gd split out of protocol.gd (max-file-lines);
sim_bridge gains browse_response_received + request_browse_index/detail.

Live-data catch: a present-but-NULL key (unnamed asteroid belt
proper_name) bypasses Dictionary.get fallbacks and rendered '<null>' —
_display_or() null-vs-absent helper applied across all six detail
mappers, 4 regression tests distinct from the absent-key cases.

43 gdUnit adapter cases; full suite 3074 green. Live-verified against
a real server + real systems.db: all six kinds Ready with real row
counts (301/3240/466/165/36/28), detail drill-down, NotFound on bogus
ids. Spawn-mode DB resolution issue found during verification is
pre-existing (cwd-relative data/systems.db) — server-side fix follows
separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:24:39 +02:00
jpmschweitzerandClaude Fable 5 d48d72fd31 feat(engine): T-1131 browse data proxy — six entity kinds, index+detail, one wire envelope (D-254 SS4)
browse_reader.rs: BrowseReader on the CityContextReader::open() pattern
— six index + six detail reads against systems.db (bodies filterable by
containing system; system/corporation/commodity details fold their join
partners). browse_proxy.rs: BrowseRequest{browse, kind, query} /
BrowseResponse{kind, status, index, detail} wire types + dispatcher;
BrowseIndexRow{id, primary, secondary} generic across kinds;
BrowseDetail a per-kind enum of field-exhaustive structs.

Demux: Inbound::BrowseRequest is the FIFTH map shape — deliberately the
last; the doc's four-shape ceiling is re-pinned at five with rationale
(six kinds x two forms folded into ONE envelope whose internal enums
pick sub-behavior, the AtlasLayerRequest.up_to precedent, instead of
twelve top-level shapes) and a hard rule that a sixth shape must
migrate to the D-225 tagged-envelope framing. Served for BOTH roles,
connection-tagged 1:1 in-order like atlas/starmap/citynames.
serve_browse_requests pub so integration tests drive the true
end-to-end pipeline. Wire-only per D-254 (T-949 precedent); v1
exclusions (cascade geometry, event logs) respected.

30 unit tests + 7 bridge_tcp integration tests (six-kind round-trip
over real TCP, reader-can-browse, no crossed responses between two
readers, unknown-id NotFound, empty-table Ready); 2 pre-existing tests
updated for the new receive_bridge_inputs parameter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 10:01:21 +02:00
jpmschweitzerandClaude Fable 5 a346410832 chore(meta): activate companion wave 2 — T-1131/T-1133 in progress (atlas-companion-browser worktree; Oscar proxy + Stig browser UI)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 09:37:41 +02:00
jpmschweitzerandClaude Fable 5 edde411fb6 chore(meta): close companion wave 1 — T-1129/T-1130/T-1132 done (PR #183 merged); D-254 synced
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 09:33:54 +02:00