Atomic index writes (tmp+rename), orphan-payload reconciliation sweep
folded into the background sweep, payload shape guard mirroring the
protocol's own width/height discriminator, size_bytes via get_position()
instead of a full payload re-read, and a 64-bit SHA-256 payload filename
(String.hash()'s 31-bit space made a silent wrong-map filename collision
a ~1-in-16k event per cap-full body; migration self-heals via the orphan
sweep). Tier-3 class doc rewritten to name the real D-253 seam — the
glaciation/flooded_q wire fields exist but carry static values and no
staleness signal crosses the wire; T-1190 tracks threading a wire TTL
into put(sim_ttl_sec) when the driving clock lands — replacing the false
'no sim-state wire field exists' premise. Four new tests plus a
_stub_canvas fixture helper centralizing the canvas shape contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
step_canvas_disk_cache.gd: the Tier 2/3 store per D-255(d) and the
round-2 three-tier spec. Payload is the WIRE, pre-decode — store_var/
get_var round-trips the PNG-encoded PackedByteArrays natively, and
Image.load_png_from_buffer never runs in this file. One composite key
shared verbatim with Tier 1 (hash filenames for filesystem safety);
per-body index.json with malformed-index recovery (rebuild-or-discard,
never crash).
Three independent eviction mechanisms, exactly as ruled: rung-0 Global
carries a retention floor no sweep touches (now also threaded into
Tier 1 per the T-1182 handoff); Tier 2 geometry is byte-valid forever
and evicts only by time-since-last-visit (14d starting tunable, on
body-open) and LRU byte budget (256 MiB/body, 5-min coarse timer) —
two separate sweeps; Tier 3 sim-state TTL is wired and tested but has
no production caller yet (no sim-state field exists on
EncodedStepCanvas — the D-253 stub inheritance, documented).
Hardening per D-255(d), both mandatory: per-body deep-rung cap
(512 Block+Chunk entries, enforced synchronously in put(), floor- and
budget-independent — the ticket sanctions count-or-quota; count chosen
as the direct D-226(d) information-content proxy) and a schema/version
tag on every entry (project.yaml version via the existing
loading_screen line-scan idiom — D-192 co-ship makes the client
version the wire-schema version; exact-inequality mismatch = miss +
drop, NEVER decode, checked in both has() and get_canvas()).
Integration: request_now() checks Tier 2 on a Tier-1 miss (synchronous
promote), Ready responses write through to both tiers, Pending never
writes; viewer runs the visit sweep on body-open + the background
sweep on a 5-min timer.
30 new disk-cache tests + 7 request-integration + 3 sweep-wiring tests
(restart persistence, sweep independence both directions, cap
semantics, version-mismatch never-decode, corrupt-index recovery).
Full client suite 3,440/3,440, 0 orphans; cold-parse clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tyre finding: the orphaned AtlasViewer cluster is now actually deleted
(atlas_viewer, atlas_marker_overlay, atlas_descend_geometry,
atlas_legend_panel — a sixth orphan found beyond the review list —
atlas_generation_proxy, atlas_generation_state; ~2,497 lines), with
reachability re-verified across preload/class_name/res:// strings,
every .tscn, and the standalone companion app. Test suites triaged,
not blanket-deleted: 5 pure AtlasOverlayColors tests relocated into
test_atlas_window_colors, the live type-identity regression guard
relocated into test_step_canvas_viewer, dead coverage deleted. A real
harness gap surfaced during diligence and RULED, not patched:
visual_scenarios/visual_capture golden shots call retired
continuous-zoom API — no shim (would resurrect what D-255 kills);
inventory recorded on re-scoped T-1157 (gate-invisible, manual
targets only).
Hoshe finding 1: decode_png_field now detects the [Error,
PackedByteArray] bin-shape from messagepack.gd explicitly — a genuine
msgpack bin payload decodes correctly instead of silently collapsing
to [0,0]; test built from a real round-tripped bin decode.
Hoshe finding 2: the hard zoom-out reset is wired — ascend at rung 0
with a drifted view triggers _reset_to_global (the restored HARD
condition), behavioral tests through the real input path.
Notes folded: refloat + edge-scroll test coverage, legend smoke suite,
Vector2i narrowing-safety comment with computed headroom.
gdlint clean on touched files; full client suite 3364/3364.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoshe finding 1 (live-firing on GJ1c: 2 spill collisions + 1 i==1
collision among 51 Overflow basins): adjacency adjudicated
INSUFFICIENT for the cue — a course's visible anchor is its upstream
cell, so nothing pre-existing belongs to the lake unless wired. The
spill cell (outlet_path[0]) now always gets a real entry: appended
when new, OVERWRITTEN IN PLACE when it collided with an existing river
cell (append would duplicate edge_id; the hydrology solve is the more
authoritative downstream answer for that cell than flat D8
extraction). Interior stop-on-collision stays, now provably safe.
Internal lookup is a dense Vec<Option<usize>>, never iterated (D-010).
Two non-vacuous regression tests prove the cue through build_edges
output; end-to-end on GJ1c all 51 Overflow basins now build a readable
edge (was: one silently missing).
Hoshe finding 2: both doc sites now state the fallback-vs-production
split explicitly (fallback moisture 55: 51/2; production GJ1c moisture
80: 53/53 all-Overflow) — the golden's Endorheic pair is a
fallback-constant artifact, not a fact about GJ1c.
Golden re-regenerated: river_cells 143->192, position-identity diff
purely additive (zero removed, one legitimate in-place overwrite at
the spill-collision cell); attractors/basins/mouths/confluences
byte-identical. Suites: hydrology 26/26, full lib 1943, cascade_golden
1/1, window goldens + believability untouched green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The two-layer client rebuild per D-255(a)(b)(e), replacing the
_canvas.scale continuous-zoom model with one viewer, one path, all six
rungs:
- step_canvas_protocol.gd: StepCanvasRequest/Response codec against
the T-1181 wire contract — incl. the discovered png_bytes subtlety
(rmp_serde without serde_bytes emits a msgpack int-array, not bin;
decode repacks via PackedByteArray before load_png_from_buffer) and
the extent-echo rule (read the server-clamped extent, never assume
the requested one).
- step_canvas/ component: transport (six-rung ladder, cursor-anchored
scroll steps, edge-scroll/WASD pan with re-request on edge crossing,
hard reset-to-Global), RTT terrain layer (Image.set_pixel colorize
per the c1 measured ruling, texture.update reuse on step-cross,
NEAREST coarse / LINEAR fine per rung), unscaled screen-space
annotation sibling (courses + settlement markers at literal px),
in-memory LRU cache (Tier 1; T-1183 layers the disk tiers beneath),
request lifecycle (pending retry, staleness gate, extent echo).
- Full _canvas.scale retirement in the same change: the zoom-scaled
canvas model, the _zs compensation family, select_rung /
MAX_COVERAGE_M / compute_tile_grid, the orbital-mosaic-vs-window
two-path split, _view_zoom/_canonical_fit_zoom — 10 source files
deleted; their 14 test suites deleted with them (T-1157 dead-goldens
rule; replacement visual-capture coverage is re-scoped T-1157).
- Surviving surfaces kept per the ticket: atlas_window_cache.gd's LRU
shape (the ticket's named file atlas_window_tile_set.gd was the
retiring orchestrator; the real LRU shape lives in
atlas_window_cache.gd — cited in step_canvas_cache.gd), overlay
colors, legend/overlay-bar chrome, AtlasViewer descend geometry.
Determinism boundary per D-255(e): the client interpolates only within
the closed server-supplied input set. 7 new gdUnit suites (164 cases)
incl. a real extent-echo bug caught by its own test during
implementation. Full client suite green (exit 0) with the live-gated
suites running against a worktree server build.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
extend_river_network_with_basin_outlets threads each Overflow basin's
resolved outlet_path into RiverNetwork as real D8 downstream
continuations (spill cell skipped as lake interior; Sea target ends at
RIVER_DOWNSTREAM_MOUTH with a seaward entry, Basin/OpenSpillway at
RIVER_DOWNSTREAM_EDGE_DRAIN); Endorheic basins contribute nothing —
the ruled zero-bit cue is outflow-course PRESENCE (D-227 amendment
(4)): a lake with no outgoing course reads as closed. Additive per
T-1170 Ruling 7b; no wire migration, no new zone, no endorheic bit.
Wired in run_layer1_with_moisture strictly AFTER attractor extraction
so outlet cells never perturb settlement placement (tested). Edge
identity is the existing pack_cell_id (row,col) convention; wiring
determinism proven by three independent double-solve byte-identity
tests. 13 new tests across hydrology_equilibrium and layer1.
Goldens: cascade_layer1.json re-pinned (third deliberate re-pin,
documented in cascade_golden.rs) — river_cells 93->143 on GJ1c,
append-only prefix byte-identical, 51/53 real basins Overflow with
short OpenSpillway stubs (the dominant honest pattern: most basins
spill onto adjacent open ground, not a long channel to sea).
window_derivation_golden and river_course_golden verified structurally
unreachable and unchanged.
Known scope boundary (documented in-code): outlet cells carry
river_class 0 (stream) — outlet-channel classification/meander width
scaled to catchment is a named follow-up, not guessed at here.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoshe finding 1: StepCanvasRequest.extent is no longer wire-trusted —
clamp_step_canvas_extent enforces the D-255(b) canvas budget at the
request boundary (per-axis cap 3840 defeating u32::MAX before any
multiplication, then an aspect-preserving total-cell ceiling at the
measured 3840x2160 = 8,294,400-cell workshop budget), mirroring the
legacy carrier's clamp_window_n_v2 discipline; the Global rung ignores
the wire extent entirely. StepCanvasResponse gains the extent echo
field so a client can detect the clamp (the DistrictWindowLayer.n
precedent — a pre-existing gap closed in passing, recorded on the
ticket for T-1182). Seven new tests including an end-to-end u32::MAX
request proving actual allocation respects the cap.
Hoshe finding 2: submit_step_canvas coalescing now has the same two
regression tests its submit_window sibling always had (same-key
collapses to one pending item, different-key does not), exercising
step_canvas_supersede_key.
Targeted suites green: 1928 lib, acceptance gate 5/5, bridge_tcp 22/22,
window_derivation_golden 6/6 byte-green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two needless mutable borrows in the serve system, one spurious
markdown list marker from a doc-comment line wrap (a leading '- '
turned the whole T-1186 convention note into a lazy continuation), and
a named row/col pair replacing the identity-op grid index in the
settlement-id tie test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The T-1184 merge seam: TerrainAnalysisCache::get_or_derive gained a
body_params parameter (real moisture ceiling for the hydrology solve);
the DeriveStepCanvas arm now passes its own body_params so step-canvas
requests get the same hydrology-carrying TerrainAnalysis the legacy
DeriveWindow path does. Acceptance gate + window goldens green
post-merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The D-225-discharging wire migration per D-255(c): a new
server/src/atlas/step_canvas.rs subsystem (six-rung StepCanvasRung
ladder — Global variable-extent rung 0 through Chunk 64m — the
StepCanvasRequest/StepCanvasResponse tagged envelope extending the
proven ShapeProbe discriminated-shape pattern, PNG-per-field dense +
MessagePack-native sparse encoding per the T-1179 measured table, and
both server cache tiers: the structurally keep-always GlobalTierCache
and the dual-axis StepCanvasCache with storage TTLs per rung and
SIM_STATE_TTL clock-bucket staleness per the D-227 amendment (1)
formula). Wired through bridge/{mod,tcp,local}.rs (sixth demux shape,
send_step_canvas_response mirroring the five existing senders),
gen_queue.rs (DeriveStepCanvas work item with per-connection-per-rung
coalescing, reusing the shared TerrainAnalysisCache), and plugin.rs
(serve/complete systems, lazy D-206 rung-0 population).
Acceptance gate (mandatory per D-227 amendment (3)):
tests/step_canvas_acceptance_gate.rs — cache-hit == cache-miss
byte-identical for every rung, lossless encode round-trips, cache
round-trips vs fresh derive, distinct-center sanity. 5/5 pass.
Station-spacing cap ADOPTED: course stations floored to District
spacing (2,048 m) at finer rungs — the S2-measured +38-87% chunk/block
course cost had zero display benefit at the same station density
(COURSE_STATION_SPACING_FLOOR_M).
Documented honest gaps, not shortcuts: settlement_id is a proximity
approximation (no footprint polygons exist yet); glaciation/flooded_q
sim-state planes are wire-shape-ready D-253 stubs; rung-0 uses signed
equator-anchored rows (the canonical D-256 core convention — T-1186's
wrong-latitude behavior applies unchanged and unfixed here, by
instruction).
Legacy district_window carrier byte-unchanged: window_derivation_golden
6/6 byte-identical, all district_window suites pass unmodified. Full
suite at implementation time: 2127 passed across 45 binaries.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoshe finding 1: dropping HydrologySample.elevation was PROVEN unsafe
(TerrainAnalysis.elev_pct is a rank percentile, not raw elevation;
HydrologyResult carries no elevation) — the copy stays, and the truth
moves into the docs instead: gen_queue's TerrainAnalysisCache sizing
comment corrected to real 512x256 working-grid numbers (~1.57 ->
~2.62 MB/entry, capacity-8 worst case ~21 MB), clone-on-hit cost
documented, byte-safety proof recorded on HydrologySample itself.
Arc<TerrainAnalysis> follow-up filed as T-1187.
Hoshe finding 2: the endorheic-split test now asserts the bowl basin's
BasinOutcome actually diverges (Endorheic at moisture 0, Overflow at
100, straddling ENDORHEIC_MOISTURE_CEILING=60) plus basin-count sanity
— mutation-verified by stubbing is_endorheic and watching it fail.
Doc/test-only round: goldens byte-unchanged, full suite 2114 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Productionizes the T-1177 equilibrium solver: run_layer1 now solves
hydrology once per body (~24ms, mirrors drainage::analyze) and carries
it as TerrainAnalysis.hydrology; run_layer1_with_moisture threads the
real body moisture ceiling (extracted derive_moisture_ceiling_q), with
the T-1177 population-survey default as fallback. The resident rung-0
global tier does not exist yet (T-1181's scope) — hydrology rides
TerrainAnalysis and lands in that tier for free when it is built
(deviation recorded on the ticket).
MorphologyZone::Lake is now sourced from the settled solver at derive
time: a gridunit is Lake when bilinear-sampled filled surface exceeds
bilinear-sampled original elevation at the sample's own (px, py) — the
continuous comparison, so lake edges refine with rung like coastlines;
never a discrete basin-cell projection. The gate sits strictly between
OpenOcean (>= 80) and the old ocean_fraction heuristic (>= 60), which
survives as the derive-fresh fallback when no solve is attached —
byte-identical to pre-T-1184 output in that case. Static
classification, distinct from the sim-state flooded plane; no
endorheic bit (the drains-vs-closed cue is T-1185's outlet-course
presence, per the D-227 amendment (4) sequencing). Zero new wire
bytes.
Acceptance: lake_classification_cache_hit_equals_cache_miss (solve
twice independently, byte-identical zones, non-vacuous Lake hit) plus
hydrology determinism tests. Golden fidelity: the window golden
fixture now builds TerrainAnalysis through the production entry point
(run_layer1_with_moisture, per-body), and a dedicated lake_bowl golden
body pins the hydrology-sourced Lake path (morphology 1 at
ocean_fraction_q 0 — provably not the heuristic); the 108 pre-existing
golden rows are byte-identical (pure append). believability.json moved
by one lake-shaped line (GJ338Bd voxel_relief_m 27->28, a correctly
reclassified lake district leaving the dry-relief sample set).
river_course and derivation-harness goldens unchanged. Full suite:
2114 passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Hoshe finding 1: derive_all_districts passed a permanently-empty
region_cache, so every survey cell paid four on-the-fly baseline
derivations — and derive_district_profile's docstring (build the cache
before calling in a loop) was contradicted by its sole production
caller. The cache is now pre-built on the TRUE region keys the shared
core looks up (survey-cell centre metres -> containing district ->
region ±1 ring, BTreeSet-deduped), restoring the per-body build-once
cost model. Cache-hit == cache-miss byte-identity holds by D-227 purity
(build_region_profile and the miss branch share the same expressions) —
verified by the believability harness passing against the UNCHANGED
golden. Finding 2: the cascade.rs call-site comment and the stale
module header now state the pre-build truthfully.
Found in passing, filed as T-1186 (pre-existing, out of scope here):
region_centre_latitude_deg is pole-anchored while the derive core keys
equator-anchored signed regions — northern-hemisphere baselines clamp
to +90.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
derive_district_profile is now a thin wrapper over the shared
derive_at_metres_with_riparian core at survey-cell-centre world metres
— one derive core, two position sets. The batch pseudo-grid and the
true D-243 district grid were two coordinate systems sharing one bare
(i32,i32) type; the new SurveyCellPos newtype re-keys every batch
product (BodyWorldState.districts, Layer1Output.survey_basin_dirs) so
the compiler rejects cross-namespace passing.
Fixes two latent same-position divergences the T-1174 investigation
surfaced: three inconsistent latitude conventions collapse into the
core's single inverse mapping, and the region-climate baseline now
floor-divides true world metres instead of collapsing the whole body
onto region (0,0)'s baseline — batch climate becomes latitude/region
graded (D-245 direction: every changed believability metric increased).
Binding preservations per D-256(c): basin_direction rides a post-call
override with the true L1 D8 survey-cell aggregate (layer1's map
re-keyed to SurveyCellPos, identity lookup — a floor-divide lookup
against the pseudo-keyed map would have silently defaulted every cell
North); the riparian verdict comes from near_perennial_water_at, never
the empty-slice default (which would have flipped riverside
vegetation_class).
Quarter-skeleton morphology_zone now resolves at the settlement's
exact world position via derive_at_metres at work-item execution
(where TerrainAnalysisCache lives), replacing the survey-cell-centre
map lookup (D-256(d)); settlement_district_pos fixed to true-district
floor-division in passing (same doc/impl mismatch class). Second
pixel-vs-metre conflation fixed in aliveness_probe's anchor-walk math.
Window path byte-unchanged (window_derivation_golden 6/6 byte-
identical); derivation_harness golden untouched; believability golden
regenerated. Full lib + integration suites green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Records the T-1174 ruling: derive(seed, absolute world metres) via the
derive_at_metres family is the only derive core; the batch 64x32
pseudo-grid is re-scoped as a survey raster with a real SurveyCellPos
newtype (role name, not a D-243 rung); derive_district_profile becomes
a thin wrapper at survey-cell-centre positions with binding basin and
riparian preservation; point-feature terrain judgments move to exact
world positions; D-255 step canvases are fenced to the window family.
LayerRegionOutput rebuild deferred to T-1181 (tripwire verified: sole
reader is the region_grid overlay); voxel carrier deferred to Phase 5.
Consults: Tyre APPROVE-WITH-CHANGES, Dudley FEASIBLE-WITH-CHANGES —
both incorporated. Discharges the T-1174 blocker on D-255's T-1181
step-canvas envelope.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The interactive panel is no longer hand-composed per render: support/
panel-template.html carries the widget markup (CDS tokens, pick-up/detail
sendPrompt contract) and support/make-panel fills it with live pql data —
actionable WIP + unblocked leaf work from the active phase AND the
maintenance initiative T-1037 (the unblocked head T-1174 lives there, not
under the phase epic — a phase-only query missed it), sorted
status→priority→recency with overflow noted. SKILL.md §Interactive panel
now instructs: run the script, paste stdout as widget_code verbatim.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Second surface for the skill: an in-chat widget panel (WIP + unblocked
ready work, capped ~10 rows, native pql projections) with Pick up ↗ /
Detail ↗ per row and Refresh board / Next batch footer actions. Defines
the pick-up prompt contract ('pick up the following ticket: T-NNN — title'
→ single-ticket batch activation per the /whats-next step-3 flow). Records
the verified platform boundary: widget read-back is unsupported — panels
talk to Claude via sendPrompt only; the artifact stays reference-only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The artifact tab is sandboxed (no phone-home), so Claude cannot query the
tab's live selection; the copy-ref button in the ticket header copies
'viewing T-NNN — title' for a click-paste handoff (clipboard API with
prompt fallback). Selection also remains in the URL hash.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Jeroen's gap catch: T-750 never stated that the seed-to-tile cascade is
also what determines the world where the player walks. Now connected in
one statement across three homes: D-012 amendment (the founding 'chunks
load/unload around the player' driver now concretely = the D-227/D-239
cascade; 3x3 chunk neighborhood minimum, coarser context self-provided by
D-255(f) function composition, Atlas interaction never a precondition,
byte-identical either way), the matching T-750 deliverable note (in
changelog), and a one-truth consumer note on Q-093 for the Phase-5 insert
minimap (design deferred, no independent map pipeline expected).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tooling/pql-board-html: self-contained interactive board snapshot from
pql-native JSON (ticket list --full + batched --with-blockers for non-terminal
tickets + plan status) — status-grouped rail with filter/type chips, ticket
dossier with status pills, dep/children chips, deep links, keyboard nav;
clide's visual identity (amber on warm near-black, mono data type). The
/pql-board skill regenerates and redeploys to the canonical artifact URL so
the user's open tab survives refreshes across sessions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The complete workshop record: four round-1 positions, five round-2 syntheses
(incl. Troblum's adversarial pass with addendum + final scorecard — all seven
findings resolved), both lead interviews, Qatux's round notes and the 8-section
workshop-outcomes.md (the lakes message-crossing documented as process
history), measurement ⑥ (set_pixel/c1) + the population-survey and chunk/S2
addenda in the measurement docs, the brief's appendix updated through ⑥, and
architecture-briefing-final.md — Jeroen's outline written back as-built
(six-level ladder, lakes, ~9MB resident global tier). README row: Complete.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tyre C2: DownstreamTarget::OpenSpillway added — success (open low ground,
complete carved path) split from EdgeUnreachable (strict search exhaustion);
both doc comments exact; test updated. Tyre C3: determinism docstring
corrected (no BTreeMap; the endorheic f64 gate stated as deterministic-by-
derivation). Hoshe H1: vacuous cliff_edge test replaced by
single_basin_bowl_never_carves_a_gorge asserting the known-empty outcome.
Hoshe H2/H3: courses-force-empty disclosure at rect_window_replica and in
the results doc; courses.len() print added to the square production-fn
bench — measured 3/6/10 courses in window (NOT courses-empty, verified
twice); 'faithful stand-in' claim retracted for a precise scope statement;
GJ1c 18-course run identified as the sole production-density rate. Tyre C1:
appendix (4) headline rephrased — the tagged-envelope migration cannot be
dodged by payload optimization (byte math), field-count-rule trigger is a
workshop synthesis call; appendix (2) scope split per-shape.
Hydrology unit suite 15/15; atlas lib suite 679 green; benches compile.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The T-1177/T-1178/T-1154/T-1179/T-1180 in_progress transition wrote through
to the changelog after the sign-off commit; landing it per the
ticket-mutating-turn persistence rule.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cargo fmt across the four new files; needless_range_loop x2 (enumerate /
iter_mut) and identity_op in hydrology_equilibrium.rs. cargo test was green
on the bounced push — lint-only fixes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Four results docs under docs/workshops/body-map-viewer/measurements/ and the
brief's measurement appendix rewritten from owners/effort to MEASURED
headlines: settled hydrology viable (~24 ms/body, 273 bodies ~0.8 s);
parallel derive throughput holds 330K-8.3M cells (~64 ms / ~1.8 s); block+tile
cost-cleared (deepest step 83K cells ~17 ms); PNG-per-field smallest and
fastest with the tagged-envelope migration foreclosed by byte math (21x the
ceiling at the smallest size); texture upload a non-issue (8.3M px ~3.2 ms,
L8 4-9x cheaper). All numbers post-date the background-load closure with
stability re-runs. The workshop round-1 gate is satisfied.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>