Files
settled-reach/docs/architecture/river-courses-t1170.md
T
jpmschweitzerandClaude Fable 5 18c731a5de docs(meta): D-255 body-map-viewer stepped render architecture + deprecation sweep
D-255 filed (server-determines-content / client map-art function / stepped
six-level ladder Global+Region→Chunk / tagged-envelope wire discharging D-225 /
three-tier cache with distinct staleness-storage axes / cache-accelerated-pure-
function seed-chaining / lakes from settled hydrology, endorheic cue =
outflow-course presence). Twelve in-place amendments: D-166 corollary repoint,
D-192 persistent-cache boundary, D-225 deferral discharged, D-226 consolidated
(ceiling re-scope, select_rung→step-index, stepped transport, item-(d)
per-request + retention cap + chunk-floor partial restore, courses gloss +
cliff sparse-list), D-227 four-part (TTL-split, version tag, seed-chaining,
lakes), D-243 gridunit vocabulary. Clerk-audit fixes: atlas-zoom-ladder-t1143
superseded banner, CLAUDE.md Phase-4 cascade row updated to the stepped model,
Q-093 prior-art cross-ref. river-courses-t1170 carrier gloss. governance
README index regenerated (109 decisions through D-255); validate clean, sync
1344 refs 0 broken. Ticket chain T-1181–T-1185 + reconciliations in changelog.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 10:58:02 +02:00

150 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "River Course Invention — T-1170/T-1168 Design Ruling"
description: Binding design ruling for course invention + riparian vegetation (Tyre, from the three-audit design pass)
type: design
status: binding
round: T-1170
created: 2026-07-23
---
> **Note (2026-07-24, body-map-viewer workshop — D-255):** the carrier three-way rule below (Ruling 1c / Ruling 6) survives unchanged in substance. Two terminology/scope updates from D-255: **(1)** "the windowed payload" is repointed to "the per-step data-canvas payload — formerly the `district_window` field, now the tagged step-canvas envelope" (D-226 2026-07-23 amendment / D-255 §c). **(2)** Rule (iii) — *rung-indexed invented detail rides the windowed payload regardless of geometric kind* — gains a second vector member alongside `courses`: **`cliffs: Vec<CliffSegment>`** (carved-gorge geometry: dominant `elevation` + per-segment `channel_depth` + `cliff_edge`), a sparse list zero-length when nothing is carved (T-1177 population survey: zero carved cells across all 267 real bodies), Phase-4 Atlas scope. Governance capture is in the D-226 and D-227 body-map-viewer amendments; this note only glosses the design doc so its "windowed payload" language stays current.
*cracks knuckles* — I've read both tickets in full, the D-226 amendment block (wave-1 carrier note, two-waterline note, T-1137 queue ruling, windowed-family ceiling), D-227, D-243, and the T-1143 zoom-ladder serving model. The audits are code-true and the tension called out in point 1 is real — I created it, and it resolves cleanly once the carrier rule is split on the right axis. Ruling follows.
---
# TYRE — Binding Design Ruling: T-1170 (river course invention) + T-1168 (riparian vegetation)
**Date:** 2026-07-23. **Status:** binding for this batch; implementers code from this directly. Governance capture text in Ruling 6.
**The keystone insight, stated once up front:** the framework tension between my wave-1 carrier note ("discrete geometry rides whole-body") and my two-waterline note ("invention detail is rung-indexed") dissolves when you split on the correct axis. The wave-1 rule was written for the **skeleton** — a fixed, finite, rung-independent graph, computed once, valid forever. Course geometry is not skeleton; it is **invention** — the linear sibling of the coast crinkle, refined per rung by construction. Skeleton rides whole-body; invention rides the window. The rule wasn't wrong, it was under-specified, and this ruling refines it rather than reversing it.
---
## Ruling 1 — Invention locus and wire carrier: server-side, per-window, inside `DistrictWindowLayer`
**1a. Locus: server, per-window, at serve time — Dudley's option (b). Binding.** Course geometry is invented inside the window derive (`GenWorkItem::DeriveWindow`, background queue per T-1137 — queue discipline [HARD], unchanged), at the window's granularity and `min_wavelength_m`. Dudley's numbers close this: +0.090.21 ms against a measured ~5 ms window baseline, under 5% — noise. Whole-body precompute at Quarter detail is **rejected** on payload grounds (~4.4 MB dense-body for geometry 99% never viewed — categorically the wrong shape under D-227 derive-don't-store). Client-side GDScript invention is **rejected** on the determinism surface, not CPU: a byte-exact two-language mirror of `splitmix64`/`value_noise`/octave tables is a standing D-010/D-227 liability the project has deliberately avoided everywhere else, purchased for a compute saving option (b) proves unnecessary.
**1b. Carrier: a new vector field inside the existing windowed payload. The windowed-family ceiling is untouched — and here is why, precisely.** The ceiling ([HARD], D-226 T-1124 §2) counts **windowed-query fields on `AtlasLayerResponse`**. It exists to prevent a second concurrently-in-flight windowed *query* needing per-field request correlation. Course geometry is not a second query: it is **content of the one windowed payload**, keyed by the same `(body, center, n, granularity)` echo, arriving in the same response, stale-discardable by the same rule. `DistrictWindowLayer` gains `courses: Vec<RiverCourse>` (`#[serde(default)]`), exactly as it holds six dense arrays today. No ceiling impact, no tagged-envelope migration, no new request class.
**1c. The carrier rule, refined (this is the governance-grade restatement — capture text in Ruling 6):**
> Three-way, replacing the wave-1 two-way rule: **(i)** rung-independent discrete features — skeletons, graphs, point markers, computed once and valid forever — ride the whole-body overlay family, filtered per-rung client-side. **(ii)** Continuous per-metre fields ride the windowed per-cell arrays. **(iii)** **Rung-indexed invented detail rides the windowed payload regardless of geometric kind** — raster or vector — because rung is a *request parameter*, and only the windowed query carries one. The coast crinkle has always followed (iii) implicitly (it arrives baked into windowed cell verdicts); course polylines are its vector sibling, arriving alongside them.
**1d. The two-waterline problem dissolves under this carrier.** A whole-body course would need a rung-parametrized terminus (the fork the audit flagged as sharpest). A windowed course does not: the server invents the course *at a known rung*, in the same pass that computes that rung's per-cell water verdicts — so the terminus is resolved against the drawn coast **at that rung**, server-side, consistently. Nothing whole-body ever carries a terminus. The skeleton stays rung-independent, as the two-waterline note requires.
**1e. Window-independence invariant (binding, tested).** The geometry is a pure function of `(seed, body, edge, rung)`**never** of the window rect. Stations are generated at deterministic global arc-length positions along the edge; the window *crops*, it never re-parametrizes. Two overlapping windows at the same granularity must produce byte-identical points for the shared stretch. This is the course analog of the coast warp's absolute-world-metre keying and it is a mandatory determinism test (see Discipline).
---
## Ruling 2 — Adjacency: persisted downstream pointer. Reconstruction rejected.
**2a.** `RiverNetwork` gains `river_downstream: Vec<u8>` — additive, `#[serde(default)]`, parallel to `river_cells` (the exact `river_class` precedent). Captured in `extract_river_network` (`drainage.rs:247-349`) where `fdir[i]` is already in scope and currently discarded after its boolean use. One `.map()`, zero new grid passes, ~1 byte/river cell. This is the **opening move** of the batch — everything else consumes it.
**2b. Reconstruction is rejected** on the Si audit's confluence finding: adjacency alone cannot distinguish inflow from outflow at a 3-river-neighbor confluence, and re-deriving direction from elevation is re-running D8 badly. We had the true answer in hand and threw it away; stop throwing it away. The D-203 memory-frugality rationale for discarding covered the 131 KB *full grid*, not the river-cell projection.
**2c. Sentinel vocabulary (values in the u8 space above 7):** `MOUTH` (flow reaches raw-sea) · `EDGE_DRAIN` (flow exits the grid's top/bottom edge — a grid artifact, *not* a mouth, per Ruling 3f) · `TERMINAL`**reserved now, unused in round 1** — flow ends in an interior sink (future endorheic basin / inland delta, see Ruling 7b). Reserving the value costs one enum arm and keeps the future option additive instead of a wire migration.
**2d.** Each edge is uniquely identified by its **upstream cell** (every river cell has exactly one downstream pointer), so `edge_id = pack(u16,u16) → u32`. This is the seeding key (Ruling 3a).
---
## Ruling 3 — Course algorithm
**3a. Seeding (D-227/D-010 discipline).** `SeedChain::for_body(...).derive(SeedDomain::RiverCourse, edge_id as u64)`, new `SeedDomain` variant, with a distinct `RIVER_COURSE_WARP_SALT` on the noise stream (the `COAST_WARP_SALT` pattern verbatim) — never correlated with coast warp, terrain scatter, or vegetation massif fields at the same position. Pure `(seed, body, edge, rung)`.
**3b. Two-stage shape — and the stage split is load-bearing for cross-rung stability:**
- **Stage A — coarse valley-seeking control path. Rung-INDEPENDENT.** Between the two anchor points (upstream/downstream cell centres — skeleton truth, never moved), place control stations at chord/8 (~9.6 km). At each, evaluate k=5 candidate perpendicular offsets within the amplitude envelope; score = bilinear `ta.elev_pct` at the candidate (plus a small continuity penalty against the previous chosen offset to prevent zigzag); pick minimum. **The elevation proxy is the bilinear `TerrainAnalysis` read — the same tradeoff the coast warp already made at `district_profile.rs:1152-1157` — NOT `derive_at_metres` per candidate.** Dudley's numbers make this affordable (+µs/segment); the Si audit's unmeasured-derive-cost gap is thereby not load-bearing for this design (we still close the measurement gap — see Discipline). Stage A is computed identically at every rung, so the coarse course never moves as you refine.
- **Stage B — fine warp octaves. Rung-INDEXED.** Perpendicular scalar displacement of intermediate stations via salted multi-octave value noise keyed on global arc-length, octave band from ~chord/2 (~38 km) down to the window's `min_wavelength_m` hard-truncate (the `warp_fbm` cutoff idiom, T-1162 rung discipline, reused exactly). Station spacing = the rung's sample spacing (2,048 m District / 512 m Quarter — Dudley's ~37/~150 points per segment), at global arc-length multiples so windows agree (Ruling 1e).
**Cross-rung invariant that falls out:** the Quarter course is the District course plus octaves in the (1,024 m..4,096 m) band — displacement between rungs is bounded by the truncated-octave amplitude sum, sub-cell at District spacing. And at Region spacing no octaves survive at all, so **the rung-truncated course degenerates to the straight chord — which means the client's Region-rung skeleton-chord drawing (Ruling 5a) IS the course at that rung**, not an approximation. That's the kind of unification I get excited about: one function, every rung, no special cases.
**3c. Amplitude envelope.** Sine-shaped taper to **zero at both endpoints** — this is what makes confluences work for free: every edge into and out of a cell meets exactly at the cell-centre anchor, C0-continuous, and the confluence marker draws at the anchor. Peak amplitude ≤ ~8% of chord (~6 km), scaled down by local `ta.slope_deg` (steep terrain → straighter) and up modestly by `river_class` (trunks meander wider). All tunables; taper-to-zero and the ≤ half-cell hard cap are binding.
**3d. Valley preference is IN for round 1** (costed at noise level by Dudley), via Stage A only. This is the round-1 answer to the wave-1 "rivers may cross invented hills" gap: courses *prefer* invented-terrain valleys at coarse wavelengths; residual fine-octave conflicts (a course crossing a `voxel_relief` hillock) are **accepted and documented**. The converse mechanism — terrain invention becoming course-aware (valley carving along courses) — is explicitly deferred; it belongs at the block/tile rungs and Phase 5 fill, noted in governance as the future direction, not built now.
**3e. Termination at the invented coast (the T-1172 retirement mechanism).** For an edge whose downstream sentinel is `MOUTH`: walk stations upstream→downstream, sampling the **same rung-consistent morphology water verdict the window's own cells use** (the `open_water`/morphology path, at the window's `min_wavelength_m` — not raw `ocean_frac`, so the terminus agrees with what is drawn). First water station → bisect against the previous land station (fixed 6 iterations) → terminus point, flagged `Mouth` on the wire. If the final anchor still samples land at this rung (drawn coast receded past the raw-sea cell — the inland-mouth oddity, fixed by construction here), extend along the D8 direction up to one cell length probing; if still no water, terminate at the anchor with **no** mouth flag (degenerate, rare, bounded). A few dozen probes per mouth edge, on the background queue — within the T-1137 discipline by construction.
**3f. Pole-edge drains are not mouths. Binding.** `EDGE_DRAIN` termini get no mouth flag and no double-ring; the course ends at the last in-grid station. Server-side, `extract_river_network` stops classifying grid-edge exits into `mouths` (deliberate Layer-1 golden re-pin, see Discipline). They are grid artifacts, exactly as Jeroen's capture question suspected.
**3g. T-1172 clip: restructured, not blanket-deleted.** The three marker sites in `atlas_window_nature_overlay.gd` (lines 288/311/347) retire **for the course-drawing rungs** (District/Quarter) — courses carry real rung-consistent termini, the clip's job is done there, and suppressed offshore mouths return as real geometry. The **Region-rung skeleton path keeps a clip**: Region still draws whole-body skeleton against a rung-dependent drawn coast, which is precisely the presentation-frame reconciliation the two-waterline note prescribes. Rewrite the marker comments: the surviving clip is documented as permanent-until-Region-goes-windowed (T-1143 ruling 2's progressive tiling), at which point Region inherits windowed courses and the last clip retires.
**3h. Wire shape.** `RiverCourse { edge_id: u32, class: u8, points: Vec<(i32,i32)> /* world-metres */, terminus: CourseTerminus /* None | Mouth | EdgeDrain | ContinuesBeyondWindow */ }`. Only edges whose chord-inflated-by-max-amplitude bounding box intersects the window ship; points cropped to window + one station beyond each edge of it. ~12 KB typical per window. Well inside every budget.
---
## Ruling 4 — T-1168: shape and sequencing
**4a. The mechanism: a scale-free point-sample distance test. This dissolves the blotch problem rather than mitigating it.** `near_perennial_water(sample_pos) = distance(sample_pos, nearest invented course polyline) ≤ band_m`, where `band_m` defaults to D-239 §8's governed 13 tiles (class-scaled: thicket band for trunks, scrub band for streams — tunable constants, governed default). Because the test is a pure point predicate against real course geometry, it is **automatically correct at every sampling density**: at 512 m Quarter spacing it essentially never fires (the band is sub-cell — honest, no over-fattening, the exact Lendel-failure discipline), and at 1 m tile spacing it fires on exactly the 13 tile bank strip. No per-rung riparian policy exists or is needed. The audit's skeleton-disc model — any "within N km of a 76 km-spaced skeleton point" test — is **rejected outright**: it is off by 34 orders of magnitude from the governed band and cannot be tuned into anything but green blotches.
**4b. Consequently the 512×256 distance-field-over-grid proposal is also rejected** — a grid quantized at 76 km cannot express a metres-scale band. The test runs against course polylines resident in the derive context: in the window path, T-1170's already-invented courses (coarse bounding-box cull, then point-to-segment distance — most cells cull to zero edges); in the batch path, courses for edges near the district, invented on demand via the same pure function (cachable per derive batch). The Si audit's observation that `gen_queue.rs:626` discards the `Layer1Output` **still gets fixed** — the window path needs `RiverNetwork` (cells + downstream pointers) resident to know which edges exist; retain it in `TerrainAnalysisCache` instead of re-deriving-and-discarding.
**4c. Hard sequencing: T-1168's riparian test lands AFTER T-1170's course inventor, full stop.** The test is meaningless without course geometry (4a). The **threading scaffolding is exempt** and proceeds in parallel — it is mechanical and fully mapped by the audit: `build_district_profile` gains the riparian signal parameter consumed at `district_profile.rs:1469`; threaded via `derive_all_districts``derive_district_profile` (batch, sourced from `cascade.rs`'s already-unpacked `river_network`, the `road_graph` precedent) and `build_district_window_layer``derive_window_cell``derive_at_metres`/`derive_orbital_at_metres` (window, sourced from the retained `Layer1Output`). Until the course inventor lands, the provider returns "no course in range" — wired but inert, zero behavioral change, zero golden churn.
**4d. T-1162 composition contract, re-affirmed as binding:** `near_perennial_water` is a separate boolean/geometry signal into `derive_vegetation`; it never touches `moisture_q`, and `moisture_perturb_q` never reads river data. The existing parameter separation already enforces this — the implementer's only job is not to break it. Climate gating stands: extreme-cold Barren beats riparian (ice is geology per D-227); `Marine`/airless precedence unchanged.
**4e. Experience honesty (what Jeroen will see):** after this batch, District/Quarter windows show continuous meandering rivers with real coast mouths. They will **not** show visible green riparian corridors — under the governed 13 tile band that is sub-cell at every Atlas rung, and honestly so. T-1168's visible payoff arrives at the block/tile rungs (opened by T-1143 ruling 1) and Phase 5 ground truth. If Atlas-visible green corridors are *wanted*, that is a design widening of D-239 §8 — flagged to Jeroen in Ruling 7a, one constant away, not an architecture change.
---
## Ruling 5 — Per-rung presentation surface
**5a. Region and coarser (skeleton path, whole-body `layer1`):** the client upgrades dots to **connected straight chords** via `river_downstream` — which per Ruling 3b *is* the rung-truncated course, so this is not an approximation, it is the course at Region truncation. Clip retained (Ruling 3g). Confluence/mouth markers from the skeleton lists (mouths now excluding pole drains).
**5b. District and Quarter (course path, windowed):** polylines from `DistrictWindowLayer.courses` via the existing `_pos()`/`draw_polyline` plumbing (`_draw_basins` precedent — no new transform code). Mouth markers at `Mouth` termini. No clip. **Quarter rivers return** — the streams class draws at Quarter, executing exactly the pre-announced fade-down revisit from the wave-1 visibility note.
**5c. The revisit point is preserved and split:** `RIVER_CLASS_VISIBLE_BY_RUNG` is replaced by two tables in `atlas_window_geometry.gd``SKELETON_CLASS_VISIBLE_BY_RUNG` (Region+, path 5a) and `COURSE_CLASS_VISIBLE_BY_RUNG` (District/Quarter, path 5b), with per-class width/opacity companion tables. **This is where Araminta's forthcoming presentation ruling plugs in** — implementers land functional defaults (trunk widest, streams thinnest, class-filtered per rung: District trunk+tributary, Quarter all three), and Araminta's ruling edits those tables and only those tables. Same single-revisit-point discipline as wave 1.
---
## Ruling 6 — Governance captures (exact text)
Append to the D-226 amendment block (`governance/decisions/architecture.md`), dated 2026-07-23:
> **Course-invention carrier note (T-1170, 2026-07-23 — Tyre):** river course geometry below D8 resolution is **invention, not skeleton**, and rides the **windowed payload** as a vector field inside `DistrictWindowLayer` (`courses`, additive) — invented server-side per window on the background queue (T-1137 discipline) at the window's rung, terminated server-side against the same rung's morphology water verdict the window's cells carry. This does **not** count against the windowed-family ceiling (§2 [HARD]): the ceiling counts windowed *query* fields on `AtlasLayerResponse`; courses are content of the single existing windowed payload, same echo key, same staleness semantics. The wave-1 carrier rule is hereby refined three-way: **(i)** rung-independent discrete features (skeletons, graphs, markers — computed once, valid forever) ride the whole-body family, filtered per-rung client-side; **(ii)** continuous per-metre fields ride the windowed per-cell arrays; **(iii)** rung-indexed invented detail rides the windowed payload regardless of geometric kind, because rung is a request parameter and only the windowed query carries one — the coast crinkle has always implicitly been (iii); courses are its vector sibling. The two-waterline note's reconciliation resolves per-rung server-side for courses (the terminus is windowed content at a known rung); the Region-rung skeleton path retains the presentation-frame clip until Region itself goes windowed (T-1143 ruling 2), which retires the last clip site. The skeleton itself gains `river_downstream` (additive per-river-cell D8 pointer with `MOUTH`/`EDGE_DRAIN`/reserved-`TERMINAL` sentinels) on `RiverNetwork` — whole-body, rung-independent, per rule (i). Pole-edge drains are grid artifacts, not mouths — excluded from `mouths` at extraction.
Append to D-227's amendment trail:
> **Amended 2026-07-23 (T-1170 — river courses join the invention family):** the "invented deterministically" clause now covers linear features: river courses between D8 cells are pure `(seed, body, edge, rung)` functions — a rung-independent valley-seeking coarse path (bilinear `TerrainAnalysis` proxy, never full re-derivation) plus rung-indexed perpendicular warp octaves under the `min_wavelength_m` truncation discipline, distinct salted stream, amplitude tapered to zero at cell-centre anchors (confluence continuity), stations at global arc-length positions (window-independent). Round-1 relief reconciliation is course-follows-terrain (valley preference); terrain-carves-for-course is the deferred converse, targeted at block/tile rungs.
Also: fix the stale `scale.rs:107` grid-shape comment (one line, audit nit) in whichever PR touches that file first.
---
## Ruling 7 — Jeroen items
**7a. Riparian visibility at Atlas rungs (genuine design call).** Under D-239 §8's governed 13 tile band, riparian vegetation is honestly invisible at every Atlas rung (Ruling 4e) — the drawn river itself is the only visible river response at District/Quarter. If you want the Nile effect — a visible green corridor at Atlas scale — that is a *design widening* of the band (e.g. floodplain-riparian corridors of hundreds of metres on alluvial-plain morphology, class- and morphology-scaled). The mechanism ships scale-free, so this is one governed constant/function away, zero architecture change. Your call, not blocking this batch.
**7b. Endorheic basins (one paragraph, as asked).** This design does not foreclose deliberate endorheic basins or inland deltas — it deliberately cheapens the future path. The `TERMINAL` downstream sentinel is reserved now (Ruling 2c), so an interior sink becomes an additive drainage-extraction change, not a wire migration; and the termination mechanism (walk stations to the first rung-consistent *water* verdict — which is the morphology verdict, covering lakes, not just ocean) generalizes unchanged to a terminal lake shoreline. When you want endorheic basins, the work is in D8 sink retention and lake morphology, and every piece this batch builds — pointers, courses, termination, riparian — consumes them without modification. Nothing to design today.
---
## Discipline — benches, goldens, determinism tests
1. **Run the dormant bench first.** `zoom_ladder_bench.rs` `--release --ignored`, before the course inventor merges; record the numbers in `docs/architecture/atlas-zoom-ladder-t1143.md` (which itself flags them UNMEASURED). Cheap, closes a documented gap this batch would otherwise inherit blind. Not load-bearing for the design (Ruling 3b avoided depending on it) but the gap closes now.
2. **Course-cost bench:** window derive with courses on/off; assert the delta stays under ~5% of the window baseline (Dudley's envelope).
3. **Determinism tests (mandatory, new):** (a) overlapping-windows agreement — two windows sharing an edge produce byte-identical course stations in the overlap (Ruling 1e); (b) cross-rung stability — Quarter course points within the truncated-octave amplitude bound of the District polyline (Ruling 3b); (c) salt isolation — course stream uncorrelated with coast warp at shared positions (the existing isolation-test pattern).
4. **Goldens, deliberate re-pin discipline** (`UPDATE_GOLDEN=1` + rationale comment, the T-1162 precedent): `cascade_golden` re-pins (mouths list loses pole drains; `river_downstream` added). `window_derivation_golden`: first **verify empirically** whether the 128×64 fixture produces river cells near the sweep positions (audit: unconfirmed); add a course-bearing sweep position either way so courses are actually pinned. `believability`: expected unchanged (the point test cannot fire at district spacing) — **verify, don't assume**; an unexpected re-pin there is a bug signal, not a regen chore.
5. **Full `cargo test` before push** (the golden harnesses are separate test binaries; `--lib` misses them), and the live-screenshot pixel-diff eyeball check on the merged result, cold-launched — this batch is rendered-path.
---
## Work split and sequencing
**Dudley — server (owns the cost model he probed):**
- **A1** (opening move, unblocks everything): `river_downstream` + sentinels + pole-drain mouth exclusion + Layer-1 golden re-pin.
- **A2**: course inventor (Ruling 3a3d, 3h) in the window derive + `Layer1Output` retention in `TerrainAnalysisCache` + wire field.
- **A3**: termination + mouth flags (3e3f) — with A2.
- **A5** (after A2): T-1168 riparian point test wired into the threaded signal, batch + window paths.
**Stig — client + mechanical threading:**
- **B1** (parallel with A2): T-1168 threading scaffolding (Ruling 4c), inert provider, zero behavior change.
- **B2** (needs A1 only): Region skeleton-chord drawing.
- **B3** (needs A2/A3): course polyline drawing, mouth markers, clip restructure (3g), visibility-table split (5c) with functional defaults for Araminta.
**Hard edges:** A1 → everything. A2 → {A3, A5, B3}. B1 ∥ A2, converging at A5. Nothing else serializes.
**Difficulty tier, honestly: challenging but doable — and the architecture is on our side.** Every primitive exists (`value_noise`, `splitmix64`, the cutoff idiom, the queue, the polyline draw path); this batch composes them, it doesn't invent machinery. The one place I'd have called "extremely difficult" — reconciling a whole-body course with a rung-indexed coastline — stopped being a problem the moment courses went windowed. That's the ruling doing the work.
— Tyre