PROCITY/G-progress.md
m3ultra 4314622c1b Lane G R25: sku-derived slot ids — the re-emit (ledger #3), index-only
Per C §7.2a: items[].id = "sku_<POS sku>" (e.g. sku_20260314070442), never positional. One line at
the emit — the snapshot already carried the sku, I was dropping it.

MEASURED: id overlap with the generic pack 0/120, was 120/120 (F's finding). 120/120 unique, all
sku_-prefixed, none left in the generic packs' rec_ namespace. Id equality discriminates again —
verified through the live loader, not just the file. Index-only as briefed: the two atlas .webp
files are sha-identical (bytes did not move), no town cache touched, no goldens moved. uv,
one-material-per-atlas batching, and shop-pack/town-pack coexistence (120/350) all still hold.

C's reason #2 is the one that outlives the gate: position is not identity. Sell one record out of
crate 550 and rec_0050 silently becomes a DIFFERENT record on the next bake — so a wallet
purchase, a saved dig, or above all tier-2's sold-means-gone would point at the wrong item. The
sku is the shop's own identity for that copy (release_id is the pressing; the sku is the copy). So
the positional ids were a latent correctness bug in the ratified §7 economy, not only a vacuous
gate. Fixed while there are two atlases to migrate instead of fifty.

Conflict #1 closed: E's R25 validator prints "LICENCE: ... FLAG BEFORE ANY PUBLIC/COMMERCIAL
RELEASE" against the top-level US `license` and counts it — atlas-QA OK, 1 licence line shown, 0
warnings. The flag guarding real product photos is unmissable. Nothing owed either way.

Scoped: committed by pathspec on main (G's first as a full lane). F's six staged files and E's
in-flight validate_atlas.py left exactly as their sessions have them.

-> F (your file, your call, not touched mid-flight): interior_mode.js:378's comment now reads
false — ids are no longer positional and no longer collide (0/120). Your gate stays canonical
regardless: a texture URL proves which file the GPU sampled, which id equality never could. Only
the rationale is stale; id equality is now available as a second discriminator if you want it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 02:28:44 +10:00

251 lines
18 KiB
Markdown
Raw Permalink 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.

# G-progress — GODVERSE lane (runs on ultra)
*Lane brief: `docs/LANES/LANE_G_GODVERSE.md`. This file follows your progress-file convention —
newest round first. Fable-on-ultra writing.*
## Round 25 (2026-07-17) — the sku re-emit (ledger #3), index-only
**Landed (main — G is a full lane now, pathspec-atomic; F's six staged files and E's in-flight
`validate_atlas.py` untouched):**
- `godverse_stock.py` emits **`id = "sku_<POS sku>"`** per C §7.2a. One line at the emit; the
snapshot already carried the sku — I was dropping it.
- `stock_godverse/3962749/stock_record_index.json` re-emitted. **Index-only, as briefed:**
| check | result |
|---|---|
| **id overlap with the generic pack** | **0/120** — was **120/120** (F's finding) |
| ids unique in-pack / all `sku_`-prefixed / none in `rec_` namespace | 120/120 · yes · yes |
| **atlas .webp bytes moved** | **none** — sha-identical both files |
| town caches / goldens touched | none |
| ids stable when a record sells (drop item 50, re-derive) | **0 drift** |
| E's validator (their R25 build, live in-tree) | `atlas-QA OK · 1 licence line(s) shown · 0 warnings` |
| live loader: shop pack vs town pack | 120 / 350, coexist; uv + one-material-per-atlas hold |
**Id equality is discriminating again** — verified through the live loader, not just the file.
**C's reason #2 is the one that mattered**, and it's worth restating because it outlives the gate:
position isn't identity. Sell one record out of crate 550 and `rec_0050` silently becomes a
*different* record on the next bake — so a wallet purchase, a saved dig, or **tier-2's
sold-means-gone** would point at the wrong item. The sku is the shop's own identity for that
*copy* (`release_id` is the pressing; the sku is the copy). My positional ids were a latent
correctness bug in the ratified §7 economy, not just a vacuous gate. Caught while there were two
atlases to migrate instead of fifty.
**Conflict #1 is closed** (R24 → R25): E's validator now prints
`LICENCE: … FLAG BEFORE ANY PUBLIC/COMMERCIAL RELEASE` against my top-level US `license`, and
counts it. The flag a human must read on real product photos is unmissable. Nothing owed.
**→ F (one line, your file, your call — not touching it mid-flight):** `interior_mode.js:378`
now reads *"ids are positional slots (`rec_0000`) that BOTH packs reuse … every atlas id is also a
town-pack id (measured R24)"*. As of this commit that's false — 0/120. **Your gate stays canonical
either way**: a texture URL proves which file the GPU sampled, which id equality never could, so
the assertion is right and only the rationale is stale. Id equality is now available as a *second*
discriminator if you want belt-and-braces.
## Round 24 (2026-07-17) — the re-emit + THE SHOP'S REAL STREET (ledger #5)
**THE WRITE-BACK RULING — John, 2026-07-17: A THEN B.** G3 §7 is **ratified** with the ruling
inline; charter law #4 is satisfied. v5.0 ships **sandboxed** — a game purchase never touches real
monsterrobot/Square inventory. **Option B (reservation) is chartered as a v5.x upgrade** behind a
hold budget John sets; **C is not chartered**. What I wrote into the doc as binding, beyond the
one-liner, because a sandbox that can be flipped on by a config typo isn't a sandbox:
`POST /reserve` + `/buy` stay **absent, not flag-stubbed**; the tier-2 reader connects with a
**read-only role** (`SELECT` on inventory/crate/disc_cache only — which carries the §9 PII fence in
the same grant); and the gate asserts the write verbs **404** + the role's grants are read-only,
because "we didn't call buy()" proves nothing (the vacuous-gate law applied to ourselves).
**Carried to v5.x: the hold budget is John's number and is not yet set** — B isn't startable until
it is. B's non-negotiable: **the shop always wins** a race with an in-store Square sale.
**Landed (branch `lane-G-godverse`):**
- **`redhill_godverse`** — the town whose record shop is THE shop. Monster Robot Party seated on
Musgrave Road (**verified: lot 8, type `record`, `godverseShopId` 3962749**), 37 shops, 884 real
Red Hill roads off E's donor.
- **The atlas re-emit** — US `license` throughout (British `licence` retired, 0 occurrences),
provenance lifted to top level per C §7.3 **and** kept nested per E's validator (see conflict #1).
`atlas-QA OK`, 120 real records, byte-identical re-bake holds.
- **`newtown_godverse` re-emitted with `godverseShopId`** (ledger #2) — 18 census shops keyed.
- **`godverse_town.py`**: psycopg2 → `psql` (the m3 has no psycopg2); emits `godverseShopId`;
`EXTRA_SHOPS` roster; **Fable's R22 Ruling 2 finally implemented** (see below).
- G3 §4: the `godverseShopId`/`godverse_id` naming split recorded (two artifacts, two conventions).
**Monster Robot Party's coordinate** is John-supplied (Google Maps place `/g/11g6rlbbc0`
-27.4553791, 153.0076244). It could not be derived: OSM doesn't know the shop (no name match, no
147 Musgrave Rd address node), the census doesn't have it, dealgod's `stores`/`store_entity` rows
carry NULL lat/lng, and recordgod has no address anywhere. Verified inside E's bbox **and** on
Musgrave Road's own geometry. My own estimate was ~120 m out — asked instead of shipping it.
**FABLE'S RULING 2, IMPLEMENTED (R22 → R24) — and it was load-bearing, not cosmetic.** "Merge
census heroes WITH the donor's texture shops; census heroes win a collision; count the swap."
I never built it. Measured this round, census-only Red Hill is **not shippable**:
| redhill_godverse | shops | A's spacing warn | poster-clears-kerb |
|---|---|---|---|
| census only | 9 | **306 m** ⚠ | pass |
| census + Monster Robot | 10 | **261 m** ⚠ | **FAIL** (poster inside edge 1037 by 2.95 m) |
| **+ donor texture (Ruling 2)** | **37** | **none** ✓ | **pass** ✓ |
| *(E's donor `redhill_real`, for reference)* | 36 | none | pass |
261 m is **worse than the 255 m that retired ballarat this round** — the alpha's headline town
would have shipped flagged "scattered, not a high street, or retire the town". Ruling 2 fixes both.
9 donor heroes swapped for their census entries in Red Hill, 18 in Newtown — counted, per the ruling.
**CONFLICT #1 — C's contract §7.3 vs E's validator (provenance).** C says "lift the four to TOP
LEVEL, US `license`; British retired — *exactly what E's validator reads*". **Measured: it is not.**
`validate_atlas.py:98` reads **nested** `provenance`, and `:105` reads `licence` British-first.
Lifting-and-retiring as written **fails the gate**. My R23 atlas already passed it untouched. This
is the same species as the bug that held the tag — a doc asserting what code does without running
it. **Resolved without drama:** E's check accepts `licence or license`, so US-nested passes; I emit
the four at top level (C's contract + the town-cache house convention) off ONE source of truth.
**→ E, one line:** `validate_atlas.py:198` PRINTS `licence` British-only while its *check* accepts
both — so adopting C's mandated US spelling **silently stops printing the licence flag**, which
:199's own comment calls a human call ("the licence is PRINTED — clearing it is a human call").
The gate still passes; the evidence line vanished. Fix: `.get("licence") or .get("license")`.
**CONFLICT #2 — Ruling 2 vs A's identity gate. THIS ONE NEEDS A RULING; it is why the tree is red.**
Ruling 2 makes a godverse cache *mixed*: a keyed GODVERSE layer (census + Monster Robot) plus an
inherited OSM texture layer. A's sweep asserts **every** shop is keyed → partial ⇒ FAIL. The two
standing rulings cannot both hold.
**The texture shops carry no `godverseShopId` deliberately**, and I'd argue A's own words settle it:
- The field *means* "this lot's stock lives at `stock_godverse/<id>/`". An OSM milkbar has no
GODVERSE identity. Minting one from its OSM id pushes a **third id space** into a field that
already carries two, and A's validator calls a duplicate **mis-stocking** — charter risk #3's
exact nightmare, with Monster Robot's crate as the prize. (Measured: OSM ids here are ≥53.1 M vs
census ≤2992 and store id 3,962,749 — no collision *today*; dealgod store ids reach 7 digits and
OSM ids are 8+, so the margin is thin, and "no collision today" is not an id-space design.)
- **A's validator and A's sweep disagree with each other.** The validator: *"Missing = tier 0
(soft). Duplicate = mis-stocked (hard). **They are not the same failure.**"* The sweep fails
partial keying because it *"mis-stocks the rest"* — conflating precisely the two failures A said
are not the same. Unkeyed → parody is the **designed ladder**, not a gap.
- **Proposed (A's call, Fable's ruling):** assert coverage over the **godverse layer**, not the
inherited texture layer — the subject is "shops that claim stock", and the gate stays honest
(it still names its subject and proves a count). Zero-keyed still SKIPs; duplicates still error.
**The 8 red checks, itemised — no surprises for F:**
- `newtown_godverse` base+gig goldens (**2**) — my re-emit moved them, exactly as ledger #2
intends. **A re-pins** (batched): base `0xcf69b387`, gig `0x1e266f60`.
- `godverse identity` ×3 on each godverse town (**6**) — conflict #2, above. Nothing else.
- Unpinned (warn, expected): `redhill_godverse` base `0xb2224939` / gig — **A pins**.
- **Classic covenant `0x3fa36874` intact.** `atlas-QA OK`.
**If Fable rules the other way** (texture layer out): revert to census-only and F inherits the
poster-kerb FAIL at edge 1037 + a 261 m town — that break is A/B's invariant, exposed by real data,
and would need an owner before the tag. I'd rather hand F the conflict than the broken town.
## Round 23 (2026-07-16) — G2a: THE FIRST REAL CRATE + the G3 draft
**Landed (branch `lane-G-godverse`, G namespace only — ready for your mid-round merge):**
- `pipeline/godverse_stock.py` — the per-shop atlas pipeline, split at **the snapshot boundary**:
`snapshot` (runs where the DBs are; freezes every source row + every cover's sha256) →
`pack` (pure: snapshot + image bytes → atlas, no DB, no network). That split is deliberate —
**it's what lets E's `validate_atlas` gate G's output on m3 without the dealgod DB** (ledger #4).
- `pipeline/_godverse/monsterrobot_550.snapshot.json` — the artifact of record (committed).
- `web/assets/stock_godverse/3962749/`**120 real records** from a real crate: 2 atlases
(2048², 256px cells, E's contract verbatim) + index with provenance.
- `docs/G3_ECONOMY_DESIGN.md` — the draft (ledger #2), incl. **the write-back question framed for
John** (§7), now grounded in a real trading shop rather than a hypothetical.
- **Verified:** byte-identical re-bake (same snapshot → same bytes); uv ⊂ [0,1]; every item's
atlas ref resolves; bands standard 58 / collector 56 / grail 6. Eyeballed the atlas: it's a real
deep-house crate (Basement Jaxx, Byron Stingily, Angel Moraes, 4hero, Murk, Blaze).
**THE HEADLINE FINDING — the brief's premise doesn't hold (all measured, R23):**
The ledger asked for "dealgod inventory → one real **Newtown** record shop". That can't be built:
- **No Newtown record shop has stock in any database.** Egg Records / Papa Disquo / Haze Guitars /
The Vintage Record / Downtown Music: **0 items each**.
- **`dealgod.stores` is not a shop census** — 8,754 of 9,285 are **Discogs seller accounts**.
Zero Newtown stores, zero census name matches. It's an item *feed*, not a shop directory.
- **`thriftgod.item` is a demo seed** — 2,221 items across 29 shops, **all Brisbane/Newcastle/Alice
charity shops**, zero record shops.
- **`mint()` cannot produce tier 1**: `TABLESAMPLE SYSTEM (0.5)` + `random.random/uniform/shuffle`,
and **`random.seed` appears nowhere in `server.py`**. Non-deterministic, and it assigns other
sellers' listings to shops that never owned them — which also voids the licence law's "the
*stores' own* product shots" green and makes write-back meaningless. (G3 §2.)
- This is **not** risk #3's "fuzzy matching" — it's a population mismatch. Nothing to match *to*.
**What we found instead — and it's better.** `monsterrobot` (**147 Musgrave Rd, Red Hill, Brisbane**
— John's ruling) is the same real shop in three datasets: `recordgod` (its POS: 28,624 live vinyl,
**24,914 in 357 real crates** with real labels and slot numbers), `monsterrobot.party` (its own
site — **the covers are the shop's own product shots**), and dealgod store **3962749** (the scrape;
the cover cache + the godverse id). **99.3%** of its crate stock joins to a cached cover by Discogs
`release_id`. Not in thriftgod's census, so its godverse id = its dealgod store id 3962749 (real,
stable, clear of the census space — thriftgod max shop id = 2992). Drops counted: 120 of 122 in
crate 550 baked; 2 dropped (no own photo).
**Rulings received from John this round (recorded):**
1. **The crate ships as the shop it really is** — Red Hill, Brisbane, not Newtown.
2. **Real titles/artists at tier 1** — an amendment to the no-real-trademarks law that
`build_stock_pack.py` enforces (it parody-transforms metadata). Same shape as the licence law:
in-house 🟢, **flagged before anything public**. Recorded in every atlas's provenance.
**Asks — two things gate the crate reaching a room, and both are outside G's namespace:**
1. **[C + F] Per-shop packs aren't wired at runtime.** `stockpack.js` caches by `type` alone
(`_packs`/`_resolved`), and `interior_mode.js:192` does `getStockPack(shop.type)` with `base`
fixed to `assets/models/`. R23's single shop works via a `base` override, but **two stocked
shops collide in that cache** — so this blocks v5.0-beta, not just ledger #3. Seam needed:
key the cache by `type + base` (or `godverse_id`) + preload per-shop on entry. **C owns the
wording (LANE_C_PUB); G re-emits to whatever lands.**
2. **[E, via Fable] The crate has no street.** `redhill_real` doesn't exist; `westend_real` is the
only Brisbane cache and stops ~2.3 km south. Needs a `build_towns.py` TOWNS entry
(~`center: (-27.4553, 153.0064), span_km: 2.4`) + one Overpass fetch, then
`godverse_town.py redhill_real redhill_godverse`. **That's E's file and an outward-facing
fetch — G touched neither.** Note monsterrobot must be added to the godverse cache's `shops[]`
as id 3962749 (it's not in the census); `godverse_town.py` takes shops from thriftgod only, so
that's a small G change once you rule on the town.
**Environment note (matters for reproducibility):** this ran on the **m3**, not ultra — the box has
neither `thriftgod` nor `dealgod` Postgres. Both were restored/read from John's mounted backup
drive (`/Volumes/johnking/db-backups`, **2026-07-15** dumps); dealgod (2 GB gz) was never restored,
its cover map was streamed straight out of the dump (command recorded in
`godverse_stock.py:load_image_map`). This is *better* for the charter's snapshot discipline, not
worse: the dump date is pinned in every snapshot's provenance. I left two restored DBs on the m3
(`thriftgod`, `recordgod`) — say the word and I'll `dropdb` them.
**Fences held:** PII — `recordgod` holds real `customer`/`staff`/`sales`; the pipeline reads only
`inventory`/`crate`/`disc_cache`, and G3 §9 makes that a standing fence. Licence — covers are the
shop's own shots, in-house 🟢, flagged before public, provenance in every atlas.
## Round 1 (2026-07-16, ultra) — the marriage's first artifact
**Landed:**
- `pipeline/godverse_town.py` — thriftgod PG census + donor OSM cache → `<key>_godverse.json`
(schema v2, `source: "godverse+osm"`). Deterministic, stdlib+psycopg2, runs where the DB lives
(ultra). Type map thriftgod→registry: music→record, charity/second_hand/antiques→opshop,
books→book, toys/games→toy, video_games→video, pawnbroker→pawn, market→dept.
- `web/assets/towns/newtown_godverse.json`**18 REAL Newtown shops** (Sydney; DealGod census)
on your real 1,086-road graph (roads donated from `newtown_real`, attribution extended).
- Verified on ultra: boots via `?plansrc=osm&town=newtown_godverse&seed=20261990` — splash and
HUD show Newtown, selector shows "Newtown Godverse · OSM fixture", streets render, 25 chunks /
~78 draws. Real shop names should render on facades exactly as your fictional ones do
(data-driven) — **not yet eyeball-confirmed on a specific facade** (see bookmark ask below).
**Found while verifying (asks, no files touched):**
1. **Per-town bookmarks:** `DBG.teleport('shopfront_detail')` on an OSM town lands inside
geometry (synthetic-town coords). Suggest bookmarks resolve against the active plan.
2. **`DBG.enterShop(selector)`** — took neither a type nor a shop name from the cache; a
name/type/id selector would make cross-repo QA one-liners. (Your harness is excellent —
`info/teleport/shot` made this round's verification trivial.)
3. **Sync:** gitea `origin/main` is at `06fe648` (R20 kickoff); the m3 clone holds R20 lane
commits beyond that (up to `94e56ed`). Push when the round closes so ultra tracks you.
**Context from the ultra side (useful to AF):**
- **MODELBEAST grew:** `trellis_mac` (local TRELLIS.2 image→3D, ~$0, proven 15/15 on thriftgod's
Tier-1 props), `sf3d`, `bg_remove_local`, `mflux_image_edit`, `seedvr2_upscale` all live on the
m3's own queue (:8777). Lane E's "HF-gated, setup needed" note is stale — weights are unlocked.
- ⚠️ **Do NOT run trellis_mac output through the MESHGOD finish farm** — its fill_holes+decimate
shreds 200k-tri marching-cubes meshes (proven on ultra, post-mortem in dealgod memory). The
working pipeline: raw GLB → `npx @gltf-transform/cli optimize --compress draco --texture-compress
webp --texture-size 1024 --simplify-error 0.01` → 0.41.8 MB at raw-quality look.
- **Which collides with your no-Draco law** → the ruling ask in the lane brief. If no-Draco wins,
same command minus `--compress draco` (files ~2-3× bigger, still fine); if Draco wins, three.js
needs the DRACOLoader wire your vendored addons already include. Either is one re-emit; the
depot should hold ONE law.
- **15 thriftgod hero props** sit in `OPSHOPGAME/tools/props_out/game/` on ultra (record-crate,
rummage-tub, teapot, crt-tv, suitcase, mannequin-bust…) — op-shop interior dressing your Lane C
might want; John is picking keepers for the 3GOD depot now.
**Next round (G2, proposed):** real-stock atlases — dealgod inventory → `build_stock_pack.py`
per-shop record/book atlases keyed by the godverse shop id, behind `?stock=real`. Contract I'd
like C/E's eyes on: atlas file per shop vs per town; budget per interior; cache invalidation
when stock sells (thriftgod items are one-of-a-kind — sold means GONE, which is the whole
GODVERSE magic: the crate you riffle is a real crate in a real shop).