diff --git a/docs/LANES/LANE_E_NOTES.md b/docs/LANES/LANE_E_NOTES.md index 0d6b5d5..37ad1cf 100644 --- a/docs/LANES/LANE_E_NOTES.md +++ b/docs/LANES/LANE_E_NOTES.md @@ -1,5 +1,53 @@ # LANE E — cross-lane notes +## Round 27 — provenance v5-final, and the roster gap the docs freeze caught ⟨v5.0⟩ + +**1. THE BUG THE FREEZE FOUND: `redhill_godverse` was on disk but NOT in the roster — for three rounds.** +The v5 provenance table needed real numbers, so I measured instead of carrying the v4 row forward. The +count didn't match: **23 caches on disk, 22 rostered.** The missing one was **`redhill_godverse` — the +town the entire v5 epoch walks to.** + +**Mine, squarely.** `index.json` is Lane E's file (`write_index()`). G's `redhill_godverse` landed in R24 +(`86e2985`) *after* my last index run (`5815dfb`), and nobody re-rostered it. **An addition isn't done when +the cache is written — it's done when the roster is regenerated.** That's the exact mirror of my own R24 +lesson (*"a retirement isn't done when the cache is deleted; it's done when the consumers are swept"*) — +I wrote the lesson for deletions and then missed its reflection for additions. + +**Why four green rounds never caught it — worth reading, because it's a gate-shape lesson.** Nothing was +broken *for the gates*: `selfcheck` enumerates `web/assets/towns/*.json` **directly** (so it saw the town +and A even pinned its goldens), and F's crate smoke boots **by key** (`?town=redhill_godverse`). The +roster's *only* consumer is **B's HUD selector** (`hud.js`, my R20 ledger #2 design). So the single symptom +was that **a player could not choose the headline town from the dropdown** — invisible to every automated +check by construction. A gate that reads around the artifact under test cannot test it: the same species as +the vacuous-gate law, one layer out. **Fixed:** re-ran `write_index()` → **23 rostered, 23 on disk, 0 +missing**; only `index.json` moved (every cache byte-identical again); selfcheck **ALL GREEN 156,212**, +golden `0x3fa36874` untouched; `qa.sh --strict --matrix` **7/0/0**. + +**→ F: this matters for #5, the tour.** The money shot walks Musgrave Road into Monster Robot Party. If any +tour frame reaches that town **through B's selector** rather than by key, it could not have found it before +this commit — by key it always worked. Worth one glance at your framing path. +**→ B:** the dropdown now carries both godverse towns. Your `${t.state ? ', ' + t.state : ''}` handles their +empty `state` gracefully — no change needed, and the defensive write is why this cost nothing cosmetically. +**→ G:** your godverse caches carry no `state`, so they roster as `state:''`. Harmless today (B degrades +cleanly). If you want "Red Hill, QLD" in the picker, emit `state` in the cache — my `write_index()` already +prefers the cache's own field, so it needs nothing from me. + +**2. Provenance v5-final (ledger #6).** The ⟨v5.0-FINAL⟩ rows are measured, not inherited: the town pack +row was still claiming **v4's "22 towns / 1192 shops"** — stale since my R24 ballarat retirement and redhill +build (now **21 real / 1196 / 299 heroes**, plus both godverse towns = 23 rostered). Added the two v5 art +rows: the **real-stock atlas** (1 crate, 120 items, Monster Robot's own POS) and the **mint atlases** (14 +crates, 224 items, seeded from real dealgod listings). **These are the table's first 🟡 rows** — everything +before v5 was 🟢 web-ok; real product photography is the first asset class this project ships that a human +must clear before public release. + +**3. The licence line's story, written down as a mechanism (ledger #6).** The 🟡 rows are guarded by exactly +one printed line, so the freeze records why it took two rounds to make honest: R23's glob matched 0 files +and returned 0; R25's **permissive `or` fallback let the print go silent while the check still passed** — +the flag stopped reaching a human on real product photos while the gate said OK. Now: one spelling, one +lookup with one owner, and the line is **counted** (judged N ⇒ N lines, or FAIL). **Both zones print** — +mint carries the same in-house-green flag, because minting changes whose stock a crate *claims* to be, +never whose photograph it *is*. Frozen today at **15 crates, 15 flags, every one in front of a human.** + ## Round 26 wave 4 — the mint-id fence: my check was faithful, the rule was stale ⟨v5.0-beta⟩ **The red was mine and the fix is C's ruling.** My R25 slot-id check demanded `sku_` on every real-stock @@ -702,12 +750,50 @@ loader wiring (`spawnRig`/fleet). Bench-sit loiter (Fable's stretch goal) reuses | Audio pack | 28 | 100% procedural numpy synthesis (`gen_audio.py`) | oscillator/noise render → ffmpeg OGG+M4A | 🟢 CC0-equiv, parody-safe | | Stock packs | 3 (350/311/273) | GODVERSE `dealgod` Postgres — **real** cover art | `build_stock_pack.py`: parody-transform metadata + atlas | 🟢 real-art / parody-metadata | | Ped clip **⟨v3.1⟩** | `sit.glb` (E R16; + pre-existing `walk`/`idle` from D/90sDJsim) | Adobe **Mixamo** `Sitting_Idle.fbx` | `fbx_to_clip.py` (Blender, mesh-strip) | 🟢 Mixamo royalty-free (motion only, mesh stripped) | -| Town pack **⟨v4.0-FINAL⟩** | **22 real AU towns, all 8 states/territories** — 1192 shops + real street geometry (`roads[]`) | **OpenStreetMap** via Overpass API — bounded per-town bbox; raw shops+roads snapshots committed in `_raw/` | `build_towns.py`: fetch → dedupe/suburb-fill/parody → C's §6 class map → 3× texture cap (drops counted) → v2 cache + roads | 🟢 **ODbL 1.0** (© OSM contributors; `web/assets/towns/SOURCES.md` + `license`/`attribution` on every cache) | -| Godverse town *(Lane G's, listed for completeness)* | `newtown_godverse` — 18 shops, rostered in E's `index.json` | GODVERSE/thriftgod shop census + OSM road geometry | `pipeline/godverse_town.py` (**Lane G owns this provenance**) | 🟢 ODbL 1.0 + GODVERSE census (G's own `license`/`attribution` fields) | +| Town pack **⟨v5.0-FINAL⟩** | **21 real AU towns, all 8 states/territories** — **1196 shops** (299 heroes) + real street geometry (`roads[]`) | **OpenStreetMap** via Overpass API — bounded per-town bbox; raw shops+roads snapshots committed in `_raw/` | `build_towns.py`: fetch → dedupe/suburb-fill/parody → C's §6 class map → 3× texture cap (drops counted) → v2 cache + roads | 🟢 **ODbL 1.0** (© OSM contributors; `web/assets/towns/SOURCES.md` + `license`/`attribution` on every cache) | +| Godverse towns *(Lane G's, listed for completeness)* **⟨v5.0-FINAL⟩** | `newtown_godverse` (72 shops) · **`redhill_godverse` (37)** — the town whose record shop is THE shop. Both rostered in E's `index.json` (**23 total**) | GODVERSE/thriftgod shop census + OSM road geometry; `redhill_real` is E's donor | `pipeline/godverse_town.py` (**Lane G owns this provenance**) | 🟢 ODbL 1.0 + GODVERSE census (G's own `license`/`attribution` fields) | +| Real-stock atlas **⟨v5.0-FINAL⟩** | **1 crate, 120 items**, 2×2048² webp — Monster Robot Party (`3962749`) | **the real POS** (`recordgod`) — crate 550 "DEEP HOUSE"; covers are **the shop's own product shots**, cached by dealgod | `pipeline/godverse_stock.py` (**Lane G owns**) — `snapshot`(DB-side, sha256-pinned) → `pack`(pure) | 🟡 **in-house-green — FLAG BEFORE ANY PUBLIC/COMMERCIAL RELEASE** · `sourcing:"real"` · ids `sku_` | +| Mint atlases **⟨v5.0-FINAL⟩** | **14 crates, 224 items**, 14×1024² webp — keyed hero shops with **no POS** (5 record · 6 book · 3 toy across both godverse towns; the 6th record crate is the real one above) | **real dealgod listings** (the sellers' own product shots) — a *seeded sample*, `random.Random(shop_id)`, deterministic | `godverse_stock.py` mint baker (**Lane G owns**) — same bake path, sampled source | 🟡 **in-house-green — same flag** · `sourcing:"mint"` · ids `mint_` · **never claimed as that shop's stock** | **GLB fleet = 33 manifest (23 fit + 10 furniture) + 5 `_hi` = 38 published.** Only external spend ever: ~$0.64 (fal-Hunyuan, R5). Everything else is $0 / on-device (electricity only). +### ⟨v5.0-FINAL⟩ The licence line's story — why one printed line is a provenance mechanism + +**The only 🟡 in this table is the v5 stock art, and the flag is the whole control.** Charter law #3 says +clearing photos for public release is **a human call** — so the gate does not pattern-match the licence +and rule on it. It **prints it**, every run, for every atlas, and a human decides. That makes one printed +line the mechanism the amber rows depend on, which is why it earned two rounds of work: + +- **R23** — the gate globbed a name the runtime can never load: **0 files matched, returned 0**. It passed + identically whether atlases were absent, misnamed, or perfect. (The vacuous-gate law came from this.) +- **R25 — the line went silent and the gate still said OK.** Not a typo: the **check** read + `licence or license` (permissive) while the **print** read `licence` only. G's re-emit moved to US + `license`; the check passed, the print resolved to `{}`, and `FLAG BEFORE ANY PUBLIC/COMMERCIAL RELEASE` + **stopped reaching a human on a real shop's product photos**. *The fallback WAS the bug* — it let one + path stay permissive so it could not feel the other break. +- **The fix is structural, not a spelling.** One spelling, no fallback (British `licence` now ERRORS, + naming C's §7.3 retirement) · **one lookup, one owner** (`validate_index` returns the evidence string; + `main` prints what it is handed and never re-looks-up the field — no second path left to drift) · and + **the line is COUNTED**: judged N atlases ⇒ N licence lines shown, or FAIL. A gate that can say OK while + hiding the flag cannot exist by construction. + +**Today, frozen:** `atlas-QA OK — 15 per-shop atlas(es) valid, 15 licence line(s) shown, 0 warning(s)`. +Fifteen crates, fifteen flags, every one in front of a human. **Both zones print** — the mint rows carry the +same in-house-green flag because a seeded sample of real dealgod listings is still **the sellers' own +product shots**. Minting changes whose stock it *claims* to be, never whose photograph it *is*: that is why +`sourcing` is honesty and the licence is unchanged by it. + +### ⟨v5.0-FINAL⟩ The id-space fences — provenance carried in the id itself + +Two disjoint namespaces, blessed as design (C §7.2a, R26 w4), asserted by `validate_atlas`: +**`sku_`** names a physical copy on Monster Robot's shelf · **`mint_`** names a dealgod +listing standing in for one. A crate wearing the other's prefix **FAILS**. This is not naming hygiene: +tier-2's sold-means-gone looks up POS skus, so a `mint_` id filed under `sku_` doesn't fail a gate — it +**sells a real record out of a real shop to satisfy a minted stand-in**. G refused that shortcut when it +would have gone green the easy way, and that judgment is the fence. *(Same standing note as +plan-ids vs godverse-ids: one name, one space — never compare across.)* + ### Audio inventory — 28 assets (`web/assets/audio/`, committed; contract = `manifest.audio`) All procedural, seeded, $0, parody-safe; OGG/Opus + M4A/AAC; beds+music loudnorm −16 LUFS, SFX peak-norm. diff --git a/web/assets/towns/SOURCES.md b/web/assets/towns/SOURCES.md index 8d993ae..f2024e9 100644 --- a/web/assets/towns/SOURCES.md +++ b/web/assets/towns/SOURCES.md @@ -20,9 +20,17 @@ the "© OpenStreetMap contributors (ODbL)" credit visible. **`index.json` is the machine-readable roster** (key/town/state/shops/roads) — read it rather than hardcoding a list. Every cache carries the same terms; per-town numbers live in each cache's `counts`. -**The pack: 21 real towns · 1196 shops · 299 heroes** (+ Lane G's `newtown_godverse` = 22 rostered in -`index.json`), every one fetched from OSM Overpass with a bounded per-town bbox, ODbL 1.0, raw snapshots -in `_raw/` (shops + roads per town), fetched 2026-07-16 (`redhill_real` 2026-07-17). +**The pack: 21 real towns · 1196 shops · 299 heroes** (+ Lane G's `newtown_godverse` and `redhill_godverse` += **23 rostered** in `index.json`), every one fetched from OSM Overpass with a bounded per-town bbox, ODbL +1.0, raw snapshots in `_raw/` (shops + roads per town), fetched 2026-07-16 (`redhill_real` 2026-07-17). + +> **⟨v5.0-FINAL⟩ roster fix (R27):** `redhill_godverse` — the town the whole v5 epoch walks to — was **on +> disk but missing from `index.json` for three rounds**. G's cache landed *after* my last `write_index()` +> run and nobody re-rostered it. Every gate stayed green because `selfcheck` reads the directory directly +> and F's smoke boots the town **by key**; only B's HUD selector reads this roster, so the sole symptom was +> that **a player could not choose it from the dropdown**. Mine to own: the index is Lane E's, and an +> addition isn't done when the cache is written — it's done when the roster is regenerated. (The mirror of +> R24's lesson, where a *retirement* wasn't done until the consumers were swept.) See LANE_E_NOTES R27. | state | towns | |---|---| diff --git a/web/assets/towns/index.json b/web/assets/towns/index.json index bdf81be..e9dcc1e 100644 --- a/web/assets/towns/index.json +++ b/web/assets/towns/index.json @@ -144,7 +144,7 @@ "key": "newtown_godverse", "town": "Newtown", "state": "", - "shops": 18, + "shops": 72, "roads": true, "source": "godverse+osm" }, @@ -164,6 +164,14 @@ "roads": true, "source": "osm" }, + { + "key": "redhill_godverse", + "town": "Red Hill", + "state": "", + "shops": 37, + "roads": true, + "source": "godverse+osm" + }, { "key": "redhill_real", "town": "Red Hill",