Tyre finding 2: _log_atlas_view_transform's footprint_px now logs the
real on-screen pixel footprint (StepCanvasTransport.canvas_footprint_px
* canvas_scale — the same public pure function the terrain layer uses),
with the old cell-count field kept as canvas_cells. Live-verified the
divergence the fix exposes: Global logs footprint_px=(1528, 760) vs
canvas_cells=191x95 — the T-1192 fit-multiplier class the log exists to
root-cause, previously invisible under the mislabel.
Tyre finding 3: atlas_shots.json's one_shot_per_body note replaced by
rung_coverage stating the true distribution — 13 goldens across 7
bodies (per-rung coverage map, GJ380c's 3 shots as the invariance-proof
body, curated-subset rationale per T-1121). Corrects the prior commit
message's '12 new goldens' miscount: the true count everywhere is 13,
verified against shots array, visual.json entries, and PNGs on disk.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tyre's PR #212 finding 1: the review-status row existed only in a live
DB, unrecorded in any git-tracked changelog — a rebuild reverted it.
Root cause: pql run from the capture worktree resolved the MAIN vault
(FR-4), so the write-through row landed here, uncommitted. Committing
it main-side makes the transition rebuild-safe; branch and main
changelog rows union at merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_setup_atlas_golden_shot and _run_atlas_matrix rebuilt on the real D-255
surface: nav.push('regional') through AtlasApp's own body-selection tail,
then StepCanvasViewer.jump_to at a fixed center (inventory item 5) — no
shim over the retired continuous-zoom API. is_pending()-aware bounded
settle (mirroring atlas_agent_driver.gd) and view-transform logging
(inventory item 3) wired into both capture paths. The 12 z2_0/z4_0/zfit
goldens are replaced by 12 (body, rung) goldens captured live against
fresh --test-mode servers; atlas_shots.json/visual.json re-keyed;
atlas_gen_open's stale gen_l1_* overlay ids fixed to gen_dw_temp.
Verification: two consecutive District runs byte-identical, and a
cold-vs-warm disk-cache invariance proof on both terrain draw branches
(Global/NEAREST, District/LINEAR) — byte-identical either way, so
capture output does not depend on the shared user://atlas_cache state.
DEVOPS.md's real-rendering exception note now records the fold-target
mapping for the smoke file T-1182 already deleted (Global + District
goldens exercise its two real-pixel draw branches). Old legacy-tracked
.import sidecars go with their PNGs; new goldens ship bare per
.gitignore's client/**/*.import rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
user://atlas_cache/ is one directory for every worktree gate run, live
capture driver, and real play session, and T-1183's Tier-2/3 lookup
short-circuits BEFORE test_mode's silent-no-op IPC — so a warm shared
cache delivers real canvases into tests written against 'nothing ever
arrives'. Caught live: a concurrent GJ380c Global capture flipped the
two before-any-canvas viewer tests in another worktree's push gate.
Adds disk_cache_root_override on StepCanvasViewer (threads into
StepCanvasRequest's existing test-injection-only seam; production
leaves it empty) and routes every direct viewer construction in the
viewer + legend suites through a _make_viewer() helper pinning an
isolated root. First slice of T-1193's viewer test seam; screen-built
viewers still share the default root (noted on T-1193).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Authors the full style bible: camera table separating D-148 gameplay from
D-019 offline-renderer use; the delegated toon-vs-PBR ruling (environment
props share the character toon treatment, with a minimal-PBR carve-out for
glass/polished metal so sightlines read truthfully under occlusion-based
perception); a color/material register for every D-235 ObjectTag (hue,
grain, D-217-keyed weathering); and explicit supersession notes both ways
with visual-grammar-v01.md and the mood-board workshop transcript.
Includes branch-side pql changelog rows (T-1050/T-1052 -> review); the
worktree pre-commit export step failed benignly (write-through had
already refreshed the files) so they are staged explicitly here.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Instantiates the five D-244 catalog files (models/textures/artwork/icons/
effects — icons carries the 13 as-built SVGs, stance icons traced to their
consumer and marked final), creates client/assets/models/{furniture,props}
with a schema-documented manifest.json mirroring the character manifest,
fixes glb-gen SKILL.md's stale 'path does not exist' paragraph, and authors
docs/assets/visual/conventions.md: category-first model naming (araminta
ruling), mask sidecars per the character convention, D-235-token-keyed
texture naming, footprint_tiles as manifest metadata. Door-state and
TileSet conventions are recorded as explicit deferrals (Phase-5 owned).
visual/README.md carries both this ticket's count/link updates and
T-1052's palette-section rewrite (shared file, committed here).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Guard becomes land_districts <= 1 (both reviewers converged — a lone
island definitionally cannot show two distinct directions; same
nothing-to-vary condition one value short), with a lone-island vacuous-
pass fixture; golden confirmed untouched. Oasis scaling adjudicated as
LIVE, not future — GRID_W is already 1024 on main, so ring iterations
change 2/4 -> 4/8 today: extracted a pure oasis_ring_iterations()
helper pinned by tests at both 512 and 1024, and traced exactly why the
determinism hash stayed green (it reads only elevation; the rings touch
only biome — a genuinely different array, not a coincidence). The
drainage merge-logic question answered byte-precisely: zero logic
changed vs main (comment-only diff) — and the deeper dig PROVED the
'isolated basin with another basin to escape to' branch is
mathematically unreachable for any connected grid (contracting vertex
groups of a connected graph cannot disconnect it), so the comment now
states that instead of narrating a divergence that never fires; two
direct merge-target tests added regardless. Wrap test renamed to what
it actually pins (non-wrap-awareness). D-010 docstring softened to
same-process purity, naming the cascade golden as the cross-run layer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The channel eyeball caught the committed reference driver silently
relying on SimBridge's hardcoded default port, unlike every sibling
real-render driver — a caller starting the server on a chosen port got
20 silent connect retries against the wrong port and a hollow session
whose results had valid shapes but no data. Mirrors visual_capture.gd's
convention exactly: SR_LIVE=1 without SR_PORT is a hard error; SR_PORT
sets SimBridge.server_port before boot.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every screen-targeted intent now routes through one
_require_current_screen() check and returns the structured error shape
instead of silently mutating an off-screen viewer (hoshe's finding:
scroll_rung from the reach screen fired real IPC and reported ok). The
reference driver's fixed 4-frame settle becomes is_pending()-aware with
a 600-frame bound, the keep-waiting decision extracted as a pure
testable function — restoring the proven eyeball-driver discipline. The
terrain_reference guard moves into AtlasApp._on_body_selected(), the
shared tail for double-click, Enter, AND the intent path — closing a
pre-existing click/Enter divergence hoshe caught this PR formalizing;
the intent layer pre-checks via the new SystemScreen.find_body() and
reports structured errors for unknown ids and terrain-less bodies.
after_test() resets AtlasAgentBridge.current_app (tyre's freed-pending
footgun). Suites 58/58 + 14/14; full suite 3,638.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tyre's PR #209 review flagged T-971's re-scope appends as invisible to
the branch-side planning store — same bookkeeping-lag class as PR #208's
T-1195 finding: the write-through rows were awaiting this commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tyre's PR #209 finding: every prior D-226 re-scope carries a dated
amendment in the record, and this vocabulary change existed only in
code comments and ticket appends. Records the drops (select_city,
open_regional — no settlement hit-test affordance post-D-255; one
screen Region..Chunk), the additions (open_atlas, jump_to_center via
the constrained jump_to seam), the summary-field reconciliation, and
the in-process-only transport narrowing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A real D-245 gate-shape strengthening, not just a test: the D-256/T-1174
finding proved the believability golden byte-identical under a total
all-North basin_direction collapse — every scalar contrast field is
structurally blind to the one field that regressed. ContrastMetrics
gains land_districts and basin_directions_distinct (both over ALL
districts, no new derive calls — the evidence-backed pick over the
voxel-transect proxy, which washes out at production sample density),
and evaluate_criteria gains 'basin direction variety': pass when
land_districts == 0 (the drained-body guard — an all-ocean body has no
cells that can cast a D8 vote per the aggregator's own exclusion rule,
so a uniform default is legitimate, mirroring the file's existing
nothing-to-vary idiom) or distinct >= 2. Negative test proves the
criterion catches the land-bearing all-North regression; vacuous-pass
test proves the waterworld guard. Golden regenerated and rerun-stable;
both validation bodies (Arbour, Edict) pass at distinct=2.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The verified-still-open coverage list: per-type attractor reachability
fixtures (LakeShore via enclosed depression, PassEntrance via crafted
saddle, PlainCenter via flat terrain, RiverCrossing via confluence) plus
thin_by_spacing behavior (collision, strict-< boundary, equirectangular
column wrap); heightmap 8-bit decode, sea_level passthrough, downsample
identity and zero-target early-return; drainage area_pct bit-for-bit
determinism plus the isolated-basin-fallback divergence comment (Tyre
N1, citing the pre-#953 behavior it deliberately departs from); the
layer1 mountain-branch pairing test (investigated first — the cascade
test supplies a mountain pool but only ever asserted river counts, a
genuine gap); an importer idempotency test covering atlas_city_names
AND atlas_feature_names plus the Sol exemption, wired into
make test-tooling; and the oasis_water dilation radius scaled by
GRID_W/512 (Tyre N2, hash-stable). One stale item dropped per the
refinement trim (test_sim_determinism wiring — already done).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
D-226 layer 4, rebuilt against the post-D-255 stepped Atlas after the
Phase-1 reconciliation (the original intent list targeted the retired
continuous-zoom viewer). Eleven intents, each backed by the exact
production handler a click calls — select/open for systems and bodies
(extracted shared by-id tails so click and intent paths are one code
path), scroll_rung, reset_view, back, open/close_atlas, set_overlay —
plus two new first-class capabilities: jump_to_center (the fixed-center
revisit pattern proven by five eyeball drivers, via a new
StepCanvasViewer.jump_to seam that reuses _scroll_rung's exact request
tail — same extent cap, same cache keys) and get_current_canvas_summary
(allocation-light reads off the raw wire dict, courses-by-class,
draw-matched settlement dedup — no PNG decode). Contract shape: dumb
AtlasAgentBridge autoload holding the app handle (untyped per the
parse-order rule), all logic in the static AtlasAgentInterface class.
observe() is side-effect-free: current state + a generic Control-walk
affordance tree. In-process consumers only this ticket (documented);
the committed reference driver (atlas_agent_driver.gd, InputSwallower +
settle-until-ready from the T-1157 inventory) replaces the scratch
eyeball drivers as the sanctioned headless-drive pattern.
select_city/open_regional dropped with recorded rationale (no
settlement hit-test affordance exists post-D-255) — diff on the ticket.
33 new tests across three suites.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoshe found the concrete residual: the hand-copied driver block called
derive_temperature_c unconditionally where invent_primitives prefers the
lapse-adjusted region baseline on non-airless bodies — driver_temp feeds
glaciation/moisture into the warp magnitude, so orbital displacement
could still differ from District at the same position (the ticket's
defect class, one step upstream); the copy structurally couldn't branch
right because region_baseline_at_district was computed after it. Tyre
demanded the structural cure: steps 1-3 now live in ONE shared helper
(invent_coastal_position -> warped position + CoastCharacter);
invent_primitives composes helper + detail-scatter; the orbital path
hoists the baseline and makes a single helper call. The audit test's own
'District-style' side turned out to be a THIRD copy carrying the same
bug — rewired to the real helper (raw pre-fix side untouched as the
historical baseline; refreshed: 5.01% disagreement, mean 5,957.9 m,
748.9 ns/cell). Golden verified byte-identical under forced regen, with
the reason traced: the wire temperature never flowed through the buggy
internal branch, and the fixture's probe positions cross no discrete
boundary — the 267-body audit is the instrument that sees the drift.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
T-1194 (biome/relief stipple layer, from T-1175's assessment) and T-1195
(river+mountain label positions, the T-1169 scope adjudication target)
now have their write-through rows in git — tyre's PR #208 review caught
the branch-side store unable to resolve the T-1195 reference because
these rows were awaiting this commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One commit for two tickets whose changes share the bridge/plugin
plumbing files. T-1169 connects the three dormant feature-name pieces:
atlas_feature_names populated at regen (17,891 rows — 15,190 mountain,
2,701 river — via populate_atlas_feature_names mirroring the city-names
importer; systems.db regenerated, stamp fresh), attach_feature_names
wired into the cascade's Topography block with name pools threaded
DB-free through AnalyzeBody (D-225 pattern) and assignments stored on
Layer1Output/BodyWorldState for future consumers, and a
FeatureNamesRequest/Response read proxy as the bridge's 7th tagged
envelope (D-236 pattern, both SimBridge impls). Client label DRAW is
deliberately NOT here — implementation proved both river and mountain
labels need a wire-carried position (the pool is position-free; course
polylines aren't correlated with the named attractors by construction) —
deferred to T-1195's single design pass. cascade_layer1 golden re-pinned
(additive feature_names field).
T-1159 retires the legacy u32 granularity field fully shadowed by
window_granularity_v2: AtlasLayerRequest.window_granularity,
DistrictWindowLayer.granularity echo, the u32::MAX sentinel, and
resolve_window_granularity are gone server-side; client encode paths and
the caller-less atlas_window_cache legacy key component dropped;
msgpack fixtures regenerated; the T-1150 aliasing regression test now
drives through the surviving enum field. The district_window carrier
itself survives byte-compatible per D-255(c).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Global/Region rungs sampled the heightmap ocean mask raw while every
finer rung samples it at the coast-warped position — a structurally
different coastline at the orbital-to-district seam. Audited on all 267
real body heightmaps at region spacing, coastal band only: 5.01%
land/ocean classification disagreement (2,911 of 58,073 cells), mean
displacement ~6.0 km, max ~18.9 km. Fork taken: APPLY the warp —
derive_orbital_at_metres now runs invent_primitives' steps 1-3 (driver
climate -> coast character -> coast_warp_px) before sampling, still
skipping detail-scatter (its octave ceiling, 32.8 km, is below region
spacing; the WARP's octaves reach 262 km, which is why skipping it was
wrong). Cost measured: ~784 ns/cell added (~15 ms on an Earth-class
Global canvas; low hundreds of ms parallel at the 8.3M-cell ceiling).
The ignored audit test preserves the pre-fix baseline for the record.
Golden re-pinned — region rows only, district/quarter byte-identical.
project.yaml 0.4.2 -> 0.4.3: orbital canvas bytes changed, client disk
caches must miss. Awaiting Araminta's review-seat sign-off per ticket.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five findings from the araminta+hoshe round. Tapering now fires only on
a TRUE upstream source: the course's first raw world point is tested
against the canvas's own world bounds (conservative 1m epsilon) —
exact detection because the server crop keeps one point beyond the
window (layer_proxy crop_course_to_window lo = first_in-1, contract
documented), so crop passthroughs draw the old flat full-width cut and
never a false headwater. The averaged-normal joint is replaced by a
real mitre (half_w/cos(theta/2) recovered trig-free via the bisector
normal), clamped by a 2x mitre limit AND 0.45x the shorter adjacent
segment — restoring true perpendicular width at bends (the 29% pinch at
confluences is gone) and preventing the hairpin bowtie; the winding doc
now states the actual bounded guarantee. Antialiasing restored via the
hybrid: only the varying-width taper head draws as a ribbon; the
constant-width ~85% of every course keeps the original antialiased
draw_polyline (byte-identical for untapered courses), split at an
interpolated arc-length point sharing position and width — junction
capture evidence in .cache/screenshots/t1175-fix-round/. Flat-fill
single-element color array. Suite 24 -> 48 tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The single large polish pass Jeroen requested off the T-1170 captures,
benchmarked against RimWorld's world-map fluency. Courses now draw as
source-tapered ribbons: per-vertex width ramps from a hairline at the
upstream source to full class width over 15% of the course's arc length
(arc-length parameterized, not vertex-indexed, so point density doesn't
change the read), built as one draw_polygon ribbon with mitred joins.
Class width table retuned 0.9/1.4/2.2 -> 0.6/1.2/2.4: a clean ~2x
per-class ladder so a tributary-joins-trunk confluence reads as a join,
trunk held at its visually-proven weight, stream thinner per the
benchmark's thin/consistent/restrained grammar. Opacity untouched
(Araminta's T-1170 ruling stands). Coast-gradient item resolved as
already-correct (the coastal transition zones + elevation lightness
render the shoreline band; capture-verified) — no wire change. Stipple
assessment filed as T-1194. Eight new taper-geometry tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>