Verdict: shipped, not killed. The R7 park reason ("touches shared materials") is a non-blocker under
R16's measurement-over-brief standard: the gum-tree billboard material is B-owned (furniture.js), so
this is entirely Lane B -- no C/E material seam. Verified fresh Chromium seed 20261990.
- New web/js/world/wind.js: shared uniforms (uWindTime/uWindAmp) + applyWind(material) (onBeforeCompile
vertex patch: top-weighted horizontal sway, per-instance world-position phase, USE_INSTANCING-guarded)
+ updateWind(dt,intensity). furniture.js applies it to the tree material; weather.js drives it from
update(dt) (base breeze 0.05 clear -> 0.05+intensity*0.30 ~0.35 rain gusts).
- Trees only. Awnings excluded by MEASUREMENT: rigid posted-verandah box slabs don't flutter (fabric
canopy ripple = separate v3.3, shares the rigid awning InstancedMesh today).
- Byte-identical when weather off (the covenant): updateWind runs only inside weather.update, and the
weather system isn't constructed under ?weather=0 / ?classic=1 -> uWindAmp stays 0 -> sin(...)*0.0==0.0
-> identical vertices. Proven: amp=0 two times = 0/180000 px differ; ?weather=0 boot = 0 tree-motion px;
?classic=1 = amp 0, trees render, 0 errors. No plan/fetch/rng change -> F's classic gate untouched.
- Sway works: rain amp 0.305 moves ~14100/180000 region px over 0.8s (exaggerated 2.5 -> 101k); trees
render clean, no glitch. ~0 draws (ALU ops in the existing tree InstancedMesh vertex program), 0 errors.
-> Lane F (B->F handshake): SWAY SHIPPED. In old frames under the default boot; ?classic=1/?weather=0
sway-free + byte-identical. Procedural (no asset -> E has nothing to do).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ledger #4. Verified fresh Chromium seed 20261990. No new rng, goldens untouched.
- Town-wide pools (venue.js): extended the R13 instanced-pool pass from venue frontages to EVERY
streetlight + bus shelter. New townPoolSpecs(plan) replicates furniture.js's lamp cadence off the
plan street graph (lamp every 18m from s=8, alternating sides, off=halfRoad+0.7) and reuses the
exported busShelterStops(plan) -- read-only, furniture.js untouched (imported one function). All
pools ride the ONE existing InstancedMesh -> still ~1 draw: 381 instances / 1 draw / ~760 tris.
Night-driven; fog:true now so distant pools fade into night fog (pools aren't chunk-streamed) instead
of floating as dots. Gig-gated -> ?classic=1 is pool-free = v2 parity by construction (no always-on
furniture change, the v3.0 blocker). Deterministic cadence, no seeded draws (release law).
- Default-boot re-baseline: measured the default content (gigs + weather=rain + winmap + tram all
live), settled. Busiest venue block (pub, NIGHT, rain) ~157 scene / ~170 total draws, 66k tris;
venue_night 122, queue_night 121, district_posters/street_noon 185 (worst tour shot), market_square
fresh 97/52k. ALL <=300 draws / <=200k tris. Flip adds ~3 draws (rain 1 + tram 2; winmap 0), pools
add ~0 (instanced). Daytime dense-citizen ceiling (~275, Lane D, live-walk) unchanged (pools night-only).
- Bookmark spot-check: all 19 resolve, un-letterboxed, 0 errors under the default boot; rain+tram+winmap
compose cleanly in old frames (street_noon rainy 177/114k, nothing blocked). No pose fixes.
Ran before F's flip landed (out of the stated order): pools are gig-gated so they work under ?gigs now;
re-baseline uses explicit all-flags URLs = post-flip default content. F re-confirms at close.
-> Lane F (B->F handshake): default-boot busiest block ~170 total draws / 66k tris; worst street view
185 / 131k; densest daytime 97 / 52k. All under budget. Town-wide pools ~1 draw. Pool sprite is
procedural (E has nothing to do).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verified A's ledger-#1 flip (35da83c): the pub's own-frontage poster moved from 15.9m behind the
building to 0.09m from the door on the +Z street face, facing the reader -- no queue_night pose
change needed (R14 prediction held). Gig golden 0x1f636349->0x4f4a549d consumed cleanly.
Fix (John-sanctioned exception to the R14 freeze): posters were unlit MeshStandardMaterial and
rendered pure black at NIGHT (measured frontage poster centre [183,71,59] day -> [4,0,1] night), so
queue_night + district_posters showed no readable bill even after A's flip. venue.js now gives posters
emissiveMap = the poster art, emissiveIntensity ramped in update() by night (0 day -> 0.55 night, same
lerp as glow/pools). Self-lights the bill after dark; daylight byte-identical (verified midday spine
poster pixel-unchanged). No new rng, no plan change, goldens frozen. ?noassets fallback self-lights too.
Verified fresh Chromium seed 20261990: queue_night (seg5, live queue) frames marquee + window glow +
streetlamp pools + a readable red poster by the door + queue punters (90 draws/29k tris);
district_posters night now shows a poster (was black, 180/138k); daylight unregressed.
-> Lane F (B->F handshake): HERO VERIFIED. Shoot queue_night at seg 5 (NIGHT) -- poster now reads there
and night is needed for pools+glow; drive the queue live (rAF throttled in automation). Poster
night-emissive rides the shell's per-frame venuePresentation.update(gigState.byVenue).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Release round: no new systems, no rng, goldens frozen (0x3fa36874 / gig 0x1f636349 both unmoved).
Files: audio.js, venue.js, dbg.js (+ LANE_B_NOTES). Verified fresh Chromium, seed 20261990.
- Alpha-alias readers dropped (debt #1, B first): audio.js venueGigState() loses the alias hop
(g.venueShopId===id -> g.state); byVenue + clock fallback only. venue.js stateGetter() loses the
bare-string arm (F passes gigState.byVenue since R13, confirmed index.html:379); seed = update(null).
Verified live: byVenue {116:on,404:on,490:quiet} at NIGHT drives the marquee with no string arm;
audio resolves gig-<genreKey> per venue with no alias hop. F is UNBLOCKED to delete the getters.
- Bookmark/tour audit under ?gigs=1: all 19 bookmarks resolve, frame un-letterboxed, 0 page errors,
<=300 draws. District venue-conversions hijacked none (night_neon->Video Regal, dig_real->Retro
Groove). No pose fixes needed. (Orphan-chunk teleport inflates tris across sequential shots -- fresh
counts <=153k; tram_stop's real ~293k is close-range Lane D GLB ped rigs, framing fine, not a venue block.)
- queue_night bookmark added (dbg.js): John's release hero -- close 3/4 on the pub door at seg 5
('on'), biased to the queue side; new poseForVenueQueue() recomputes venue.js frontage geometry.
Frames marquee + window glow + streetlamp pools + the queue (spawned live by the shell loop; F's
gig_shot.py drives it live -- verified by manually spawning D's VenueQueue: 2 punters at the door).
- Poster-repetition call (debt #4): FINE, no ask to E -- 2 gigs tonight => 2 distinct designs
(screenprint/Screaming Utes x7, xerox/The Dead Ringers x7); variety scales with venues playing.
- Town-wide streetlamp pools: v3.1 candidate per Fable ruling (venue-scoped for v3.0; no code).
-> Lane F: cross-lane alias sweep is CLEAN (no A/C/D/E reads it); only your own 20 tool lines in
flags_check.py + gig_shot.py remain -- migrate to *Of(id)/venueShopIds[0] when you delete the
gig_state.js:141-151 getters + the CITY_SPEC alias line (with A).
-> Lane A (now gates John's hero-shot poster): buildPosters item 1 still seats each venue's own
frontage poster on local -Z (back wall, 15.9m from the +Z street facade). Flip to +sin,+cos and it
seats by the door -- in the existing queue_night frame, no pose change. Per "don't touch world
code," B did not work around it. Re-flagged from R13.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Generalises the R12 one-pub slice to all 2-4 venues and lands the night-readability polish. All
gig-gated (flags-off byte-identical, verified in a fresh browser context). Files: venue.js, audio.js, dbg.js.
- venue.js -> N venues: per-venue lit marquee/frontage on B's +Z facade side + window-light spill;
streetlamp pools on venue blocks (one instanced warm-pool mesh, night-driven -> the Friday-night
walk reads); town-wide posters instanced per gig (14 posters = 2 draws / 2 textures, band-name
overprint, flat printed-poster fallback). Town-wide pools deferred (would need always-on
furniture.js -> breaks flags-off parity).
- Queue-zone marker per venue: venue.queueZone = {x,z,ry,len} for Lane D (head at the door, extends
along the frontage; queuer faces -ry). queueZones{} + queueZoneFor(id).
- audio.js muffled spill per-genre (debt #1): import gigKeyFor; the nearest venue at doors/on within
26 m spills its gig-<genreKey> through the 470 Hz lowpass, so pub/band_room/RSL crossfade genre.
F: delete the GIG_BED bridge.
- update(gigStates) polymorphic: per-venue map {[venueShopId]:state} (F wires PROCITY.gigs.byVenue)
or alpha-compat bare string (primary pub). Contract documented for F in LANE_B_NOTES.
- ?noassets fetch fix (latent R12 bug): gate the poster JPEG fetch behind !noassets -> 0 gig-layer
network over the 22-JPEG facade/ground baseline.
- dbg.js: venue_night + district_posters bookmarks (seg 5) so tools/qa/gig_shot.py scripts the
street money shot; poseForVenue resolves from the live plan.
Budget (fresh Chromium, gigs-on NIGHT, busiest pub block, all frontages lit): worst 154 scene /
~167 total draws, 64k tris -- <=300 / <=200k. 0 console errors (gigs / gigs+noassets / flags-off).
Verified 3 venues seed 20261990: pub->gig-pubrock, RSL->gig-covers, band_room->gig-grunge (all in
E's manifest).
Finding for Lane A: buildPosters item 1 seats each venue-frontage poster on the lot -Z (back wall,
measured 15.9 m from the +Z street facade) -- flip to +sin,+cos. Spine/pole posters render correctly
and face the footpath ("SCREAMING UTES" readable). Non-blocking (marquee + pools carry the shot).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- web/js/world/venue.js (new): createVenuePresentation — renders E's poster skins at plan.posters with band-name overprint (nameZone, seeded template, flat fallback if JPEG missing); lit pub marquee + bulb row over the door, update(gigState) ramps the glow. Constructed by the shell/F under ?gigs (like weather/tram).
- web/js/world/audio.js: muffled-gig spill — near the venue (<=26m) while a gig is at doors/on, pubrock-live plays through a 470Hz lowpass at low distance-gain. Reads window.PROCITY.gigs (F) with a plan.gigs+clock fallback.
- Prime flag law: inert/absent without the gig layer; goldens frozen (no citygen edits, selfcheck 3074/3074); byte-identical flags-off boot.
- Verified live on a gig plan: THE WOMBATTS posters over band-photo art, The Thornbury Hotel lit at night, spill gain ~0.14. F wiring documented in LANE_B_NOTES; streetlamp-pool stretch deferred.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- web/js/world/audio.js: one AudioContext unlocked on first gesture; day/night ambience crossfade, rain (weather.intensity), footsteps, shop-door music spill (nearest open music-shop, distance-gain), tram rumble+bell, enterShop SFX. Consumes Lane E manifest.audio (3x retry). Self-ticks off window.PROCITY.
- House audio law verified live: silent pre-gesture (0 fetches), ?mute=1 silent surface (0 fetches), ?noassets=1 zero audio/manifest fetches, lazy-load (8.7MB<=25MB), no per-frame alloc.
- window.PROCITY.audio for Lane F: playInterior({musicKey,toneKey})/stopInterior (street beds duck while inside), playSfx, setMasterGain, mute, state diag. Confirms Lane C room.audio={musicKey,toneKey} contract.
- Small guarded [Lane B R11 audio] loader in index.html.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- tram.js: 1 small bus, seeded out-and-back loop on the main-street spine,
door-dwell at each busShelterStops stop, ping-pong at ends. Deterministic,
exactly 2 draws, night headlights via lighting.isNight(). Flag-off identical.
Shell wiring (2 lines) documented for F in LANE_B_NOTES.
- dbg.js: 8 v2 tour bookmarks (16 total) incl. rain_verandah hero shot;
tram_stop now frames the nearest-origin (open) shelter stop.
- weather.js: cap rain gl_PointSize (clamp 2-22px) - near drops are thin
streaks now, not blobs. Rain smoke still GREEN.
- qa.sh --strict GREEN, golden hash frozen, flags-off byte-identical.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New js/world/weather.js + a one-line lighting.setSky(). Seeded per citySeed (weatherFor):
~57/24/19% clear/overcast/rain over 400 seeds, deterministic. Rain = ONE draw (camera-following
Points + procedural streak/fall/wind shader) + wet ground (roughness/darken on shared ground mats,
restored on dispose) + matching rainy sky dome via lighting.setSky. Fully procedural (0 depot fetch).
- Exposes window.PROCITY.weather = { state:'clear'|'overcast'|'rain', intensity:0..1 } for Lane D's
weather-reactive crowds (decision #1). Documented the contract + the exact 3-line shell wiring for F
in LANE_B_NOTES (I don't touch index.html). ?weather=1 seeded (default town rolls clear);
?weather=rain|overcast|clear forces a state for demos/smokes.
- Worst view 141 draws day / 126 night (<=300); composes with ?winmap + night (rain outside a lit
interior-mapped window = the money shot, screenshotted); deterministic; 0 console errors; flag-off
byte-identical (shell never constructs it). Deferred cut line: vertex-shader wind sway on
trees/awnings (touches other lanes' materials) — noted, not done. Tram stretch not attempted.
qa.sh --strict GREEN (5/5).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Consumes the two orphaned street GLBs via the use-if-ready furniture path (fail-soft; ?noassets →
primitives, 0 network).
- Bins: genuinely sparse (~1/block, s+=78m, seeded side), decoupled from benches — country town not
a mall. GLB on its 0.57x0.68 footprint.
- Bus shelters ON THE STREET GRAPH (future tram/bus stops): deterministic rule = midpoint of every
MAIN edge with hashEdge(id)%3===0, road-side footpath by the kerb, long axis along the edge, open
front to road -> 1-3/town (2 in seed 20261990). Solid oriented-rect collider (furniture now returns
colliders; chunks.js merges them into getColliders) -> walk-into-it is blocked. Exported
busShelterStops(plan) -> [{edgeId,x,z,yaw}] as the stop-list contract for the vehicle loop.
- Perf: worst view WITH rig-fleet citizens 94k tris / 148 draws (<=200k / <=300, big margin);
deterministic; all-flags-on (winmap+dig+roster) composes clean, 0 errors. street_bin GLB is 3k tris
-> flagged to Lane E as a decimation candidate (bounded by the sparse cadence for now).
qa.sh --strict GREEN.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Vuntra window trick — a passing pedestrian sees a plausible room through the shop glass with real
parallax, no geometry. One shared ShaderMaterial does single-cube interior mapping on the existing
window mesh (back wall + seeded shelves + side walls + floor/ceiling); per-shop variation via
aTangent/aTint/aSeed attributes, still 1 window draw/chunk. §3.5 held via the shared uHour/uNight +
aHours: night → open room glows warm, closed room dark.
v2 prime law: WINMAP is read from the URL in buildings.js (self-contained — no index.html seam; F
just needs a flags-table row). Flag-OFF byte-identical to v1 (windowQuad → v1 hoursQuad, v1
windowMaterial). Proven: flag-off windows MeshStandardMaterial w/ no winmap attrs; flag-on interior
ShaderMaterial; worst view 122-168 draws (<=300); 100% procedural (0 fetch delta vs ?noassets
baseline); 0 console errors; GOLDEN.hash untouched. Screenshots in docs/shots/laneB/winmap_*.
qa.sh --strict GREEN (4/4).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- B1: per-shop closed-facade visuals — dark windows + red CLOSED plate + door tooltip, batched via a
per-vertex aHours attr + two shared shaders + one uHour/uNight uniform pair on a procity:segment
event (facade atlas untouched, no per-shop materials, no per-frame poll). 22:00 → only the openLate
video shop lit, all others CLOSED; ~200 draws worst-view with citizens.
- B2: the shots 'letterbox' was camera-jammed-into-a-wall poses, not a composer bug (composer proven
correctly sized headless). Reframed street_noon/arcade/warehouse to look down a street
(streetViewPose), added the 3 missing bookmarks, night_neon now frames the lit video shop amid
CLOSED neighbours, + a defensive composer resize. shots.py: 10 un-letterboxed shots, 0 errors.
- B3: furniture GLB use-if-ready upgrade (bench + food_cart, sit on their footprints) + novelty_record
placed at record stores. novelty_record GLB is 26.5k tris (5x glb_law) → stays low-poly primitive
until Lane E decimates it; ?noassets verified 0 network.
qa.sh --strict GREEN (4/4).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- lighting.js sets scene.environment (neutral PMREM sky->ground gradient, no asset) in attachRenderer, before CitizenSim constructs; Lane D rig-fleet peds bake their impostor atlas from it and render dark if null. Verified set in street/night/interior + after interior-return.
- Re-measured worst continuous-walk view WITH citizens (pop 140, 125 active peds) via window.DBG: 263 scene / 275 total midday, 275 night -- <=300 everywhere. Radius-2 auto already the spawn default.
- Round-3 task 3 (furniture GLB footprints) standby: Fable s3.4 manifest upgrade not yet landed.
- Docs: LANE_B_NOTES.md + B-progress.md round-3 updates.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>