Lane C R23 (v5.0-alpha): the first real crate verified in the room (ledger #3)

Verified G's stock_godverse/3962749/ (120 real records, Monster Robot Party crate 550,
2 x 2048^2, cell 256) in a fresh context — deliberately BEFORE the merge, so a contract
failure would block it. It didn't.

PASS — the contract holds; G re-emits nothing:
- Resolves through the existing stockAdapter path via a base override (no C code change for
  the single-shop alpha). 120 items / 2 atlases / 8-of-8 stock meshes atlas-backed (real
  covers: peperecordings, DEEPCHILD, "39", mff FREAKS...).
- Ceilings hold: 118 draws with real covers (<=350 law), pathOK, 0 carves.
- Fail-soft holds (clean cache): missing atlas -> null -> parody (20 meshes, 110 draws);
  no adapter (?noassets shape) -> parody, zero fetch. 0 console errors.
- G's index compliant: items[] sorted by id (my determinism ask honoured), provenance, uv in
  [0,1], 2 atlases = exactly the cap, cell_w/h harmless (C reads uv, never cell).

CORRECTED MY OWN CEILING (LANE_C_PUB §7.2): I wrote "<=8 MB decoded" from an assumed ~16-item
"typical shop". A real record shop is 120 records => 2 x 2048^2 ~= 32 MB, 4x my number. The
structural rules held (<=2 atlases; 2048^2 for 60+ items — G landed on the cap); only the MB
figure was wrong, because it described a shop that doesn't exist. New: <=2 atlases @<=2048^2,
LRU = 1 shop's atlas set resident => <=32 MB peak (bounded; vs E's 181 MB unbounded today).
Do NOT shrink the cell below 256 to save VRAM — the dig renders covers close up.

G's ask #1 CONFIRMED and worse than reported (LANE_C_PUB §8 — C's spec, C's fix): stockpack
keys _packs/_resolved by type alone, so base is ignored on a cache hit (measured: the 2nd
preload returned the identical object). (1) two stocked shops collide; (2) it BREAKS FAIL-SOFT
— an unstocked shop of a cached type inherits that crate instead of parody. Seam: key by
type+base, per-shop preload on entry, LRU=1 + dispose; C consumes whatever identity field
lands, C does not invent it.

Two gaps block F's #7a, neither C's: the crate has no street (redhill_real absent; monsterrobot
not in any shops[] — G's ask #2 to E/Fable), and interior_mode.js:192 pins base to
assets/models/ (needs §8 + the identity field).

Committed from a temp git worktree on main — the shared checkout stayed on lane-G-godverse
(Fable's review) and G's branch keeps its disjoint namespace. Docs-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-16 23:42:30 +10:00
parent 84e0a1b764
commit d2eb9df03f
2 changed files with 100 additions and 6 deletions

View File

@ -3,7 +3,54 @@
*Status: **v1 complete & verified**. Standalone interiors library + test page. Every shop door opens
into a unique, seeded, themed interior, generated on demand in ~4ms, byte-identical every revisit.*
Last updated: 2026-07-16 (round 22) · owner: PROCITY-C · reviewer: Fable
Last updated: 2026-07-16 (round 23) · owner: PROCITY-C · reviewer: Fable
---
## Update 2026-07-16 (round 23, v5.0-alpha THE FIRST REAL CRATE) — the crate in the room (ledger #3)
R23 §Lane C. **Verdict: the contract holds — G's atlas needs no re-emit.** Verified against G's
`stock_godverse/3962749/` (120 real records from Monster Robot Party's DEEP HOUSE crate 550, 2 × 2048²,
cell 256²) in a fresh context. Ran **before** Fable's merge deliberately — if the contract failed, that
blocks the merge. It didn't.
**PASS — the first real crate renders in a PROCITY room:**
- **Resolves through the existing `stockAdapter` path** via a base override — no C code change needed for
the single-shop alpha. 120 items · 2 atlases · **8/8 stock meshes atlas-backed** (real covers). The
sleeves are legible on screen: *peperecordings · DEEPCHILD · "39" · mff FREAKS · The Angels Instinct feat
Charlie Ashcroft* — a real deep-house crate.
- **Ceilings hold:** **118 draws** with real covers (≤350 law), `pathOK`, 0 carves.
- **Fail-soft holds** (clean cache): missing atlas → `null` → parody (20 parody meshes, 110 draws); no
adapter (the `?noassets` shape) → parody, zero fetch. **0 console errors.**
- **G's index is compliant:** `items[]` sorted by id (my R22 determinism ask honoured), provenance present,
`uv ⊂ [0,1]`, 2 atlases = exactly my cap, `cell_w/cell_h` harmless (C reads `uv`, never `cell`).
**I got a number wrong, and the first real data caught it (LANE_C_PUB §7.2 CORRECTED).** My R22 ceiling
said "≤8 MB decoded" — derived from assuming a "typical shop" is ~16 items @1024². **A real record shop is
120 records.** At the contract's own 256² cell that's 2 × 2048² ≈ **32 MB**, 4× my figure. The *structural*
rules held (≤2 atlases; 2048² for 60+ items — G landed exactly on the cap); only the MB number was wrong,
because it described a shop that doesn't exist. **Corrected:** ≤2 atlases/shop @≤2048², **LRU = 1 shop's
atlas set resident ⇒ ≤32 MB peak** (still bounded; still far better than the 181 MB unbounded accretion E
measured). And explicitly: **don't shrink the cell below 256² to save VRAM** — the dig shows a cover
close-up; resolution is the one thing the player actually sees.
**G's ask #1 CONFIRMED — and worse than reported (LANE_C_PUB §8: C's spec, C's fix).** `stockpack.js` keys
`_packs`/`_resolved` by **`type` alone**, so `base` is **ignored on a cache hit**. Measured:
`preloadStockPack('record', {base:'…/3962749/'})` then `preloadStockPack('record', {base:'assets/models/'})`
**returned the identical object**. Consequences: (1) two stocked shops collide — the 2nd serves the 1st's
crate (blocks v5.0-beta, as G said); (2) **it breaks the fail-soft law** — an *unstocked* shop of a cached
type inherits that crate instead of parody. The second is a correctness bug, not a mix-up. Seam spec
published (cache key = `type + base`; per-shop preload on entry; LRU=1 + dispose; **C consumes whatever
identity field lands — C does not invent it**). **C owns and lands it** — the §7 promise coming due.
**Two gaps block F's gate #7a (neither is C's; both flagged):** (1) **the crate has no street**
`redhill_real` doesn't exist and monsterrobot isn't in any town's `shops[]` (G's ask #2 → E/Fable);
(2) the shell's `interior_mode.js:192` calls `getStockPack(shop.type)` with `base` fixed to
`assets/models/`, so it can't reach a per-shop pack until §8's seam + the identity field land (C+F).
*Process note:* the shared tree was checked out on `lane-G-godverse` for Fable's review, so I committed
these C docs from a temporary `git worktree` on `main` — the shared checkout was never touched, and G's
branch keeps the disjoint namespace the two-studio merge law depends on.
---

View File

@ -7,6 +7,9 @@
> (ledger #2, the density widening; C→E handshake). The frozen venue contract (§0§5) is unchanged.
> **v4.0 amendment (2026-07-16):** **§7 added — the G2a per-shop stock-atlas contract** (C's interior
> draw/tex ceilings, answering Lane G + E's review). §0§6 unchanged.
> **v5.0-alpha amendment (2026-07-16):** **§7.2's VRAM number corrected + §7.8 added** — G's first real
> crate (120 records) proved my "≤8 MB" figure was derived from a wrong assumption, and the per-shop cache
> seam is now specified for G+F. **G's R23 atlas needs no re-emit.** §0§6 unchanged.
*The district ships **three** venue archetypes behind `?gigs=1``pub`, `band_room`, `rsl`. Lane A
converts a chosen shop to a venue kind in place (`shop.type = kind`); C keys the interior recipe off
@ -242,10 +245,21 @@ worst rooms today are record 41 / book 58 / toy 57 draws against the ≤350 law;
E's audit is correct and the cause is a deliberate C design note (`stockpack.js:11`): atlas textures are
"shared/cached in the pack (**NOT per-room**), like depot GLBs". That is **right for 3 bounded type-packs**
and **wrong for unbounded per-shop atlases** (23 towns × N shops). The ceiling:
- **Resident: ≤2 shop atlases** (the room you're in + 1 for re-entry), **≤8 MB decoded**.
- **Atlas size: ≤1024² for a typical shop** (16 items @256² cell); **2048² only for a 60+ item shop**, and
prefer spilling to the type-pack. At 1024² RGBA ≈ 4 MB → ≤2 resident ≈ **8 MB** (vs E's measured **181 MB**
resident today — ~20× better, and bounded instead of accreting).
> **⚠️ CORRECTED v5.0-alpha — measurement beat my assumption.** I wrote "≤8 MB decoded" by assuming a
> "typical shop" is ~16 items @1024². **G's first real crate is 120 records** (Monster Robot Party, crate
> 550) — a real record shop is nothing like 16 items. At the contract's own 256² cell that's 2 × 2048²
> = **~32 MB decoded**, 4× my stated figure. The *structural* rules were right (≤2 atlases; 2048² for a
> 60+ item shop) — only the MB number was wrong, because it was derived from a shop that doesn't exist.
> **G's R23 atlas is compliant; no re-emit.** The corrected ceiling:
- **Per shop: ≤2 atlases, ≤2048² each** (unchanged — G's 120-item crate lands exactly on the cap).
- **Resident: ONE shop's atlas set** (LRU = 1 shop, not 2) ⇒ **≤32 MB decoded peak**. Still bounded, and
still far better than the **181 MB unbounded** accretion E measured today.
- **≤1024² whenever the crate fits it** (≤64 items at 256²) — don't hand a 6-item shop a 2048².
- Cell size is E/G's call: **C reads `uv`, never `cell`** (so 256², 176×256 portrait, etc. are all fine).
Do **not** shrink the cell below 256² to save VRAM — the dig renders a cover close-up; resolution is the
one thing the player actually sees.
- **C lands the LRU cap + dispose in `stockpack.js`** (evicted shop's atlas texture + material disposed).
Type-packs keep today's shared cache (bounded, reused across rooms of a type) — unchanged.
- **Scheduling:** today's 181 MB accretion is **pre-existing**, and `?stock=real` is **opt-in**
@ -274,4 +288,37 @@ a re-emit silently reshuffles every crate. Same discipline as E's byte-identical
satisfies that naturally (better than the type-pack's seeded `atlasPool` pick). Parody = not buyable stays.
**7. Parody law — E's (d), unchanged and not C's to relax.** Metadata deterministically parody-transformed;
cover art real; prices real-or-seeded.
cover art real; prices real-or-seeded. *(v5.0-alpha: John amended this at tier 1 — real titles/artists ship
in-house-green, flagged before public. Recorded in G's provenance; not C's to relax either way.)*
**8. The per-shop cache seam (v5.0-alpha — C's spec; G+F build to this). CONFIRMED BROKEN in R23.**
G's ask #1 is real and I reproduced it. `stockpack.js` keys `_packs`/`_resolved` by **`type` alone**, and
`preloadStockPack(type, {base})` **ignores `base` on a cache hit**. Measured (R23, fresh context):
- `preloadStockPack('record', {base:'assets/stock_godverse/3962749/'})` → the 120-record godverse pack ✓
- then `preloadStockPack('record', {base:'assets/models/'})`**returned the identical object**
Two consequences, the second worse than G's report:
1. **Two stocked shops collide** — the 2nd silently serves the 1st shop's crate (blocks v5.0-beta).
2. **It breaks the fail-soft law** — an *unstocked* shop of a cached type inherits that crate instead of
falling back to parody. (On a clean cache fail-soft is intact: missing atlas → `null` → parody, 0 errors.
The collision is what defeats it, so this is a correctness bug, not just a mix-up.)
**The seam (C owns it, C lands it):**
- **Cache key = `type + base`** (equivalently a `packKey`; a godverse shop's key is its `stock_godverse/<godverse_id>/` base). `getStockPack` takes the same key.
- **Resolution order** stays: explicit per-shop base → the type-pack base → `null` → parody.
- **Per-shop preload on entry** (interior build/enter), **not** a boot-time preload of every shop.
- **LRU = 1 shop's atlas set, disposed on eviction** (§7.2) — the load-bearing half of the §7 promise.
- **Identity link:** a stocked shop must carry its pack pointer on the shop record (G's `godverse_id`
`stock_godverse/<id>/`). Not in the town cache today — G flagged it ("monsterrobot must be added to the
godverse cache's `shops[]` as id 3962749"). C consumes whatever field lands; **C does not invent it.**
**9. R23 verification — the first real crate, in a room (ledger #3). PASS.**
Measured against G's `3962749` atlas (120 real records, 2 × 2048², cell 256²) in a fresh context:
- **Resolves through the existing `stockAdapter` path** via a base override — no C code change needed for
the single-shop alpha. 120 items, 2 atlases, **8/8 stock meshes atlas-backed** (real covers, not parody).
- **Ceilings hold:** **118 draws** with real covers (≤350 law); room `pathOK`, 0 carves.
- **Fail-soft holds** (clean cache): missing atlas → `null` → parody (20 parody meshes, 110 draws, pathOK);
no `stockAdapter` (the `?noassets` shape) → parody, zero fetch. **0 console errors** throughout.
- **G's index is contract-compliant:** `items[]` sorted by id (my determinism ask honoured ✓), provenance
present ✓, `uv ⊂ [0,1]` ✓, 2 atlases = the cap ✓, `cell_w/cell_h` harmless (C reads `uv`) ✓.
- **Verdict: the contract holds. G re-emits nothing.** The only C-side work is §8's seam.