THE TABLE (LANE_C_PUB §10, the deliverable): what a player can actually do in each of
the 12 shop types, counted in 48 rooms per type. `record` digs (4.6 bins/room) and is the
only room where anything can be sold. `stall` digs — in 27 of 48 rooms; the other 21 (44%)
have NO crate, a measured correction to the round's binding fact #5. The other ten types
offer looking. `?stock=real` is opt-in, so the default boot has zero `buyMesh` anywhere;
garments/snacks/magazines/treasures are unbuyable in any mode; `interactable:true` on
cases/fridges/returns/arcade is read by nothing.
THE MECHANISM: `rummageBin` — a castored galvanised dump tub, rim 0.76 m, heaped with
stickered bric-a-brac and a hand-lettered "EVERYTHING $2" card. 72 rooms: placed 72/72,
reachable 72/72 (0.77–1.15 m), 0 carves, pathOK 72/72, deterministic 72/72, and the rest
of the room byte-identical to pre-R39 72/72 (the spec is appended last). Armed end-to-end:
aim → dig → 16 offers → BUY → bin depletes. Default: 0 bins, dig never opens.
THE CONTENTS ARE NOT SHIPPED. `o.dig` defaults false, so the tub is furniture and the
economy is untouched; `opts.fittingOpts.rummageBin.dig` (or `?opshopdig=1`) arms it. Held
for John with the numbers: 44 record + 36 stall vs 147 op shops across 23 towns.
THE BUDGET: `C-progress.md:841`'s GLB-on 344 is R9-era and stale — today's tree measured
319 before I touched it, so the margin was 31, not six. The bin costs +5 GLB-off / +10
GLB-on at opshop/hall; every other type byte-identical. Margin now 21. Also: `slot.pool`
stops the scatter fill minting a material per item, so 12 goods cost less than 9 did.
FILED, NOT FIXED: Lane E's bookshelf GLB ships transmission:1, which triggers three.js's
transmission pre-pass and issues every draw in the room twice — opshop/hall 191→104,
book/hall 101→51. Roughly half the interior budget. E's asset, so E/F rule.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Light release round — C interior code unchanged since R13 (venue geometry stable by
construction); this is the audit, the amp ruling, and the v3.0-FROZEN docs.
- Re-verified vs the current tree (D's continuity + RY-fix + real instrument GLBs landed):
contract byte-identical (caps 8/8/12, deckY/riserY, gigKeys, determinism), drawSweep <=350
(worst 161), gig-night draws pub 60 / band_room 52 / rsl 71 <=350. Release-law confirmed:
D's rng namespace is disjoint from C's ctx.stream; no golden can move.
- guitar_amp ruling (LANE_C_PUB §3): NOT blessed as-is. D's pose (stage.z+0.15, down-stage)
interpenetrates the bass rig by 0.29 m; move it up-stage-right ~ (stage.w*0.36, deckY,
stage.z - stage.d*0.22), clear of the bass + C's primitive ampStacks. Full amp unification
= v3.1. Cosmetic + ?gigs opt-in -> not a tag blocker. C->D handshake.
- Docs freeze: LANE_C_PUB.md + LANE_C_AUDIO.md marked v3.0-FROZEN; RY §0 reframed past-tense
(the +Z fleet was fixed at source in D's buildFigure, R13 - no per-consumer flips); budgets
updated to R14; in-flight handoffs removed.
- Comment-only code (zero runtime/golden/rng change): fixed stale R12 inline return-shape
comments (watchPoints 6..8 -> 8/8/12; stage bandPoses[3] -> [4] + riserY) in interiors.js +
layout.js; documented the standalone gigKey hand-build. theme.js untouched.
Note for E/F: settled gig-night interior is ~182k tris (E instruments 14k each x5); F's smoke
reports ~34k measuring before the async GLBs load. Interior draw gate passes; v3.1 LOD candidate.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- theme.js: band_room (small/scuzzy tin shed) + rsl (carpet-and-flock club) venue recipes,
reusing the pub machinery via a new per-kind venueSpec (deck size/height + crowd cap).
- layout.js: parametrized placeStage/placeWatchPoints; 4th `drums` pose seated on the riser
(debt #3 — the band is now a 4-piece across all venues), stage.riserY + per-pose y.
- interiors.js: robust gig-<genreKey> resolution (gig.genreKey -> shop.genreKey -> kind
default) matching E's renamed manifest beds (debt #1); API doc for the 4-piece + riserY.
- LANE_C_PUB.md: 3-kind venue contract + pinned ry convention and the empirically-verified
keeper/browser back-to-front finding + source-normalise fix for Lane D (debt #4).
Verified fresh (seed 20261990 + 90-build soak): watch caps 8/8/12, gigKeys
gig-pubrock/gig-grunge/gig-covers, determinism 0, path/carve 0, gig-night worst RSL 237 draws
asset-free (16 rigs) / 77 GLB <=350, leak geo0/tex0. Shot: docs/shots/laneC/rsl_gig_r13.jpg.
Lane F: bump flags_check band==3 -> ==4 (tools/flags_check.py:674,794) — RED by design.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
v3.0-alpha band room. New pub recipe (venue:true): stage + PA + amps at the back wall (new stage/paSpeaker/ampStack fittings, GLB slots stage/pa_speaker/amp for E), bar counter (keeper), sticky carpet, blocked back door = green room.
buildInterior returns for venues: room.watchPoints[] (6-8 seeded audience poses {x,z,ry,dance} facing the stage, dance ~1/3, counter.stand ry convention); room.stage {x,z,w,d,deckY,frontZ,bandPoses[3]} for Lane D's band; room.audio.gigKey ('gig-'+genreKey) set when Lane F passes opts.gig.
Flags-off byte-identical: venue code runs only for recipe.venue on its own seed sub-streams; non-pub rooms have watchPoints:[], stage:null, unchanged placement/audio.
Verified: 40-seed pub sweep (0 throws/carves/path-fails, 8 watchPoints, dance 0.38) + 60-room mixed soak (0 det/path fails, leak geo0/tex0, worst 19ms). Non-pub unchanged. Interface for D/F: docs/LANES/LANE_C_PUB.md. scaffold + manifest green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
layout.js placeBrowsePoints(): 1–3 deterministic floor poses in front of
browsable floor fittings, facing the goods. Guarantees (all asserted):
walkable (occ-free, not reserved), reachable from spawn (door→counter
flood-fill), ≥0.6m apart + clear of keeper stand, every archetype (rich
candidate ring — 4 sides×2 gaps + diagonals — plus a nearest-free-cell
fallback so tight/mismatched rooms still yield ≥1). Pure data: no meshes,
no draws; ≤350 law untouched. Exposed as room.browsePoints[]
{x,z,ry,atKind,slotIndex}, same coord frame + ry convention as
counter.stand (contract in LANE_C_NOTES).
Validated headless: 180 type×archetype×seed combos → 0 empties (177×3,
3×1 via fallback), determinism 0 fails, min-sep 0.7m, 0 keeper clashes.
Test page: cyan browse-post markers on the 'path' overlay + HUD count.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Published R5, unconsumed until now:
- glb.js KIND_TO_GLB: glassCase->glass_case, magazineRack->magazine_rack,
and a NEW crateStack primitive (fittings.js — a stack of crates) ->
crate_stack. yaw 0 (validated on-screen).
- theme.js: crateStack in record + opshop (back-room dressing); glassCase
added to milkbar; magazineRack added to pawn; milkbar magazineRack moved
window->wall (dodges the door-counter congestion).
- layout.js: fixed placeNearCounter — it picked one random side and gave up,
so counter-zone fittings (the glass case) rarely landed. Now it tries both
sides + offsets, then falls back to a free aisle spot, so a min>=1 fitting
reliably lands.
Validated (GLB on, baked depot): all 3 load + render planted/scaled/facing
right. Appearance glassCase 12/12 (toy/pawn/milkbar), magazineRack 12/12
(milkbar/pawn), crateStack ~11/12 (record/opshop). drawSweep still <=350
with them on (worst 177 GLB-on / 157 off). Determinism 0 fails, leak-free,
dig (?dig=1) still riffles batched bins (C3 re-verify). Contact sheet
docs/shots/laneC/glb_orphans_r6.jpg. qa.sh --strict GREEN.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
buildInterior now returns room.counter = { mesh, pose, stand } and tags the counter
interactable with userData.keeperStand. stand = {x,z,ry} where a shopkeeper stands
(service side, facing the customer, rig-front = local -Z per keepers.js), clamped
in-bounds. Deterministic; purely additive.
Note: commit 4235060 carries this message but actually contains Lane A's round-2
content (shared-index race, flagged in 3e98f05). This commit lands the real Lane C
change — identical content to stray branch lane-c/keeper-stand (85438b5), which is
now redundant. Verified: 36-build sweep + 50-room soak green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>