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>
Review debt: book room was 1,245 draws GLB-on. Diagnosed two drivers —
multi-material stock boxes (one draw per face, 6x) and one mesh per stock
item — then batched:
- stock.js: stock boxes are single-material now; every stock mesh tagged
userData.isStock.
- batch.js (new): batchRoom() two-tier merge, called from interiors.js before
the GLB upgrade. Room-level merge of all isStock across every fitting
(grouped by material, world transforms baked) + per-fitting merge of fixture
frames (kept in-group so record bins stay raycast targets for ?dig=1 and the
GLB upgrade can hide the fixture). Uses vendored BufferGeometryUtils
mergeGeometries.
- glb.js: frame-hide is now by isStock tag (not frame-count), so batched
fixtures hide while the room-level stock rides on the GLB.
- interior_test.html: drawSweep() asserts <=350 draws across all type x
archetype (GLB off and on), folded into the soak; exposed as
window.PROCITY_C.drawSweep for F's harness (hook in LANE_C_NOTES).
Result (drawSweep, seed 1990): GLB-off worst 152, GLB-on worst 313
(opshop/hall) — book 1,245 -> 189. Determinism 0 fails / 810, leak-free, dig
still riffles batched bins, worst warm build 38ms (<50), visually identical.
qa.sh --strict GREEN (5 gates).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
E baked the 6 heavy hero props to <=8k tris (c522464). Re-measured every
interior GLB-on (cache-busted to bypass the dev browser's stale HTTP cache;
production clients fetch baked directly):
- record 43.6k tris (C3 target, ~273k pre-bake), draws 322
- milkbar 38.9k tris (was 468k — the R4 over-budget flag is now CLOSED)
- all rooms <=107k tris; book is the draw-call outlier (1245 draws from ~9
bookshelf GLBs + ~600 primitive spines) — tris fine, interiors render
one-at-a-time so gate 3 unaffected; instancing spines is a future lever.
Full table in docs/LANES/LANE_C_GLB_VALIDATION.md. Round 5 complete for Lane C.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ported 90sDJsim/web/world/dig.js → web/js/interiors/dig.js. Walk to a record
bin, press E, riffle its sleeves (scroll/drag), click the front sleeve to pull
it, BUY IT. Faithful to the source: hinge-forward riffle, pull-and-inspect
panel, procedural fwip/thunk audio.
- Riffle items = seeded procedural sleeves per bin via the stockAdapter(shop,
'sleeve') seam (parody 90s-AU records now; real GODVERSE records feed the
same seam in round 6+). Same bin ⇒ same order.
- Buy is STUBBED (toast + remove-from-bin; getCash returns a constant) —
economy is round 6+ per integrator decision #1.
- Own scene + camera; leak-free: per-open GPU resources (sleeve textures/
materials, crate parts) freed on every close(), persistent set freed on
dispose(). Dig soak (20× enter/leave) → leakGeo 0 / leakTex 0.
- Flag-gated (?dig=1): buildInterior is UNTOUCHED, so ?dig=0 boot is
byte-identical to v1 (prime law). The dig is wired only in the test page via
an E-key raycast; F owns the shell input/mode seam — hook documented in
docs/LANES/LANE_C_NOTES.md.
Verified: riffle + pull + buy-stub work; dig soak leak-free; placement
determinism unaffected; close returns to the interior. qa.sh --strict GREEN.
Shot: docs/shots/laneC/dig_riffle_r5.jpg.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round-5 §Lane C task 1 (the v1.1 gate). Map Lane E's R4-late re-exports in
glb.js:
- record_crate FIXED (E stripped sourceless AO/roughness slots) → crate/
recordBin upgrade to plastic crates with the procedural sleeves inside;
removed the stale "fails to load" comment.
- counter → 'counter_till' (the real ~1.6m timber counter WITH a modelled
till; NOT the 4m balcao). Footprint-fit + floor-plant + keeper-stand pose
unchanged.
- Double-till resolved (documented): counter_till carries its own till, so
the separate cash_register attach is dropped whenever the counter GLB is
live (falls back to cash_register on the primitive counter otherwise);
milkshake_mixer stays on the milk-bar bench, lifted +0.10m onto the taller
GLB counter.
Validated (GLB on, via depot): sweep+soak {throws 0, path 0, det 0, worst
10.4ms}, 0 rooms with a visible primitive till, leak-free vs a saturated
baseline (the transient 2geo/4tex first-sight is record_crate + counter_till
cache-fill). Primitive path byte-unchanged (glb.js-only edit). qa.sh --strict
GREEN. Contact sheet docs/shots/laneC/glb_v1_1_r5.jpg. → F can tag v1.1
(LANE_C_NOTES.md).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round-4 §Lane C — map the 4 new hero props + cash_register (manifest now
14 fittings), validate, measure, clean up.
- glb.js: map listening_booth→listeningCorner (record), drinks_fridge→fridge
(milkbar), arcade_cabinet→new arcadeCabinet primitive (video focal prop).
New attachCounterTop() places cash_register on every counter's till slot
(hides the primitive till) + milkshake_mixer on the milk-bar benchtop;
counter primitive + keeper stand untouched. All yaw 0 (no correction).
- fittings.js: new arcadeCabinet primitive (footprint/height matched to the
GLB); counter exposes counterTop attach points + tags the primitive till.
- theme.js: arcadeCabinet in the video recipe; the 3 focal props (arcade,
listeningCorner already, +) raised to priority 6 + placed first so the
door-counter path loop can't pull them → 24/24 appearance.
- interiors.js: thread recipe.key to upgradeRoom (gates milkshake_mixer to
milk bars).
- interior_test.html: load GLBs via the live depot: path (drop the deleted
_local_glb localBase shim; ?localdepot=1 still works offline).
Validated (all via live depot): primitive sweep 810 {throws 0, pathFail 0,
detFail 0}; GLB-on soak {throws 0, path 0, det 0, leakGeo 0, leakTex 0,
worst 7.3ms}; all 5 new props render planted/scaled/facing right (contact
sheet docs/shots/laneC/glb_heroprops_r4.jpg). Room tris measured: milk-bar
GLB-on ~468k (drinks_fridge 77k + milkshake_mixer 73k) — reported to Lane E
as the #1 bake-pass target (not fixed, per integrator decision #2; interiors
render one-at-a-time so gate 3 is unaffected). record_crate still broken +
counter still oversized — both await Lane E re-export (C task 5). Deleted the
stale web/assets/_local_glb/ validation copy. 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>