--- title: "Round 1 Notes — Body Map Viewer Workshop" description: "Compiled record of Round 1 positions: per-question summary, cross-agent agreements, conflicts/tensions, the open-for-synthesis decision list, and scope-drift check against settled premises." type: workshop status: active workshop: body-map-viewer agent: qatux round: 1 created: 2026-07-25 --- # Body Map Viewer — Round 1 Notes **Compiled by:** Qatux **Round:** 1 — Positions against the measured appendix **Participants:** Dudley, Araminta, Stig, Tyre (Troblum is round 2 only) **Sources:** [dudley-round1.md](dudley-round1.md), [araminta-round1.md](araminta-round1.md), [stig-round1.md](stig-round1.md), [tyre-round1.md](tyre-round1.md) All four positions are argued from the measured appendix (①–⑤, [the brief's appendix](body-map-viewer-workshop-brief.md#pre-workshop-measurement-appendix)) with no extrapolation beyond what was measured — each agent says so explicitly and the citations check out against the four measurement docs. --- ## 1. Per-question position summary ### Dudley — server derivation (hydrology, step-canvas generation, chunking, cache tiers) 1. **Hydrology algorithm:** adopt T-1177's priority-flood + Dijkstra prototype as-is (production-shaped, not throwaway). Cost: ~24 ms/body single-threaded at 512×256; all 273 bodies in parallel ≈ 0.7–0.8 s; solved once per body (like `drainage::analyze` today), held in a D-203-shaped cache, never re-solved per step/request. 2. **Cliff representation:** `elevation` (unchanged) + `channel_depth: u16` + `cliff_edge: bool` — direct, non-lossy carry of solver output, no min/max synthesis. Gorge carving measured **structurally rare** (zero carved cells across all three production-scale benches) — weakens, doesn't eliminate, the wire-cost argument. Explicitly defers the Phase-4-vs-Phase-5 scope call to Tyre/Araminta. 3. **Canonical-vs-viewport (red flag 3):** **viewport-sized canvases at every step, no canonical fixed canvas past the orbital/region rung** — argued as a governance necessity (D-226(d)), not merely a cache-cost preference. Fixed pixel budget per canvas (e.g. 3840×2160), not literal client viewport echo. 4. **Compute-chunk partitioning:** the existing row-chunked `into_par_iter()` loop in `build_district_window_layer` holds flat (190–220 ns/cell) at every measured size and spacing — "the single most load-bearing measured result across all four gates." Flags that courses are excluded from the replica-loop numbers (small, bounded tax, not a different order of magnitude) and that chunking-as-seed-input-for-next-tier is unmeasured, an open data-flow question for round 2/implementation. 5. **Cache tiers:** global/orbital tier only, "always keep" ≈ ~174 MB PNG-encoded across all 273 bodies, as a D-203-shaped resource extension (not SQLite — cost doesn't force it). Everything finer: `TTL = BASE_TTL[rung] × time_decay × distance_decay`, no disk tier below orbital. ### Araminta — named-feature encoding, per-gridunit payload, encoding continuity 1. **Named-feature encoding is three decisions, not one**, per the existing carrier three-way rule: settlements/POIs → ids-with-lookup against the already-built `atlas_city_names` pool (D-223) — presence + id per gridunit, never inline name. Rivers → geometry already settled (T-1170 Ruling 1c `courses`); adds a new whole-body `river_names: BTreeMap` lookup, many-edges-to-one-name. Roads: out of scope but the pattern generalizes for free when they land. 2. **Payload schema:** the existing six dense fields stay as-is (no new classification vocabulary); one new dense field `settlement_id: Vec`; the cliff fields are **sparse, not dense** — a `cliffs: Vec` list parallel to `courses`, not two more mostly-zero dense arrays (this differs from Dudley's dense-field framing — see Conflicts below). States a hard client rule: color/style/tween presentation only, never invent geometry/flooding/cliffs — missing data is a schema gap, not a license to interpolate. 3. **Encoding continuity:** one colorizer family confirmed across every step (same field set, same enum vocabularies, only sampling density changes). Average-back is safe for continuous fields (`elev_q`/`temp_dc`/`moisture_q`) but **meaningless for categorical fields** (`morphology`/`vegetation`/`glaciation`) — coarser steps must re-derive via dominant-mode/plurality pick, never arithmetic mean. "Clearings/ponds at low zoom" is scoped as sub-zone octave detail within an existing classification, not new vocabulary — no new wire field needed. 4. **Wire-contract summary for synthesis:** confirms PNG-per-field for all dense arrays, MessagePack-native for sparse lists; confirms the payload is categorically over the 30 KB cap at every size regardless of her additions — doesn't change the tagged-envelope verdict. ### Stig — client component, step-cross UX, overlay compositing, cache store 1. **Client structure:** kill `_canvas.scale` entirely — two sibling layers replace it: RTT terrain/classification layer (texel-exact `ImageTexture`, generalizing the existing `_build_tile_texture`/`_rebuild_texture_if_needed` mosaic path from per-tile to universal) + an unscaled screen-space annotation layer (world→screen transform per frame, literal px sizes, deletes `_zs()`/`_zs_stroke()`/ `_zs_ring_radius()` by construction). T-1158 (viewer decomposition) is **subsumed** — recommends cancellation with a supersession note, not separate scheduling. 2. **Step-cross UX:** hold-fetch-swap baseline (cursor-anchored), cache-hit swaps immediately, cache-miss holds the current texture magnified during fetch (bounded by measurement ①/④: uncached 330K canvas ≈ 75 ms derive + 5 ms encode). Morph/tween is real but **strictly cosmetic and sequenced after** the baseline ships, as an optional toggle. Upload cost (⑤) confirmed non-gating; prefers `texture.update()` reuse over fresh allocation (avoids Texture object churn, despite being marginally slower in raw ms) and L8 wherever a plane is single-channel. 3. **Overlay compositing (c1):** **ship CPU `set_pixel` coloring first**, not shaders — today's code already does this and works; nothing in ①–⑤ prices CPU coloring cost at step-canvas scale (330K–8.3M cells), which Stig names explicitly as **the missing sixth measurement** (`Image.set_pixel` cost at those sizes). Shader migration is the natural landing spot for T-1175's tapering work later, not a precondition for the ladder itself. 4. **Client cache store:** **(iii) plain `FileAccess` cache dir + index** — rejects both (i) server-side SQLite (relocates a client decision onto the server's process boundary, dilutes the "server owns the DB" mental model) and (ii) godot-sqlite (a relational addon for a point-lookup-with-expiry access pattern that doesn't need one). Two-tier eviction: geometry entries get LRU + a retention floor at step-0 (the concrete "always keep global" mechanism, disk-budget-safe at ~440 MB where RAM would not be); sim-state-tagged entries get an explicit TTL sweep (the literal self-cleaning behavior Jeroen asked for). In-memory `atlas_window_tile_set.gd`-style LRU stays on top as the hot tier. ### Tyre — governance ratification, gridunit↔D-243, determinism boundary, cliff ruling 1. **Governance delta ratified as concrete amendment texts** (five, drafted and ready to file): D-166 corollary repoint (per-step derivation floor + display ratio, between-step magnification named as a bounded exception not a silent violation); T-1143 ruling 3 superseded for zoom transport only (cursor-centering/edge-scroll/ full-reset survive); `select_rung`/coverage-walk replaced by the step index; **tagged-envelope migration ruled triggered, not merely likely** (21×–563× over the ceiling, "off by two to three orders of magnitude before encoding is even considered"); T-1170 carrier rule survives with a terminology gloss only ("windowed payload" → "tagged step-canvas envelope"). 2. **Gridunit↔D-243 — the load-bearing call: gridunit SNAPS to D-243 rungs, does not float.** Argued from determinism (`derive_at_metres` on viewport-relative spacing would contaminate the cache key with a presentation parameter, breaking premise 9's "canvas for a fixed seed never changes") and from cost (measurement ③ shows no derivation-cost reason to invent a seventh spacing value — the six D-243 rungs already cover every depth cheaply). What floats instead: the **display ratio** (px-per-gridunit, 1×1 to 5×5), a pure client-side presentation parameter, decoupled from spacing. Files the D-243 gridunit vocabulary entry as "a role, not a new rung." 3. **Determinism boundary:** generalizes the T-1170 course-invention ruling into a three-bucket test — legal client interpolation is interpolation over a **closed, server-supplied input set** (two arrived textures, wire-carried control points); illegal is inventing any sample outside that set or smoothing across a step/ truncation/cliff boundary. Three concrete legal cases named (step-cross morph, river/road curve-fitting through wire-carried stations, texture-to-viewport scaling), two illegal (upsampling terrain detail, blending across a step boundary as if continuous), one gray case flagged for Araminta (label de-dup at coarse-step seams — legal only if identity, not proximity, drives it). 4. **Cliff ruling:** adopts Dudley's dominant-height + `channel_depth` + `cliff_edge` representation outright (settled by what the solver emits, zero re-derivation). **Rules Phase-4 Atlas scope, not deferred to Phase-5** — argues deferral would silently contradict "settled hydrology" itself (a map showing a smooth shoreline where the solver computed a carved channel misrepresents the settled state), and that the rarity finding makes inclusion nearly free rather than making exclusion safe. Flags his own caveat: rarity is measured on one real body (GJ1c) + two synthetics, not surveyed across ~273 bodies — names this explicitly as something for Troblum's round-2 adversarial pass to stress. --- ## 2. Cross-agent agreements (settled going into round 2 — do not re-litigate) - **Dudley, Araminta, Tyre** all treat the **tagged-envelope migration as settled by the numbers**, not a round-2 open question. Each cites T-1179 independently and lands on the same order-of-magnitude reading (21×–563× over the 30 KB cap). Tyre's position sharpens the brief's "likely triggers" framing to "triggered, unambiguous." Round 2 should treat *whether* as closed and spend synthesis time only on the *shape* of the tagged envelope (which is genuinely open — see §4). - **Dudley and Tyre** independently land on **viewport-sized canvases, no canonical fixed canvas past the orbital/region rung** — Dudley from cost-shape-plus-D-226(d) necessity, Tyre from the same D-226(d) argument plus the determinism/cache-key argument in his gridunit↔D-243 ruling. These are two independently-argued paths to the same conclusion, not one agent citing the other — worth naming as convergent, not coincidental. - **Dudley, Araminta, and Tyre all adopt the T-1177 cliff representation (`elevation` + `channel_depth` + `cliff_edge`) without dispute.** The only open edge is dense-vs-sparse wire shape (§3) and Phase scope (§3), not the field set itself. - **Araminta and Tyre agree explicitly** that the client may never invent geometry/flooding/cliff state — Araminta states it as a payload-schema hard rule, Tyre generalizes it into the three-bucket determinism-boundary test. Same conclusion, complementary framings (schema discipline vs. interpolation discipline). - **Stig and Dudley/Araminta agree** that morph/tween between steps is real, cosmetic-only, and non-blocking for the baseline — Stig sequences it as a follow-up after hold-fetch-swap ships; Tyre's bucket-A ruling gives it the determinism green light; nobody argues for shipping it in the first cut. - **All four agents report their four gated measurements (①–④) as clean GO/VIABLE results with no extrapolation** — no agent treats any of the pre-workshop numbers as contested or requiring a re-run. --- ## 3. Conflicts and tensions (named, not yet resolved) - **Dudley vs. Araminta — dense vs. sparse wire shape for the cliff fields.** Dudley's round-1 text frames `channel_depth`/`cliff_edge` as "the wire field" without specifying dense-array vs. sparse-list shape, and his cost argument ("cheap under any of the encodings in ④'s table... PNG's DEFLATE in particular loves a field that's constant almost everywhere") reads as implicitly assuming dense per-gridunit arrays alongside the other six. Araminta explicitly rejects that shape: "as dense per-gridunit arrays would be wasteful given near-zero occupancy" and proposes a sparse `cliffs: Vec` list parallel to `courses` instead. Tyre's synthesis leans toward Araminta's read ("I'd steer toward 'new arrays' over 'steal a bit'... a sparse-friendly encoding... helps this field cost less than its raw byte width suggests" — but this sentence is ambiguous on dense-vs-sparse, using "new arrays" language while endorsing a sparse-friendly encoding argument). **This needs an explicit round-2 resolution, not an inferred one** — the three positions are close but not identical, and "new arrays" (Tyre) vs. "sparse feature list, not arrays" (Araminta) is a real implementation-shape fork even if the wire bytes converge. - **Stig vs. the brief's implicit assumption — shader-vs-CPU (c1) is not close to resolved, and Stig's position is a deferral, not an answer.** The brief posed c1 as "genuinely open for the workshop"; Stig's position doesn't rule for CPU on the merits so much as rule for CPU *by default* pending a measurement that doesn't exist yet. This isn't a disagreement with another agent (no one else took a position on c1), but it is a gap between what the brief expected round 1 to produce (a position) and what it got (a sequencing recommendation plus a flagged missing measurement) — surfaced here so the lead interview doesn't mistake "ship CPU first" for "shader question closed." - **Scope-boundary tension, not a disagreement: Dudley defers the Phase-4-vs-Phase-5 cliff-scope call to "Tyre/Araminta," and Tyre rules on it unilaterally** ("Phase-4 Atlas scope, not deferred to Phase-5") in the same round without an explicit Araminta sign-off in her own document (her round-1 text adopts the field shape but does not independently address the Phase-4-vs-Phase-5 question at all). Tyre's ruling may be correct and well-argued, but strictly by the documents, it is a two-of-three-invited-parties call, not a three-way confirmed one — worth a direct Araminta confirm-or-object in round 2 rather than treating it as fully closed. --- ## 4. OPEN-FOR-SYNTHESIS decision list (for the lead interview) Carried into Jeroen's Round 1 lead interview and/or Round 2 synthesis, in the order the brief's Expected Outputs raises them: 1. **Step count and step factor** (largest → visible tile) — every agent treats this as still-open and downstream of their own numbers; Dudley's table gives per-rung costs but explicitly does not propose a step count. This is the brief's own Jeroen-interview question 2 and remains unanswered by round 1. 2. **Map time axis** (climatology vs. current sim state for frozen/flooded) — not addressed head-on by any of the four round-1 documents beyond Araminta's schema table flagging it as "where the outline's sea/flooded distinction needs a decision the workshop, not me, should rule on." Still fully open; this is Jeroen-interview question 1. 3. **Tagged-envelope migration shape** (not the yes/no, which is agreed — see §2 — but the concrete framing: new IPC message type, demux mechanics, how the legacy `district_window` carrier coexists) — Tyre's amendment text names the destination but defers the mechanical design; this is round-2 synthesis work. 4. **Cliff field wire shape: dense arrays vs. sparse feature list** — the Dudley/ Araminta/Tyre tension in §3, needs an explicit round-2 call, not an inferred one. 5. **Cliff field Phase-4 vs. Phase-5 scope** — Tyre ruled Phase-4; Araminta has not independently confirmed; the §3 two-of-three tension needs closing explicitly. 6. **Shader-vs-CPU styling (c1)** — Stig's position is "CPU first, sequence shader later," not a resolution of the open question the brief posed. **Depends on the missing sixth measurement (below) before it can be treated as settled even provisionally.** 7. **NEW: the missing sixth measurement — `Image.set_pixel` cost at 330K/2.07M/8.3M cells (GDScript, client-side).** Stig names this explicitly as a gap: nothing in measurements ①–⑤ prices CPU per-cell coloring cost at step-canvas scale, and the c1 shader-vs-CPU call cannot be made "with the same rigor as everything else in this brief" without it. This should be added to the measurement appendix (as ⑥) or explicitly scoped as a round-2/pre-implementation follow-up — flagging per the coordinator's instruction that this lands in the decision list, not just Stig's own document. 8. **Chunking-as-seed-input-for-next-tier data flow** — Dudley flags this as unmeasured and architecturally undecided (does a finer step re-derive independently from `(seed, position)`, or literally consume the coarser step's output values?). His own cost measurements assume independent re-derivation; round 2 needs to either confirm that assumption or scope a new cost pass if the alternative is preferred. 9. **Region-as-step-0 confirmation** — Tyre's §1e amendment note flags this needs confirming with Araminta in round 2 synthesis ("Region likely IS the global/step-0 rung, worth confirming"). 10. **The gray determinism case — label placement de-duplication at step seams** — Tyre flags this explicitly as unresolved and hands it to Araminta's named-feature call; not yet addressed in her document. --- ## 5. Scope-drift check against settled premises No round-1 document relitigates a settled premise (1–9) or a "settled by round A" clarification-round item. Specific checks: - **Stepped zoom, vocabulary (tile vs. gridunit), data-resolution tunable, hydrology as deterministic equilibrium** — all four agents use the settled vocabulary and model correctly throughout; no drift back to continuous zoom or "tile" misuse detected in any of the four documents. - **Server-determines-content / client-draws-art (premise 2)** — held firmly by all four; Araminta's explicit client-rule statement and Tyre's determinism-boundary bucket test both *reinforce* this premise rather than erode it. No agent proposes client-side derivation of any invented-detail category. - **CPU/Rust-server-side-only derivation, GPU presentation-only (premise 2, the c2 pre-empt)** — untouched; Stig's shader discussion (c1) is explicitly about *styling/coloring already-derived data*, not derivation, and he states this distinction himself. No drift toward GPU-side derivation anywhere in round 1. - **One caution, not a violation:** Stig's structural recommendation to cancel T-1158 outright (not just note supersession) is a **ticket-plan action**, one category beyond a "position" — it's appropriate content for round 1 (the brief's Expected Output 2 explicitly wants conflicting tickets named), but it is a concrete cancellation recommendation rather than a design position, worth the lead noting as an actionable item distinct from the architecture questions proper. - **No Phase-5/Phase-6 drag detected.** Stig explicitly declines to scope Phase-5 reuse speculatively ("I don't want to speculatively design against now — that would be exactly the kind of later-phase drag the cascade discipline warns against") — this is the correct cascade-discipline call, named here because it's a positive scope-discipline example, not a violation. --- ## Summary for the lead interview Round 1 produced four internally consistent, cross-citing positions with **no cost surprises** — every measured gate came back GO, and three of the four agents converge on viewport-sized canvases and the tagged-envelope migration independently. The genuinely open items are load-bearing but narrow: step count itself, the map time axis, the cliff field's wire shape (dense vs. sparse) and phase scope, the shader-vs-CPU call (blocked on a **new, named missing measurement** — `Image.set_pixel` cost at step-canvas scale), and two smaller synthesis-confirmation items (chunking/seed-input data flow, Region-as-step-0). Nothing here requires relitigating a settled premise, and no scope drift toward later cascade phases was observed.