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>
921 lines
60 KiB
Markdown
921 lines
60 KiB
Markdown
---
|
||
title: "Body Map Viewer — Troblum Round 2 (Adversarial Pass)"
|
||
description: "Stress-test of the round-1 measured claims and cache/governance proposals against real play patterns — findings ranked by severity"
|
||
type: workshop
|
||
status: active
|
||
workshop: body-map-viewer
|
||
round: 2
|
||
owner: Troblum
|
||
decision_refs: [D-166, D-226, D-227, D-243, D-203, D-225, D-192, D-005]
|
||
---
|
||
|
||
# Troblum — Round 2 Adversarial Pass
|
||
|
||
Read the brief (incl. the MEASURED appendix), `lead-interview-1.md`, `round-1-notes.md`,
|
||
all four round-1 position files, and all four `measurements/*.md` docs in full before
|
||
writing this. No `{agent}-round2.md` files existed at the time this was written —
|
||
I flag anywhere that matters below.
|
||
|
||
I went into this expecting to find sloppy extrapolation. I didn't find much of
|
||
that — the four measurement docs are unusually disciplined about the
|
||
MEASURED/ARITHMETIC distinction, and every round-1 agent cites correctly. What
|
||
I found instead is more interesting: **two population-scale claims that
|
||
were never actually tested at population scale** (they were tested for
|
||
*throughput*, not for the *property being claimed*), one arithmetic units
|
||
slip, one real governance-purpose gap in the D-226(d) boundary that survives
|
||
the letter of the rule, and a cache/eviction design that has never been
|
||
pressure-tested against a play session shaped differently than "look at one
|
||
step canvas once." Findings below, most severe first.
|
||
|
||
---
|
||
|
||
## BLOCKING
|
||
|
||
### B1. The "273 bodies" hydrology parallel-throughput bench is the SAME body solved 273 times — it proves nothing about cliff rarity across the population, and the workshop is about to file a Phase-4 ruling that leans on "rare" as a population-level property
|
||
|
||
**The claim as stated:** T-1177's headline: *"all 273 bodies Rayon-parallel ~0.7–0.8s"*, cited by Dudley (Q1, Q4), and Tyre's cliff ruling explicitly says *"real planetary heightmaps beyond the one body sampled may differ"* but still files "Phase-4 Atlas scope, not deferred" on the strength of a rarity finding whose own caveat says it's measured on "one real body (GJ1c) plus two synthetic gradients."
|
||
|
||
**What actually breaks it:** I read the bench source directly
|
||
(`server/tests/hydrology_equilibrium_bench.rs:233-260`,
|
||
`bench_parallel_273_bodies_at_512x256`). It calls `gj1c_512x256()` **once**,
|
||
then solves that **identical elevation array** 273 times in a `par_iter`:
|
||
|
||
```rust
|
||
let (elev, sea_level) = gj1c_512x256();
|
||
let body_count = 273usize;
|
||
let total_basins: usize = (0..body_count)
|
||
.into_par_iter()
|
||
.map(|_| {
|
||
let result = solve(&elev, 512, 256, sea_level, default_climate());
|
||
result.basins.len()
|
||
})
|
||
.sum();
|
||
```
|
||
|
||
This is a **throughput** measurement (can the Rayon pool solve 273 independent
|
||
jobs of this size in under a second — yes) wearing a **population-diversity**
|
||
measurement's headline ("all 273 bodies"). It answers "is per-body-open
|
||
hydrology affordable" (yes, cleanly) — it does **not** answer, and was never
|
||
designed to answer, "does cliff carving stay rare across 273 distinct real
|
||
terrains." The 273-basin-count sum reported (`total_basins`) is 273× GJ1c's
|
||
own 68 basins — a tell, if anyone checks it, that this is one terrain
|
||
replayed, not 273 terrains sampled.
|
||
|
||
Nobody in round 1 mis-states this — Dudley's text says "512×256 (real GJ1c
|
||
working grid)" for the single-body cost row and correctly separates it from
|
||
the parallel-throughput row, and Tyre's caveat is honest about the *sampling*
|
||
limitation. But the round-1 notes and the lead interview both let "all 273
|
||
bodies" stand unqualified as a headline in the appendix table, and the cliff
|
||
ruling (already ratified by silence for the representation, and provisionally
|
||
ruled Phase-4 by Tyre) is exactly the kind of decision where "how often does
|
||
this fire across the real population" is load-bearing for the wire-cost
|
||
argument that makes Phase-4-not-Phase-5 attractive in the first place ("nearly
|
||
free... because it's a mostly-zero field").
|
||
|
||
**The mandate's own hint turns out to be directly actionable, and cheaper than
|
||
advertised.** The brief's Troblum question asks "is there a cheap pre-filing
|
||
check (run the solver across the real 273-body population — the bench exists
|
||
and takes ~0.8s)?" — the bench that exists does NOT do this, but a real one is
|
||
nearly free to build from what's already checked in:
|
||
|
||
```
|
||
$ find wiki/star-systems -iname heightmap.png | wc -l
|
||
267
|
||
```
|
||
|
||
267 real heightmap PNGs are already committed (close enough to "273 inhabited
|
||
bodies" that the six missing are very unlikely to change the finding
|
||
qualitatively). `gj1c_512x256()` already shows exactly the load/downsample
|
||
pattern needed (`load_heightmap_png` + `.downsample(512,256)`); a population
|
||
survey is: loop the 267 paths, load+downsample+solve each, count
|
||
`cliff_edge.iter().filter(|&c| c).count()` per body, report the distribution
|
||
(bodies-with-zero-carves vs bodies-with-nonzero, and the max carved-cell count
|
||
seen). At ~24ms/body single-threaded (the GJ1c number) or parallelized across
|
||
the Rayon pool the same way the throughput bench already demonstrates,
|
||
267 REAL bodies solve in well under the same ~0.7–0.8s ballpark. This is not a
|
||
"more research needed, defer the decision" finding — it's "run this one
|
||
already-half-built script before filing the cliff D-record," and it costs
|
||
minutes, not a round-3.
|
||
|
||
**Severity and why BLOCKING, not SERIOUS:** the cliff ruling is about to be
|
||
filed as a D-record amendment with "rare, cheap to carry" as its central
|
||
argument for Phase-4 inclusion. If the real population survey finds even a
|
||
double-digit percentage of bodies with genuine carving (plausible — GJ1c's
|
||
`tectonic_class`/`hydrosphere` params are one point in a parameter space that
|
||
explicitly includes `Volcanic`/high-relief bodies per D-239 §5's morphology
|
||
gates, and D-239 §1 explicitly flags `RIVER_THRESHOLD` as eventually
|
||
per-body-class-derived, not the fixed 200 this prototype borrowed), the wire-
|
||
cost argument doesn't just weaken, the field stops being "mostly zero" and
|
||
Araminta's sparse-list encoding choice (near-free at near-zero occupancy)
|
||
needs re-costing at whatever the real occupancy rate turns out to be. Filing
|
||
now on the untested assumption risks a silent contradiction the moment
|
||
someone actually looks at a mountainous body's Atlas map and it should show
|
||
gorges that a "rare" assumption undersized the format for.
|
||
|
||
**What resolves it:** run the population survey (concrete, minutes of work,
|
||
harness 90% exists) before the D-record for the cliff ruling is filed. Report
|
||
back: (a) fraction of the 267 real bodies with ≥1 carved cell, (b) max carved-
|
||
cell count on any single body, (c) whether any body's carve count is large
|
||
enough to threaten the "mostly zero" premise Araminta's sparse-list sizing
|
||
assumes. If the finding holds (most bodies still zero, a minority nonzero but
|
||
bounded), the existing ruling stands and gets a stronger evidence base for
|
||
free. If it doesn't hold, better to know before filing than after.
|
||
|
||
---
|
||
|
||
### B2. "Cost does not gate any step in the ladder" is true for derivation but silently assumes independent re-derivation at every step — the one architecture question everyone flagged as unmeasured (seed-chaining vs consuming the coarser output) is exactly the assumption every cost number in the brief depends on, and it is explicitly still open
|
||
|
||
**What breaks it:** Dudley states this cleanly himself (Q3, "One thing I did
|
||
NOT measure..."): every ns/cell number in T-1178/T-1154 assumes each step
|
||
**re-derives independently from `(seed, position)`**, not that a finer step
|
||
consumes a coarser step's already-computed values as input. This is flagged
|
||
as "an open data-flow question for round 2," not resolved by anyone, and it
|
||
does not appear in any of the four round-1 documents as a *ruled* item — it's
|
||
listed in round-1-notes.md's OPEN-FOR-SYNTHESIS item 8, still open at the time
|
||
I'm reading this.
|
||
|
||
Here's why this is BLOCKING rather than a tidy loose end: **the two candidate
|
||
architectures have different scaling shapes under step-thrashing** (my
|
||
mandate's own named stress scenario), and nobody has priced the one the
|
||
outline's own text seems to prefer. Re-read Jeroen's outline verbatim:
|
||
*"This at the same time serves as seed information for the deeper cascade."*
|
||
That's not "the coarser step happens to also be re-derivable independently" —
|
||
it reads as an intentional data-flow claim that the coarser canvas
|
||
**functions as seed input** for the next tier. If that's the intended
|
||
architecture (not just Dudley's simplifying assumption for benching purposes),
|
||
then:
|
||
|
||
- **Every measured cost number in ①②③ prices the WRONG architecture.** A
|
||
step that consumes the coarser tier's output as an input needs that coarser
|
||
tier resident/computed first — which either means step-N+1 has a hard
|
||
dependency edge on step-N (serializing what's currently modeled as
|
||
independent parallel derivation), or it means the "seed information" framing
|
||
is loose language for "informs the RNG stream," which is a different and
|
||
much smaller claim than "consumes the values."
|
||
- **Step-thrashing (my mandate's named scenario) has opposite costs under the
|
||
two models.** Independent re-derivation: zooming out then back in
|
||
re-derives step-N from scratch (measured: 63.7ms–1.8s depending on canvas
|
||
size) — cache-miss cost is a flat per-step number. Consuming-coarser-output:
|
||
zooming out then back in either (a) re-uses the still-cached coarser output
|
||
as an input, making a re-zoom-in CHEAPER than the numbers in this brief
|
||
suggest, or (b) if the coarser tier itself got evicted (see B3/S1 below,
|
||
storage-eviction is now a real design axis), the finer tier's re-derivation
|
||
chain-reacts backward through however many rungs got evicted, which is a
|
||
cost story NOBODY has measured and that gets worse, not better, exactly in
|
||
the play pattern the mandate asks me to stress (a player who steps
|
||
in-out-in-out while exploring, potentially re-triggering upstream rungs).
|
||
|
||
**This is not a hypothetical distinction — it changes what "measured, not
|
||
extrapolated" means for the whole appendix.** If round 2 or round 3 lands on
|
||
the consuming-coarser-output model (which reads as closer to what the outline
|
||
actually asked for), literally every ①②③④ cost number needs a footnote at
|
||
minimum, and possibly a re-bench, because none of them price a dependency
|
||
chain.
|
||
|
||
**Severity:** BLOCKING because it's not a refinement of an accepted
|
||
architecture — it's a fork in the architecture itself that the brief's own
|
||
Expected Output 3 ("the step ladder... deepest step's canvas policy") cannot
|
||
honestly be finalized without resolving. Filing the D-record for "cost does
|
||
not gate any step" without this resolved risks the record citing numbers that
|
||
don't describe the shipped system.
|
||
|
||
**What resolves it:** explicit round-2/round-3 ruling: does a finer step's
|
||
derivation (a) call `derive_at_metres(seed, position, finer_spacing)`
|
||
independently, treating the coarser canvas as *display-continuity input only*
|
||
(Dudley's assumption, what's actually been measured), or (b) literally sample/
|
||
consume the coarser step's resolved field values as part of its own derivation
|
||
(the "seed information for the deeper cascade" reading)? If (b), a fresh cost
|
||
pass is needed before the ladder table in Expected Output 3 can cite the
|
||
existing numbers as authoritative for that shape.
|
||
|
||
---
|
||
|
||
## SERIOUS
|
||
|
||
### S1. Evict-then-revisit cost spikes are real and un-costed — Jeroen's storage-eviction amendment interacts with the TTL(detail,time,distance) formula in a way nobody has priced end-to-end
|
||
|
||
**The scenario (my mandate's #2/#5):** Jeroen's lead-interview ruling adds
|
||
storage-eviction on time-since-last-visit as a second, independent axis from
|
||
staleness-eviction — *"we still may also want to evict non-global-level
|
||
geometry based on time to save storage for planets the player visits but
|
||
never goes back to."* Good instinct, but nobody has run the number on what a
|
||
revisit costs once eviction actually fires.
|
||
|
||
**The arithmetic (grounded in T-1179's measured derive+encode numbers):** a
|
||
single 330K-cell district-rung canvas costs 74.8ms derive + 5.41ms PNG-encode
|
||
= **80.2ms** to regenerate server-side (before wire transfer and client
|
||
decode/upload, which measurement ④/⑤ show add a further ~4-10ms each). A
|
||
player who explored, say, 20 distinct district-rung windows of a body during
|
||
one long-ago visit, gets storage-evicted on time-since-visit, and returns:
|
||
**20 × 80.2ms ≈ 1.6 seconds of pure server derive+encode cost concentrated
|
||
into the moment they re-open that body's Atlas view** — before wire and
|
||
client costs are even added. That's not catastrophic, but it's also not
|
||
"snappy re-navigation," which is the entire stated purpose of the "always keep
|
||
global" instinct this eviction rule is explicitly carved out from. And this is
|
||
the OPTIMISTIC case — District rung. A player who was deep-stepping (Block or
|
||
Tile rung, viewport-sized canvases) across many locations before abandoning
|
||
the body has a much larger number of small entries to re-derive, and nobody
|
||
has counted how many viewport-sized canvases a typical "explore a city" session
|
||
generates.
|
||
|
||
**What nobody has specified, and needs to be specified before this ships:**
|
||
1. **Does storage-eviction apply per-entry (fine-grained, LRU-by-canvas) or
|
||
per-body (coarse, "haven't opened this body's Atlas in N days, drop
|
||
everything but global")?** Stig's `FileAccess` design (round 1, §4) says
|
||
"two-tier eviction... geometry entries get LRU + a retention floor at
|
||
step-0" — that's per-entry LRU, which means a body a player visits
|
||
*occasionally* (not "never goes back to," but not "frequently" either)
|
||
could have some of its sub-global entries evicted and others not,
|
||
producing a **partial-revisit cost** that's neither the full 20-canvas
|
||
number above nor zero — an unmeasured middle case that's actually the
|
||
MOST common real pattern (players revisit systems they've been to before,
|
||
irregularly, not never/always).
|
||
2. **Does the TTL formula's `distance_decay` term fight the storage-eviction
|
||
rule?** Dudley's TTL formula (`ttl = BASE_TTL[rung] × time_decay(age) ×
|
||
distance_decay(distance_from_focus)`) already decays entries far from
|
||
current focus faster. If storage-eviction is a *second*, independently-
|
||
timed sweep on top of that TTL, a body the player is CURRENTLY navigating
|
||
(high focus, TTL should be long) could still hit a storage-eviction sweep
|
||
timed off calendar/session time rather than in-session focus, evicting an
|
||
entry the TTL formula would have kept. Nobody has specified which axis
|
||
wins, or whether they're the same mechanism wearing two names (round-1
|
||
notes doesn't resolve this either — it's absent from the OPEN-FOR-SYNTHESIS
|
||
list entirely, which itself is a gap: this should have been item 11).
|
||
|
||
**Severity:** SERIOUS, not BLOCKING, because the base numbers (80ms/canvas
|
||
regen) are cheap enough that even an unoptimized worst case doesn't "catch
|
||
fire" — but it's serious because the FEEL goal ("atlas navigation snappy after
|
||
first calc," Dudley's own words) is explicitly what this mechanism could
|
||
undermine for exactly the play pattern (occasional revisits) that's most
|
||
common, and nobody has written down the eviction granularity or the two-axis
|
||
interaction rule.
|
||
|
||
**What resolves it:** round-2/3 synthesis needs to state explicitly: (a)
|
||
eviction granularity (per-canvas vs per-body), (b) which axis (TTL distance-
|
||
decay vs storage-eviction time-since-visit) is authoritative when they
|
||
disagree, (c) a worst-case revisit number using whatever granularity is
|
||
chosen, computed the way I did above but for the actual chosen unit.
|
||
|
||
---
|
||
|
||
### S2. The courses-inclusive rate is measured ONCE, at light density (18 courses), on ONE body — every step-thrashing/deep-pan cost projection implicitly assumes this generalizes, and the workshop's own document says not to generalize it
|
||
|
||
**What the measurement actually licenses, read carefully:** T-1178's own text
|
||
is explicit and correct about the limits of what it found — I want to confirm
|
||
this is NOT itself a finding of extrapolation (the document is honest about
|
||
its own scope), but flag that the workshop's *use* of the number downstream
|
||
risks over-generalizing what the document itself carefully scoped.
|
||
|
||
The 195.0 ns/cell "courses-inclusive, real density" number comes from **one**
|
||
window on **one** body (GJ1c, district `(7520, -2932)`, 18 courses in a
|
||
331,776-cell window) — chosen specifically because it's the densest course
|
||
window anyone happened to measure. The document's own H3 finding says the
|
||
headline table's square-path numbers are courses-inclusive but SPARSE (3-10
|
||
courses), and explicitly warns: *"The courses-inclusive rate at REAL
|
||
production course density is covered only by Cross-check 1... cite that
|
||
number, not the headline table, for a courses-representative rate."*
|
||
|
||
That's good discipline — but it means the entire ladder's cost story for a
|
||
**river-delta body, a body with many parallel drainage channels, or a densely
|
||
riverine biome** (all real terrain classes D-239's morphology gates
|
||
explicitly support — BraidedDelta, MeanderReach, AlluvialPlain families) is
|
||
projected from **one 18-course sample on one body**, not from a density
|
||
distribution across real terrain types. 18 courses in a 331K-cell window is
|
||
"nearly 2× the synthetic body's density" per the document's own framing — but
|
||
"2× the driest measured case" is not the same claim as "representative of the
|
||
densest real case." A body whose morphology leans heavily toward
|
||
BraidedDelta/MeanderReach (the exact families D-239 §5 names as real,
|
||
selectable outcomes) could plausibly carry courses at meaningfully higher
|
||
density than GJ1c's 18-in-331K, especially at the deep Tile/Block rungs where
|
||
a dense river network's tributaries are all individually resolvable (the
|
||
deep-step 83K bench explicitly EXCLUDES courses entirely, per H2 — so the one
|
||
number closest to "the actual deepest, most course-dense scenario" is the one
|
||
number this whole measurement set has zero data on).
|
||
|
||
**Why this matters for step-thrashing specifically (my mandate's named
|
||
scenario):** a player panning rapidly around a river delta at Block/Tile
|
||
spacing generates many step canvases in quick succession, each paying the
|
||
per-cell course cost. The <5% bound is well-established at District spacing
|
||
and light-to-moderate density — it has never been checked at Block/Tile
|
||
spacing (where course geometry is proportionally a larger fraction of a much
|
||
smaller viewport) or at delta-class density (where course COUNT, not just
|
||
per-course cost, could be several multiples of GJ1c's 18).
|
||
|
||
**Severity:** SERIOUS not BLOCKING. The <5% bound has enough headroom
|
||
(measured against a ~5ms District-cap baseline) that even a 3-4x density
|
||
multiplier at a river-dense body likely stays affordable — this isn't a
|
||
"computer catches fire" risk. But it is a real, named gap in the "measured
|
||
not extrapolated" claim the whole batch prides itself on, specifically at the
|
||
one spot (deep-step, high-density river terrain) where the excluded cost is
|
||
least likely to stay proportionally small.
|
||
|
||
**What resolves it:** one additional bench — deep-step (83K-cell, Block or
|
||
Tile spacing) window on a body selected for high course density (a
|
||
BraidedDelta or MeanderReach-dominant body, if the catalog can be queried for
|
||
morphology-family distribution; failing that, a synthetic river network
|
||
authored to be denser than GJ1c's). Cheap to add given the harness already
|
||
exists; closes the one density/spacing combination the current appendix has
|
||
literally zero coverage of.
|
||
|
||
---
|
||
|
||
### S3. The D-226(d) whole-body prohibition survives the LETTER at every single step, but the client-side cache accumulation mechanism has no structural ceiling — the purpose of the rule (no metre-resolution whole-body derivation) is defended only by "nobody will pan that much," not by construction
|
||
|
||
**The stress test my mandate asked for, run concretely:** Dudley and Tyre's
|
||
independently-argued convergence on viewport-sized canvases is correct and I
|
||
have no finding against the SERVER-side policy — it holds cleanly, and the
|
||
17ms/83K-cell number genuinely is never a whole-body derivation on any single
|
||
request. That part clears.
|
||
|
||
But the mandate specifically asks whether "pan-assembled coverage over time
|
||
amounting to whole-body at fine spacing" is a real boundary risk given
|
||
client-side cache accumulation (Stig's `FileAccess` store, premise 9). Here's
|
||
the number: covering GJ1c's own 512×256-district working-grid extent
|
||
(1,048.576 km × 524.288 km — the equirectangular working-grid footprint, a
|
||
reasonable proxy for body coverage) with deep-step viewport tiles (216m ×
|
||
384m, the measured 82,944-cell shape) requires **~6.6 million tiles**, at
|
||
~156 KB PNG-encoded each (interpolated from T-1179's per-cell PNG rate),
|
||
totaling **~985 GB** on disk to fully assemble one body at 1m spacing via
|
||
client-cached viewport canvases.
|
||
|
||
That number is obviously never going to happen by accident in normal play —
|
||
which is exactly why I'm calling this SERIOUS, not BLOCKING: no player is
|
||
going to pan a Tile-spacing viewport across 6.6 million distinct windows.
|
||
**But "obviously not by accident" is a practical-infeasibility argument, not a
|
||
structural one**, and the round-1 documents (Dudley's and Tyre's both) argue
|
||
the viewport-sizing rule as a *governance necessity*, i.e., as the thing that
|
||
keeps the design "legal by construction." It is legal by construction
|
||
**server-side** (no single request ever asks for whole-body coverage) — it is
|
||
legal only by *practical improbability* **client-side**, once a disk-backed,
|
||
retain-forever-until-evicted cache is added on top. If a determined player (or
|
||
a QA/agent harness doing exactly the kind of automated systematic sweep
|
||
D-226(4)'s `AtlasAgentInterface` explicitly builds for) methodically panned a
|
||
body at Tile spacing to completeness — slow, but not physically prevented by
|
||
any mechanism in this design — the client's own disk cache would, over time,
|
||
assemble the exact near-whole-body metre-resolution artifact D-226(d) exists
|
||
to forbid. It would just be assembled as N discrete files rather than one
|
||
canonical canvas, which is a difference of *packaging*, not of *information
|
||
content* — and the rule's stated purpose (avoid a whole-body metre-resolution
|
||
planetary map layer existing) is about information content, not file count.
|
||
|
||
**This is exactly the gap the mandate asked me to name: does accumulation
|
||
violate the rule's PURPOSE even if not its letter?** My answer: yes, in
|
||
principle, though the practical risk is low given the tile count required.
|
||
The more concrete risk isn't "a player does this for fun" — it's the
|
||
**agent-navigable QA channel D-226 item (4) already built** (`AtlasAgentInterface`,
|
||
`observe`/`act`, described explicitly as turning "human-eyeball review into an
|
||
agent-automatable QA sweep across the whole Reach"). An automated sweep is
|
||
precisely the actor most likely to do a systematic, exhaustive pan — and if
|
||
that sweep's client-side cache is retained (the "always keep global" +
|
||
LRU-with-retention-floor design does NOT explicitly exclude an automated
|
||
client from accumulating sub-global entries without bound), a QA run against
|
||
one body at fine spacing could, over enough wall-clock time, produce the
|
||
forbidden artifact as an unintended side effect of testing, sitting quietly
|
||
in `user://atlas_cache/`.
|
||
|
||
**Severity:** SERIOUS. Doesn't block shipping the ladder (the server-side
|
||
policy is sound and the practical risk from normal play is genuinely low),
|
||
but it's a real gap between letter and purpose that a workshop explicitly
|
||
concerned with "not just cost, a governance boundary" (red flag 3's own
|
||
framing) should close on paper, not leave to improbability.
|
||
|
||
**What resolves it:** state explicitly, as part of the D-226(d) amendment
|
||
text, that the **prohibition is a per-request/per-derivation constraint, not
|
||
an aggregate-storage constraint** — and separately, add an explicit cap on
|
||
client-side cache retention at deep rungs (a maximum resident tile count or
|
||
disk quota per body at Tile/Block spacing, independent of the "retention
|
||
floor at step-0" rule that already exists for the global tier). This turns
|
||
the current "improbable in practice" defense into an actual structural
|
||
ceiling, which is the same discipline the rest of this workshop already
|
||
applies everywhere else (measured numbers, not vibes).
|
||
|
||
---
|
||
|
||
### S4. Sim-state determinism for frozen/flooded is real (D-228 already answers "what serves them"), but the TTL-split's staleness boundary depends on a "phase" granularity nobody in this workshop has named, and the water-height mechanism is NOT wired to the map yet
|
||
|
||
**What I verified clears (good news first, per my mandate's instruction to
|
||
report clean findings explicitly):** the "are frozen/flooded actually
|
||
deterministic per (seed, sim-time)?" half of my mandate's question 5 checks
|
||
out cleanly. D-228 (already-filed, not a round-1 invention) states the
|
||
mechanism precisely: water-height is *"a region property computed once per
|
||
phase (not per tile, not per frame)... a pure function... recomputed on phase
|
||
change"* — a seasonal term phased continuously by latitude plus an optional
|
||
tidal term. This is genuinely deterministic given `(seed, region, phase)` —
|
||
no RNG, no accumulation, matches D-010. **Cleared: sim-state components for
|
||
water-height are deterministic per the existing, already-filed D-228 model —
|
||
this is not a new risk the body-map-viewer workshop introduces.**
|
||
|
||
**What is NOT cleared, and is a real gap for the TTL-split ruling (Jeroen's
|
||
lead-interview #2):** "recomputed on phase change" begs the question this
|
||
workshop needs an answer to and hasn't produced one: **what triggers a phase
|
||
change, and at what granularity does the client's TTL need to re-request to
|
||
stay non-stale?** D-228's own text names two clock terms (seasonal — a "year
|
||
clock," continuous by latitude; tidal — a lunar/day clock, only present with
|
||
a moon) but "computed once per phase" doesn't say how long a phase lasts in
|
||
real sim-time, and nothing in the four round-1 documents or the measured
|
||
appendix touches this. Jeroen's own TTL hint ("maybe shorter ttl on the
|
||
climate sim state components") is a directional instinct, not a number — and
|
||
it can't be turned into one without knowing the phase cadence.
|
||
|
||
**The concrete failure mode this produces:** if a phase is short (say, a tidal
|
||
term on a body with a fast-orbiting moon — plausible given the system catalog
|
||
includes many-moon systems) and the client's TTL is tuned assuming a
|
||
seasonal-length phase, a player who holds a view over a coastal/tidal-flat
|
||
gridunit across a phase boundary sees **stale flooded/dry state** rendered
|
||
past its validity window — not a crash, not data corruption, just a quietly
|
||
wrong map for however long the TTL overshoots the real phase cadence. The
|
||
inverse failure (TTL too short) re-requests a sim-state plane that hasn't
|
||
actually changed, which is wasted wire/derive cost but not a correctness bug
|
||
— asymmetric risk, meaning erring toward "too short" is the safe default, but
|
||
nobody has stated that as a design rule either.
|
||
|
||
**Severity:** SERIOUS, not BLOCKING — the determinism substrate is sound
|
||
(the good-news half above), and this is a tuning-parameter gap, not an
|
||
architecture gap. But it's a real gap: Jeroen explicitly ruled the TTL-split
|
||
model as the working answer at lead-interview-1, and the model as ruled has an
|
||
unfilled variable (phase cadence) that determines whether it actually holds
|
||
in play.
|
||
|
||
**What resolves it:** name the phase cadence (or the range of cadences across
|
||
body types — tidal-locked/fast-moon bodies vs moonless/seasonal-only bodies
|
||
plausibly need different `BASE_TTL` values for the sim-state plane, similar
|
||
to how Dudley's own `BASE_TTL[rung]` is already per-rung) before finalizing
|
||
the TTL formula's sim-state branch. This is a Dudley/Araminta follow-up, not
|
||
something I can resolve from the measured appendix — flagging it as an
|
||
unanswered input the round-2 synthesis needs, not asking for a re-bench.
|
||
|
||
---
|
||
|
||
### S5. The disk-backed client cache has no schema/version field on cached entries — the one place D-192's "client+server always co-ship, no version skew" guarantee genuinely does NOT hold
|
||
|
||
**What I checked, and why this is a real gap not a nitpick:** D-192 (already
|
||
filed, confirmed by direct read) explicitly drops the protocol version
|
||
handshake on the rationale that *"our actual deployment is a subprocess: the
|
||
Godot client launches the Rust server it was built with. They are always in
|
||
sync at runtime."* That's true for the LIVE wire protocol, and it means my
|
||
mandate's item 6 ("version skew between client and server during the
|
||
transition") is mostly a non-issue for the tagged-envelope migration itself
|
||
— there is no live-network deployment where an old client talks to a new
|
||
server.
|
||
|
||
**But Stig's round-1 disk-cache design (§4, ratified by silence at
|
||
lead-interview-1 as part of "cache composition... compose, don't compete")
|
||
breaks exactly this guarantee, and nobody has named it.** A disk-backed,
|
||
self-cleaning, `user://atlas_cache/`-resident cache **persists across game
|
||
updates** by construction — that's the entire point of a persistent cache
|
||
(survive process restart, survive session boundaries). D-192's "always in
|
||
sync at runtime" argument is about the LIVE client-server pair in one running
|
||
process; it says nothing about a cache file written by version N of the game
|
||
being read back by version N+1 after a patch changes the wire schema (a new
|
||
dense field, a changed enum discriminant range, a bumped `SCHEMA_VERSION`-
|
||
style change to the payload shape itself). I checked Stig's cache design text
|
||
directly (`stig-round1.md` §4) for any versioning discipline on cached
|
||
entries — **there is none**: the index schema he specifies is `{written_at,
|
||
last_read_at, kind: geometry|sim_state, size_bytes}`, with no field naming
|
||
which wire-schema version produced the cached bytes.
|
||
|
||
**The concrete failure mode:** a game update changes `DistrictWindowLayer`'s
|
||
field set (adds the `cliffs` sparse list this very workshop is about to
|
||
introduce, or bumps an enum's discriminant range per T-1150's own precedent
|
||
of "unknown values fall back, never trusted from the wire"). A player who has
|
||
a warm disk cache from before the update opens the Atlas. If the client
|
||
blindly deserializes the stale-schema cached bytes as if they were the new
|
||
schema (the most likely naive implementation, since the cache's whole selling
|
||
point is "skip the fetch, decode from disk"), this is either a hard decode
|
||
error (best case — the mismatch is caught) or, worse, a **silent
|
||
misinterpretation** of old bytes as new fields (worst case — exactly the
|
||
class of bug D-225's own 2026-06-12 amendment was written to prevent for the
|
||
LIVE wire, extended here to the DISK format, which nobody has extended the
|
||
same discipline to).
|
||
|
||
**Severity:** SERIOUS, not BLOCKING — this is a real, fixable gap, not an
|
||
architecture-breaking one, and the fix is cheap (one extra field). But it's
|
||
exactly the kind of "invisible until it's wrong" decision Araminta's own
|
||
round-1 opening line warned about, applied to a part of the design that
|
||
genuinely does cross a version boundary D-192 was written to assume away
|
||
everywhere else.
|
||
|
||
**What resolves it:** add a schema/version tag to every cached entry (a
|
||
`generator_sha`-style stamp, cheap to compute, or simply the game's own
|
||
`project.yaml` version string) at write time, and a check at read time —
|
||
mismatch = treat as cache miss, re-fetch, don't attempt to decode. This is a
|
||
small addition to Stig's already-designed index shape, not a redesign, and it
|
||
should land in the same round-2/3 pass that finalizes the cache store rather
|
||
than as a later patch once someone hits a stale-cache decode bug in the wild.
|
||
|
||
---
|
||
|
||
## NOTE
|
||
|
||
### N1. Dudley's "~174 MB" global-tier figure is decimal-MB (SI, 1000×1000), not MiB (1024×1024) — internally consistent but worth flagging before it gets budgeted against actual RAM/disk allocation numbers
|
||
|
||
Checked the arithmetic directly: Dudley's own measured per-body numbers
|
||
(1,990,693 bytes raw / 638,382 bytes PNG-encoded at 330K cells, T-1179) times
|
||
273 bodies:
|
||
|
||
- Using MiB (1024²): 273 × 638,382 / 1024² ≈ **166.2 MiB**
|
||
- Using decimal MB (1000²): 273 × 638,382 / 1000² ≈ **174.3 MB** ← matches
|
||
Dudley's stated "~174 MB" exactly
|
||
|
||
Not an error — the arithmetic is internally consistent under the decimal-MB
|
||
convention, and it happens to also match red flag 2's own pre-measurement
|
||
"~440 MB at 5×5" estimate reasonably (both used the same convention, so they
|
||
compare correctly to each other). Flagging only because the moment this
|
||
number gets used to size an actual memory allocation or `du`-reported disk
|
||
budget, the ~8MB gap (166 vs 174) between conventions is exactly the kind of
|
||
silent unit-drift that causes a "why doesn't the number match what `du -h`
|
||
shows" ticket three months from now. Recommend the filed D-record state the
|
||
convention explicitly (SI decimal MB) the first time this number appears.
|
||
|
||
**No action needed beyond a one-line convention note in the filed record** —
|
||
this is the "clean bill" item my mandate asked me to report explicitly when a
|
||
claimed number checks out. The ~174 MB figure IS what Dudley's own measured
|
||
inputs produce, under a stated convention.
|
||
|
||
### N2. Region-as-step-0 is still unconfirmed by Araminta (round-1-notes item 9) — I have no `araminta-round2.md` to check against, flagging that this is still open at time of writing
|
||
|
||
Per the mandate's instruction to note what I didn't see: no `{agent}-round2.md`
|
||
files existed in the workshop directory at the time I read it. Tyre's §1e
|
||
flagged "Region likely IS the global/step-0 rung, worth confirming" as
|
||
carried into round 2. If this is still unconfirmed when synthesis closes, it
|
||
directly affects two of my own findings above — S3's viewport-tile-count
|
||
arithmetic assumed the deep end of the ladder starts from a District-scale
|
||
"global" tier's working-grid extent as the body-coverage proxy, which is a
|
||
reasonable stand-in either way, but the exact numbers would shift slightly if
|
||
Region turns out not to be step-0. Not a finding against anyone's work, just
|
||
noting the input I was missing.
|
||
|
||
### N3. Cleared: the courses-cost bound itself (<5% at District-cap, the one number actually stress-tested at real density) holds up
|
||
|
||
Distinct from S2 above (which is about the SCOPE of what's been measured, not
|
||
its accuracy) — I directly re-checked the one courses-inclusive-at-real-
|
||
density number that exists (Cross-check 1, T-1178): 195.0 ns/cell vs the
|
||
synthetic fixture's 192.0 ns/cell is a 1.56% delta, correctly described as
|
||
"within 2%." The arithmetic is right, and the <5% District-cap bound
|
||
(`+0.09–0.21ms` against `~5ms`) is 1.8–4.2%, also correctly inside the stated
|
||
threshold. No finding here — citing this as the "clean bill" companion to S2,
|
||
since S2 is about what ISN'T covered, not about the one number that is.
|
||
|
||
---
|
||
|
||
## Summary table
|
||
|
||
| # | Severity | Finding | Resolution cost |
|
||
|---|---|---|---|
|
||
| B1 | BLOCKING | "273 bodies" hydrology bench is 1 body × 273 — no real population-scale cliff-rarity survey exists | Minutes — harness 90% exists, 267 real heightmaps on disk |
|
||
| B2 | BLOCKING | Seed-chaining data-flow (independent re-derive vs consume-coarser-output) is unresolved and changes every cost number's validity | Architecture ruling, then possibly a re-bench pass |
|
||
| S1 | SERIOUS | Storage-eviction × TTL-distance-decay interaction unspecified; evict-then-revisit costs ~80ms/canvas × N canvases, uncosted at realistic N | Specify eviction granularity + axis precedence |
|
||
| S2 | SERIOUS | Courses-inclusive rate measured once, light-ish density, one body — zero coverage at deep-step + high-density-river combination | One more bench, harness exists |
|
||
| S3 | SERIOUS | D-226(d) holds by letter at every step but not by purpose against unbounded client-cache accumulation (~985GB to fully tile one body — improbable but not structurally prevented) | Add explicit per-body deep-rung cache cap; state prohibition as per-request not aggregate |
|
||
| S4 | SERIOUS | Sim-state determinism substrate is sound (CLEARED) but phase-cadence for TTL sizing is an unfilled variable | Name phase cadence(s) per body class |
|
||
| S5 | SERIOUS | Disk cache has no schema/version tag — the one place D-192's "always in sync" guarantee doesn't hold (cache persists across updates) | One field addition to Stig's index schema |
|
||
| N1 | NOTE | ~174MB figure is decimal-MB not MiB — internally consistent, state convention explicitly | One-line note in filed record |
|
||
| N2 | NOTE | Region-as-step-0 still unconfirmed at time of writing (no round-2 files existed yet) | Informational |
|
||
| N3 | NOTE | Courses <5% bound itself is accurate where measured (cleared) | None — clean bill |
|
||
|
||
Top-line read for the lead interview: nothing here says "computer catches
|
||
fire" or "the architecture is wrong." Everything here says "two claims are
|
||
resting on measurements that don't cover what they're cited for" (B1, B2) and
|
||
"three real interaction effects between mechanisms that were each individually
|
||
well-designed haven't been costed together" (S1, S3, S5). All five of the
|
||
serious-or-worse findings have cheap, concrete resolutions — none require
|
||
walking back a round-1 position, and B1 in particular is likely to make the
|
||
cliff ruling's evidence base stronger, not force a reversal, once run.
|
||
|
||
---
|
||
|
||
# ADDENDUM (post-round-2-files)
|
||
|
||
All four round-2 files (`dudley-round2.md`, `araminta-round2.md`,
|
||
`stig-round2.md`, `tyre-round2.md`) now exist and have been read in full.
|
||
Short pass per the coordinator's four items. Verifying my own findings
|
||
against them, not re-litigating what's already settled.
|
||
|
||
## 1. Finding B2 (seed-chaining fork) — RESOLVED. Dudley's ruling closes it cleanly, and I verified the mechanism against source, not just his prose.
|
||
|
||
**Dudley's round-2 §(b) ruling: independent re-derivation from `(seed,
|
||
position)`; a finer step may call a coarser rung's derivation FUNCTION, never
|
||
read a cached RESPONSE.** I checked this against the actual code rather than
|
||
taking the argument on faith, because "this closes the cost-shape concern" is
|
||
exactly the kind of claim that needs verifying, not just reading.
|
||
|
||
Read `server/src/atlas/district_profile.rs:1705-1732` directly —
|
||
`derive_at_metres` (the function every T-1178/T-1154 bench calls) computes
|
||
`region_baseline_c` via `region_profile::region_baseline_at_district(...)`
|
||
**inline, every call, with the comment stating explicitly: "No pre-built
|
||
cache here — the on-demand path derives the four surrounding region
|
||
baselines directly. Pure, deterministic, cheap."** This is not a
|
||
generalization from a different code path — it is the *exact* function every
|
||
measured ns/cell number in the appendix already exercises. So Dudley's claim
|
||
that "my own cost numbers... are validated as the correct model" isn't an
|
||
assertion resting on the ruling being correct in principle — the nested-call
|
||
cost is *already baked into every measured number*, because the benchmarked
|
||
function already does this. **This fully closes my concern: the ①②③ cost
|
||
basis is validated, not just argued to be validated.**
|
||
|
||
**What remains for Jeroen, stated precisely, per the coordinator's ask:**
|
||
Jeroen's own outline sentence — *"This at the same time serves as seed
|
||
information for the deeper cascade"* — is genuinely ambiguous between two
|
||
readings, and interview 2 is where that ambiguity needs to close, not before.
|
||
Dudley's ruling asserts his function-composition reading is what Jeroen
|
||
*meant*, grounded in the fact that this pattern already ships
|
||
(region-baseline-feeds-district). That's a strong circumstantial argument
|
||
(it's the only reading consistent with existing shipped code and with D-227),
|
||
but it is still an inference about authorial intent, not a confirmation from
|
||
Jeroen himself. **The interview-2 item, precisely stated: ask Jeroen to
|
||
confirm "seed information for the deeper cascade" meant "the finer
|
||
derivation calls the coarser rung's derivation function as a sub-computation,
|
||
the way region-baseline-feeds-district already works today" — not "the finer
|
||
step consumes the coarser step's already-computed response bytes as a
|
||
literal input."** If he confirms, B2 is fully closed with authorial
|
||
agreement, not just Dudley's reading of the code precedent. If he meant the
|
||
second reading, the cost model needs the re-bench I originally flagged — but
|
||
given the mechanism is architecturally forced by D-227 (a response-consuming
|
||
model would require solving the cache-dependency-chain problem Dudley's
|
||
argument-point 1 lays out, which nothing in the outline text asks for), I
|
||
think this is very likely to confirm cleanly. Downgrading this from BLOCKING
|
||
to a one-line interview-2 confirmation item, not a re-open.
|
||
|
||
## 2. The envelope design — attacked directly, one real angle found, one attack that didn't pan out (reporting both, per my mandate).
|
||
|
||
**Attack 1 (didn't pan out — reporting the clean bill): does `StepCanvasRequest`
|
||
risk a structural collision with legacy `AtlasLayerRequest` in the `ShapeProbe`
|
||
demux, given `AtlasLayerRequest` has no boolean discriminator (unlike
|
||
`star_map`/`city_names`/`browse`)?** Checked directly against
|
||
`server/src/bridge/mod.rs:96-152`. `AtlasLayerRequest`'s shape-identity in
|
||
`ShapeProbe` is `body_id.is_some() && up_to.is_some()` (`up_to` is a
|
||
*required*, non-`#[serde(default)]` field on the struct itself, confirmed by
|
||
reading `layer_proxy.rs:510-512`). Dudley's `StepCanvasRequest` struct
|
||
carries `body_id` but never `up_to` — so no minimal well-formed
|
||
`StepCanvasRequest` payload can satisfy `AtlasLayerRequest`'s two-field
|
||
identity check, regardless of try-order placement. Dudley's text also
|
||
explicitly extends `ShapeProbe` with a `step_canvas` field and folds it into
|
||
the mutual-exclusivity sum — so a payload carrying both `step_canvas` and
|
||
`up_to`+`body_id` would be correctly rejected as ambiguous by the existing H1
|
||
defensive check, not silently misrouted. **Cleared: the demux design holds
|
||
under a targeted collision attack, including the one case (legacy shape has
|
||
no discriminator) that looked like the most likely soft spot.**
|
||
|
||
**Attack 2 (the "no coexistence needed" claim, stress-tested against
|
||
version-skew, not just live-wire skew — this is where a real gap was, and
|
||
it's already been found and closed by the workshop before I could report
|
||
it):** I went looking for exactly the gap I flagged in my original S5
|
||
(disk cache persists across a version boundary D-192's "always in sync"
|
||
argument doesn't cover) and found `tyre-round2.md` §(a.9) already cites it
|
||
verbatim as "Troblum S5" with a complete, record-ready fix (schema/version
|
||
tag on every cache entry, tag-mismatch = cache miss, never a decode attempt).
|
||
Verified the fix is structurally sound: it correctly scopes the claim (D-192's
|
||
live-wire reasoning stands unchanged; only the persistent-cache boundary needs
|
||
the new tag) and correctly treats a version mismatch as "just another
|
||
eviction case" consistent with D-227's existing discipline, not a new failure
|
||
mode. **No further attack needed here — this is closed, and closed well.**
|
||
|
||
**Attack 3 (genuinely new, not previously flagged by me or found addressed in
|
||
round 2): the migration's own sequencing claim — "the server-side sixth-shape
|
||
addition and the client-side viewer rewrite don't have to land in the same
|
||
PR" — is correct for the LIVE wire (D-192 co-ship holds at every commit
|
||
because client+server build together), but says nothing about the
|
||
**disk cache accumulated during the OLD viewer's lifetime being read by the
|
||
NEW viewer** once the cutover lands.** Concretely: a player has an existing
|
||
`user://atlas_cache/` populated entirely by the retiring `AtlasWindowViewer`
|
||
(old `district_window`-keyed entries, old key shape
|
||
`make_key()` without a step index per Stig's round-1 text). The new stepped
|
||
viewer ships, checks the cache directory, and — assuming Stig's `FileAccess`
|
||
index is keyed by the *new* composite key shape
|
||
(`body_id:step:center:n:granularity_v2`, per his round-2 `IndexEntry.key`
|
||
spec) — simply won't find any hits against old-format keys. This isn't a
|
||
decode-corruption risk the way S5 was (different key shapes don't collide,
|
||
they just miss), so it's lower severity than S5 was — but it does mean the
|
||
cutover moment is a **guaranteed 100% cache-cold start** for every player
|
||
with pre-existing Atlas usage, not a graceful degrade. Nobody has stated
|
||
whether the old `user://atlas_cache/` directory (if the legacy viewer even
|
||
had a disk cache — checking Stig's round-1 text, the *old* `AtlasViewer`
|
||
only had the in-memory `atlas_window_tile_set.gd` Dictionary LRU, no disk
|
||
tier at all, since the disk-backed store is this workshop's own new
|
||
proposal) gets cleared, ignored, or orphaned on cutover. **This is a NOTE,
|
||
not a SERIOUS finding, once traced fully** — because the legacy viewer never
|
||
had a disk cache to begin with (confirmed: Stig's round-1 §1 describes only
|
||
`atlas_window_tile_set.gd`'s in-memory Dictionary as the pre-existing cache),
|
||
so there's no stale-format directory to orphan; the new disk cache starts
|
||
genuinely empty on first use regardless of cutover timing. Downgrading this
|
||
from a finding to a **clean bill**: the "no coexistence needed" framing
|
||
holds for the disk cache specifically because there was no prior disk cache
|
||
to migrate away from. Flagging only so the implementation ticket doesn't
|
||
need to write dead migration code for a cache tier that never existed.
|
||
|
||
## 3. Ladder tables — Option B's zero-asterisk claim: mostly holds, one small asterisk found inside it; D-226(d) letter-compliance and the Region→District seam argument both check out.
|
||
|
||
**The zero-asterisk claim, checked row by row against what was ACTUALLY
|
||
measured this session vs. inherited from an earlier baseline document.**
|
||
Option B's five rows: Region (MEASURED, T-1178's 8.3M-cell District-spacing
|
||
row reused — see caveat below), District (MEASURED, T-1178), Quarter
|
||
(same-band), Block (MEASURED, T-1154's 128m sweep), voxel (MEASURED, T-1154's
|
||
83K-cell deep-step bench). Four of five are genuinely, directly measured
|
||
THIS session. **The Quarter row is the one soft spot**: T-1154's own text
|
||
frames Quarter's per-cell rate as "the existing... Quarter (1.823 µs/cell)
|
||
row[s] already in `atlas-zoom-ladder-t1143.md` §7" — i.e., Quarter's per-cell
|
||
rate is inherited from an **earlier session's baseline document**, not
|
||
re-measured fresh this workshop. T-1154 confirms Block/Tile land in the
|
||
*same band* as that inherited District/Quarter baseline, which is a real and
|
||
valid cross-validation — but it means Quarter was never put through this
|
||
session's own 8.3M-cell parallel sweep the way District and Block were
|
||
(checked directly: T-1178's 8.3M square-canvas row is explicitly District
|
||
spacing only, `t1178-t1154-derive-bench.md:148`). **This is a small
|
||
asterisk, not a real problem** — the same-band confirmation mechanism (flat
|
||
~190-220 ns/cell parallel rate holding across every rung this session DID
|
||
test at every size) makes it very likely Quarter holds too, and Dudley's own
|
||
table already marks it "~1,827 ms (T-1154 same-band confirmation)" rather
|
||
than a flat unqualified number, so the workshop's own documentation is
|
||
honest about this — I just want it named explicitly as "one row is
|
||
same-band-inferred, not this-session re-run at 8.3M," since "zero asterisks"
|
||
as a literal claim slightly overstates it. Doesn't change the recommendation
|
||
(Option B is still clearly the best-evidenced skeleton) — this is a
|
||
precision note, not a reversal.
|
||
|
||
**D-226(d) letter-compliance at each skeleton's deepest step:** checked all
|
||
three options (A/B/C) — every one bottoms out at voxel (1 m), display-ratio-
|
||
sized (216×384 m, 82,944 cells), never the fixed 3840×2160/8.3M-cell
|
||
canonical shape. This holds the D-226(d) letter identically across all three
|
||
skeletons — the deepest-step canvas policy doesn't vary by which skeleton
|
||
wins, only the *path* to reach it (how many intermediate steps) varies. No
|
||
skeleton-specific compliance risk found; this was already the corrected
|
||
convention Dudley applied uniformly per his own note in §(c) ("noted
|
||
consistently in all three tables below, not just this one").
|
||
|
||
**The Region→District seam argument:** Dudley's claim that the ÷100 jump at
|
||
step 0→1 "matters for serving... lines up with a real architectural
|
||
boundary" (the global/sub-global cache tier split) — checked this against
|
||
the actual cache-tier spec (both his §(d) and Stig's round-2 §(c)): yes, Tier
|
||
1 (global, keep-always) is Region-spaced exactly, and Tier 2 (storage-
|
||
evictable) starts at District. The architectural seam and the display-factor
|
||
seam are the same boundary by construction, not a coincidence — this holds
|
||
up. **Cleared.**
|
||
|
||
## 4. TTL-split planes (araminta-round2.md §a) and three-tier cache spec (stig-round2.md §c) against my S1/S5 — both specs now address the concerns; S1 substantially resolved, S5 fully resolved (see item 2 above, already covered by tyre-round2.md §a.9).
|
||
|
||
**S1 (evict-then-revisit cost spike, TTL-distance-decay vs storage-eviction
|
||
precedence unspecified):** Dudley's round-2 §(d) resolves the precedence
|
||
question by **eliminating the ambiguity structurally**, not by picking a
|
||
winner — his revised formula drops `distance_decay` entirely
|
||
(`evict_if: time_since_last_visit(entry) > STORAGE_TTL[rung]`), reasoning
|
||
that distance-from-focus is redundant with time-since-visit for a
|
||
storage-thrift purpose. This closes the "which axis wins" half of S1
|
||
cleanly — there's only one axis left for storage-eviction, so there's
|
||
nothing to arbitrate between. **Stig's round-2 §(c) independently confirms
|
||
the same simplification** (his Tier 2 spec: "(2a) time-since-last-visit
|
||
sweep" + "(2b) LRU-capacity sweep," two independent triggers, no distance
|
||
term at all) — two independently-designed specs converging on dropping
|
||
`distance_decay` is good evidence the simplification is correct, not just
|
||
convenient.
|
||
|
||
**What S1 asked for that's still not fully delivered: the actual revisit-cost
|
||
number.** I computed ~80ms/canvas (74.8ms derive + 5.41ms PNG-encode,
|
||
T-1179) × N canvases for a realistic revisit scenario — neither round-2 cache
|
||
spec states an expected N (how many canvases a typical explored-then-
|
||
abandoned body accumulates) or runs that arithmetic explicitly. Stig's spec
|
||
does now name eviction granularity precisely (per-entry, the composite key),
|
||
which was the other open half of S1 — so the mechanism is fully specified,
|
||
just not the end-to-end cost consequence of a real revisit. **Downgrading
|
||
S1 from SERIOUS to NOTE**: the mechanism gaps (granularity, axis precedence)
|
||
that made this SERIOUS are now closed; what's left is a tuning-pass number
|
||
(expected revisit cost under realistic N), which both specs correctly treat
|
||
as implementation-time tuning rather than an architecture question — Stig's
|
||
own text explicitly defers the STORAGE_TTL/budget constants as "a tuning
|
||
pass once real play-pattern data exists, not an architecture call I'm
|
||
locking here." That's the right call; I'd only ask that the ticket plan
|
||
name "measure actual revisit-pattern cost against a real play session" as a
|
||
post-ship validation step, not a pre-filing blocker.
|
||
|
||
**S5 (disk cache schema/version tag):** already covered in item 2 above —
|
||
`tyre-round2.md` §(a.9) resolves this completely and correctly, citing my
|
||
finding by name. Checked Stig's round-2 `IndexEntry` schema
|
||
(`stig-round2.md:206-223`) to confirm it does NOT yet carry the tag itself
|
||
(it doesn't — the schema shown is pre-amendment) — but Tyre's text is
|
||
explicit that "it lands in Stig's `FileAccess` spec at implementation," i.e.
|
||
this is correctly sequenced as a record-level requirement now, schema
|
||
addition at implementation, not a gap in Stig's document. **Fully resolved.**
|
||
|
||
## Summary of the addendum
|
||
|
||
| Original finding | Status after round 2 |
|
||
|---|---|
|
||
| B1 (population-scale cliff survey never run) | **STILL OPEN** — tyre-round2.md §(a.7) correctly gates the sparse-list cost claim on it running, but it has not been run yet (checked: no new measurement doc, Dudley's round-2 text doesn't mention it). Still the one thing I'd block filing on. |
|
||
| B2 (seed-chaining fork) | **RESOLVED**, verified against source (`district_profile.rs:1705-1732` — the nested-call pattern is already what every measured ns/cell number exercises). One precise interview-2 confirmation item remains (does Jeroen's phrasing match this reading), stated above — downgraded to NOTE-level follow-up, not a blocker. |
|
||
| S1 (evict-then-revisit spike, axis precedence) | **Mechanism fully resolved** (both specs converge on dropping distance_decay, granularity now per-entry). Downgraded to NOTE: the actual end-to-end revisit-cost number is still unstated, correctly deferred as a tuning-pass/post-ship-validation item by both specs. |
|
||
| S2 (courses density coverage gap) | **STILL OPEN** — not addressed in any round-2 document. Deep-step + high-river-density combination remains unmeasured. |
|
||
| S3 (D-226(d) letter vs purpose, cache accumulation) | **RESOLVED** — tyre-round2.md §(a.8), same framing, same risk actor (`AtlasAgentInterface`), concrete structural fix (per-body deep-rung cache cap). |
|
||
| S4 (sim-state phase cadence unspecified) | **Not directly addressed by name in round 2** — araminta-round2.md §(a) does much of the adjacent work (TTL-split field assignment, static-vs-sim-state reasoning per field) but does not name a phase-cadence number or range. Still open, lower priority than B1/S2. |
|
||
| S5 (disk cache version tag) | **RESOLVED** — tyre-round2.md §(a.9), complete and correct fix. |
|
||
| N1 (decimal-MB units) | Unchanged, still just a note-in-record-text item. |
|
||
| New (envelope demux collision attack) | **CLEARED** — attacked directly, design holds. |
|
||
| New (cache-format cutover / stale-key orphaning) | **CLEARED on inspection** — no prior disk cache existed to orphan; downgraded from a worry to a documented non-issue. |
|
||
| New (Option B's "zero asterisks" has one small inherited-baseline asterisk on the Quarter row) | **NEW NOTE** — Quarter's rate is same-band-confirmed, not this-session-remeasured at 8.3M; doesn't change the recommendation. |
|
||
|
||
**Net: of the 7 original findings, 4 are now resolved (B2, S3, S5, and S1's
|
||
mechanism half), 2 remain genuinely open (B1, S2) and are the two I'd still
|
||
flag as blocking/serious for interview 2, and 1 (S4) is partially addressed
|
||
but not closed.** The round-2 team's own adversarial handling of my findings
|
||
was accurate and thorough — every fix I checked against source or
|
||
cross-spec actually holds, not just reads well.
|
||
|
||
---
|
||
|
||
# FINAL UPDATE (post-B1-survey)
|
||
|
||
Verified `bench_population_survey_all_committed_bodies`
|
||
(`server/tests/hydrology_equilibrium_bench.rs:273-`) directly against source,
|
||
the same way I verified everything else in this pass — not taking the
|
||
coordinator's summary or the measurement doc's prose at face value.
|
||
|
||
**Confirmed genuine, not a repeat of the original defect:** the new bench's
|
||
`par_iter` closure calls `load_heightmap_png(path, &body_id, 0.3)` **inside**
|
||
the closure, once per discovered path — a distinct file read, distinct
|
||
`body_id` (derived from the parent directory name), and distinct
|
||
`small.sea_level` (read from each PNG's own embedded `sea_level` metadata,
|
||
not a shared constant) per iteration. This is structurally the opposite of
|
||
`bench_parallel_273_bodies_at_512x256`'s defect, where `gj1c_512x256()` was
|
||
called once *outside* the `par_iter` block and every iteration reused the
|
||
same `elev`/`sea_level` binding. The new bench also carries a `heightmap_paths.len()
|
||
> 200` assertion (guards against a silently-empty discovery walk) and a
|
||
built-in determinism spot-check (`assert_eq!` on `cliff_edge`/
|
||
`channel_depth_scaled` for the top-by-carving outlier, re-solved a second
|
||
time) that would fire the moment any future body actually carves. Basin
|
||
arithmetic checks out (22,270 total = 21,240 overflow + 1,030 endorheic,
|
||
confirmed by direct addition). The measurement doc's `cliff_edge`/
|
||
`carved_cells` filter logic in the bench (`BasinOutcome::Overflow` with
|
||
`channel_depth_scaled[b.spill_cell] > 0`, `cliff_edge.iter().filter(|&&c| c)`)
|
||
matches what the original T-1177 module actually computes — not a redefined
|
||
or looser carving criterion invented to force a zero result.
|
||
|
||
**One precision note, not a discrepancy:** the coordinator's/Tyre's cited
|
||
"31–187 basins/body" range is the min/max **within the printed top-15 table**
|
||
(GJ1075c=31, GJ1e-m1=187), not a separately-stated population-wide min/max —
|
||
the measurement doc's own prose illustrates variety with a different example
|
||
pair (GJ103c=40 to GJ1e-m1=187) rather than stating the true extremes. Both
|
||
are consistent with the same data; this is not an error, just noting the
|
||
"31" figure comes from reading the table rather than an explicit population
|
||
min/max statement in the doc. Doesn't affect the finding.
|
||
|
||
**B1 → RESOLVED.** The population-scale claim now rests on real, distinct
|
||
evidence (267 real bodies, each independently solved, real terrain, real sea
|
||
levels) rather than one body's cost profile standing in for the population.
|
||
The zero-carving result is stronger than what was being claimed before my
|
||
original finding (100% zero vs. "structurally rare, one-body-verified"), and
|
||
the epistemic framing in `tyre-round2.md` §(a.7) is honest about the
|
||
remaining limit ("not observed yet ≠ cannot occur," carving arithmetic
|
||
stays unit-proven for future bodies) rather than overclaiming "impossible."
|
||
This is exactly the outcome I'd hoped running the survey would produce, and
|
||
it did.
|
||
|
||
## Scorecard, final, for interview 2
|
||
|
||
Of the seven original findings plus the addendum's follow-ups, **two remain
|
||
open** and are the only items I'd carry into interview 2:
|
||
|
||
1. **S2 — courses-inclusive derive cost has zero measured coverage at the
|
||
deep-step (Block/Tile spacing) × high-river-density combination.** The
|
||
one courses-inclusive-at-real-density number that exists (T-1178
|
||
Cross-check 1: 195.0 ns/cell, 18 courses, District spacing, one body) is
|
||
accurate where measured (confirmed clean in my original pass), but the
|
||
deepest step's own realistic-canvas bench (T-1154's 83K-cell/17ms number)
|
||
explicitly excludes courses entirely by construction (H2's
|
||
`rect_window_replica` is courses-empty), and no round-2 document adds a
|
||
deep-step/river-dense bench. Not blocking (the existing <5% District-cap
|
||
bound has enough headroom that a multiple-density increase likely stays
|
||
affordable), but it is the one combination in the whole measured appendix
|
||
with literally zero data point, at exactly the spot (deepest step, most
|
||
individually-resolvable tributary geometry) where the excluded cost is
|
||
least likely to stay proportionally small. **Ask: run one more bench —
|
||
deep-step canvas on a body selected/authored for high course density —
|
||
before or shortly after filing; not a blocker for filing itself.**
|
||
|
||
2. **S4 residual — sim-state TTL phase-cadence is still an unnamed
|
||
variable.** Araminta's round-2 §(a) fully resolved the *field-assignment*
|
||
half of my original finding (which fields are sim-state vs static, and
|
||
why, stated per-field rather than inferred from name — `glaciation`/
|
||
`flooded` sim-state, `temp_dc` static, with a genuinely sharp
|
||
non-arbitrary argument for each). What remains unresolved is the
|
||
**numeric half**: D-228's "computed once per phase" water-height/
|
||
glaciation clock model doesn't state a phase duration, and nothing in
|
||
round 2 names one (or a per-body-class range) for sizing the sim-state
|
||
plane's actual TTL. The determinism substrate is sound (confirmed clean
|
||
in my original pass) — this is purely a missing tuning input, the same
|
||
category Stig/Dudley both correctly deferred their own STORAGE_TTL/
|
||
budget constants as "a tuning pass once real data exists." **Ask: either
|
||
fold this into the same tuning-pass deferral (acceptable, and consistent
|
||
with how the other unresolved constants in this workshop were handled),
|
||
or if Jeroen wants a concrete number before filing, that's a Dudley/
|
||
Araminta follow-up question at interview 2, not something the measured
|
||
appendix can answer as-is.**
|
||
|
||
Everything else — B1 (population survey, now run and resolved), B2
|
||
(seed-chaining, resolved and verified against source), S1 (eviction
|
||
mechanism, resolved; end-to-end cost number correctly deferred as tuning),
|
||
S3 (D-226(d) accumulation gap, resolved with a structural fix), S5 (cache
|
||
version tag, resolved with a complete fix), N1 (units note), N2 (informational,
|
||
now moot — all round-2 files exist), N3 (clean bill, unchanged) — is closed
|
||
or was never a live concern. The workshop's round-2 handling of every
|
||
finding I could verify against primary sources held up exactly as
|
||
documented, with no gap between what was claimed fixed and what the code/
|
||
doc actually shows.
|