Commit Graph

130 Commits

Author SHA1 Message Date
m3ultra
b322c998db Lane E R16 (v3.1): the drummer's sit clip — sit.glb produced + published
Ledger #2 asset half (E produces, D wires). Fetched Adobe Mixamo Sitting_Idle.fbx (533KB) by scp
from the tailnet source box, converted on-device via Blender (new pipeline/fbx_to_clip.py: import ->
skinned GLB export -> pure-python mesh-strip) to web/models/peds/sit.glb (109KB, mesh-free,
structurally identical to walk/idle: 66 nodes, 65 mixamorig bones, dangling skin, 195 channels).
Verified: three.js loads + 195/195 tracks bind to peds + 0 NaN; Blender confirms seated (hips
0.955->0.299m, stature 1.276->0.758m) + eyes-on bone-dot render (docs/shots/laneE/sit_clip.png).
Published to depot via tailnet under John's R13 auth (_published.json 38->39; benign non-procity_
drift note). Provenance: Adobe Mixamo royalty-free, same zone as the shipped walk/idle; LANE_E_NOTES
v3.1 amendment marker.

-> Lane D: sit.glb ready at web/models/peds/sit.glb (+ on depot); canon binds 195/195; seated confirmed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 12:37:27 +10:00
m3ultra
2b13dd4ad7 Lane A round 16: v3.1 corner-poster clearance bias (#6) + no-spine osm fixture (#7)
Ledger #6 fix + the round's one sanctioned gig-golden re-pin, and ledger #7. Classic/synthetic
golden 0x3fa36874 frozen (classic boot byte-identical across all seeds); base plan untouched.

- Corner poster: the R15 finding (frontage poster near a crossing kerb) is NOT fixable by the brief's
  'nudge along the facade' — proved the crossing edge is PARALLEL and spans the facade (0/187 slides
  help); band_room/rsl land on through-lots on narrow warehouse blocks whose +Z wall (B's door side)
  overlaps the block's other street by up to ~3 m. Surfaced to Fable; ruling: bias pickVenues. It now
  prefers a band_room/rsl candidate whose +Z facade clears every carriageway by >= POSTER_CLEAR (0.5 m),
  broadening off-spine if the fringe is uniformly narrow. Result: 0/851 frontage posters below floor
  across 400 seeds (worst 0.51 m); pub untouched (hero shot unmoved).
- Gig golden re-pinned 0x4f4a549d -> 0xb1d48ea1 (posters moved). selfcheck's R15 blanket frontage
  exemption becomes a real floor: frontage >= POSTER_CLEAR, spine >= 0 (POSTER_CLEAR exported from the
  barrel). Mutation-tested non-vacuous.
- No-spine osm fixture 'silverton' (single-row town, 0 main edges) proves pickVenues' no-spine branch +
  buildPosters' no-main fallback, closing the R14 sweep gap. Base golden pinned 0xd4b351c9; sweep asserts
  0 main edges + graceful 2-4-venue placement. selfcheck ALL GREEN 14769/14769; scaffold + consistency GREEN.
- CITY_SPEC v3 amended (golden, poster clearance-bias prose, no-spine note, recorded amendment). Left the
  prime-flag-law blockquote for F (the v3.1 classic-law + flags-table is F's amendment). For F:
  default-boot golden = 0xb1d48ea1; ?classic=1 target = 0x3fa36874.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 12:35:30 +10:00
m3ultra
54a030b38b Lane B round 16 (v3.1 THE FLIP): town-wide streetlamp pools + default-boot budget re-baseline
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>
2026-07-16 12:21:19 +10:00
m3ultra
42b11e717d Lane C R16 (v3.1): stage.backline[] amp unification, drop primitive ampStacks (ledger #5, C half)
C exposes room.stage.backline[] — 2 seeded up-stage amp slots {x,z,ry,y} (pure data) — and
drops its primitive ampStacks from placeStage. Lane D plants E's guitar_amp GLB at backline[0]
(D's primitive fallback under ?noassets): one unified backline, GLB when present.

- backline[0] = (stage.x + stage.w*0.36, deckY, stage.z - stage.d*0.22) == D's R15-verified amp
  pose exactly, so plumbing D's plant to backline[0] moves nothing on screen. backline[1] = spare
  stage-left mirror. ry=pi (audience-facing), y=deckY.
- Verified fresh (seed 20261990): slots up-stage, on-deck, clear of all 4 bandPoses (nearest-bass
  0.87 pub / 0.70 band_room / 0.92 rsl) and all watchPoints (>=1.95 m); determinism byte-identical;
  0 leftover ampStack groups; drawSweep venues 122/120/131 (was 126/124/135, -~4 draws each) <=350.
- Determinism/golden-safe: dropping the amp loop only drops draws on the 'stage' sub-stream (nothing
  downstream reads it); placement snapshot excludes ampStacks; interiors aren't hashed; ?classic has
  no venues. Disjoint from F's flip. LANE_C_PUB §3 amended (v3.1 marker).

C->D handshake: backline shape live. Verify with D once the GLB is wired at backline[0].

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 12:16:38 +10:00
m3ultra
b9e3f3a92d Fable (integrator): round-16 instructions — v3.1 THE FLIP (defaults on, classic covenant, drummer sits, town-wide pools)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 12:01:26 +10:00
m3ultra
0490bdd07e Lane F R15 (v3.0): docs assembly — README v3, LANE_F_NOTES §14/§15, F-progress, freezes confirmed
- README: a v3.0 'venues & gigs, THE DISTRICT' section — what shipped, the flags table, the release tour
- LANE_F_NOTES §14 (R14: F never ran, brief carried) + §15 (the R15 release-close runbook, numbers, gotcha ledger)
- F-progress: R15 release-close summary at the top
- confirmed all five freezes committed (A a3911a4/35da83c, B eee60e0/a0b5784, C 62e38c5/2446ae3, D 9a65f51/66aec0f, E 55f6698)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:38:37 +10:00
m3ultra
6a35b29352 Lane F R15 (v3.0): the release money-shot tour (ledger #4) + settled measurements (ledger #5)
tools/qa/tour_shots.py: one deterministic run capturing the release set into docs/shots/release_v3/
(+ contact.html), grouped by the flags each shot needs, all seed 20261990:
- venue_night, district_posters, queue_night (John's HERO — now with A's flipped frontage poster VISIBLE
  by the door), gig_interior (the 4-piece + real instruments + a roster crowd — 2 punters carried through),
  rain_verandah, tram_stop
- settled discipline (ledger #5): every shot measured after the async instrument GLBs / poster textures /
  chunk stream land (shoot-twice), from a clean per-group load; the queue is driven LIVE (explicit admits,
  not rAF auto-drain which automation throttles)

The hero confirms ledger #1: the frontage poster reads from the street for the first time. Interior settles
35k->182k tris (draws 56 <= 350 gate). All street shots <=300 draws / <=200k tris. 0 page errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:35:27 +10:00
m3ultra
edc0c479c1 Lane F R15 (v3.0): full-week gig soak (ledger #3) — leak/cover/roster over 7 nights
tools/qa/week_soak.py: rolls the day-clock through all 7 nights in one context, entering every playing
venue each night. Asserts latch state per plan.gigs (dark venues stay quiet), the cover STAMP per venue
per night (debited once, re-entry free, due again next night), tonight's roster clears per night (no
accumulation), and geo/tex return to a WARMED baseline across >=20 enter/exit cycles — leak proven by a
plateau (a real leak climbs every cycle; warm-up cache residue plateaus). Opt-in --soak warn-gate in
qa.sh (never blocks the tag; the core 6 stay a fast strict run).

Verified seed 20261990: 2 playing (Exchange Hotel + RSL) + 1 dark, 28 cycles, $60 covers, geo/tex flat
across the back half (115/86 -> 115/84), 0 console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:29:43 +10:00
m3ultra
687d23f654 Lane F R15 (v3.0): identity continuity — wire D's tonight-roster into the crowd (ledger #3)
The ped you followed into a venue now turns up in its crowd. D published the seam in R14; F wires the three touches:
- interior_mode.js: crew.spawn({ roster: rosterOf(shop.id) }) — the front crowd slots become tonight's roster
- index.html: rosterOf=(id)=>citizens.tonightRoster(id) into interior_mode; onAdmit=(e)=>citizens.recordVenueEntry(id,e)
  on the queue (each admit relays into the roster); the clear is automatic on the existing setGig(id,false)
- flags_check.py: smoke_continuity — asserts the seam (crowd includes roster-cap, pedIndex in tonightRoster),
  empty-roster injects nobody (shell side of D's byte-identical law), + ledger #5 settled-tris honesty

Verified: 2 queue admits carry into the crowd; empty roster 0-injected; settled interior 71k->182k tris
(C's finding — interior gate is draws <=54, no violation). 0 console errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:19:19 +10:00
m3ultra
146b5f3d2d Lane F R15 (v3.0): retire the R12 single-venue alias (ledger #2)
The compat alias delegating to the primary venue is gone — every read is now keyed by venueShopId.
B swept the cross-lane readers in R14; this migrates F's own tools + the spec, one atomic commit.

- gig_state.js: delete the alpha-shape alias block + the now-unused primaryId/P; update() just ticks all latches
- flags_check.py + gig_shot.py: .venueShopId->venueShopIds[0], .state->stateOf(id), .cover->coverOf(id), .bandName->bandNameOf(id)
- CITY_SPEC \S v3: delete the two alias sentences, add the omitted nightOf(id) to the accessor list

selfcheck 14264/14264 green (base 0x3fa36874, gig 0x4f4a549d); flags_off + smoke_gigs green, 0 warn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 11:14:19 +10:00
m3ultra
2446ae3a5d Lane C R15 (v3.0): verify D's guitar_amp reposition (ledger #4)
D moved the backline plant (66aec0f) to C's §3 corrected pose exactly
(band.js:236 = stage.x + stage.w*0.36, deckY, stage.z - stage.d*0.22).

Verified fresh (port-isolated context, seed 20261990, D's real GigCrew + GLB backline):
- matches §3 both venues; bass clearance 0.87 m (pub) / 0.92 m (rsl) — the R14
  interpenetration (0.29 m) is resolved; on-deck; flanks C's primitive ampStack
  (4.4 m pub / 3.5 m rsl) as a clean up-stage backline; no band/crowd clash.
- rendered pub gig confirms the read (amp up-stage behind the bassist).

LANE_C_PUB §3 updated RESOLVED; freeze otherwise stands. No code change (docs only).
Nothing else blocks on C — F runs the release (continuity wiring, alias delete, week
soak, tour, tag v3.0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 10:49:20 +10:00
m3ultra
66aec0f83c Lane D R15 (v3.0): guitar_amp up-stage per C's §3 ruling (ledger #4)
The R13 backline plant sat down-stage (stage.z + 0.15), 0.29 m from the bass rig
— it interpenetrated the bassist (C's R14 audit caught it). Move it up-stage-right
to C's blessed pose (stage.x + w*0.36, deckY, stage.z - d*0.22): 0.75 m clear of
the bass, behind the front line, flanking C's primitive ampStacks. Pose-only.

Verified: draw/tri delta 0 (same GLB moved — pub 50 draws / ~183k tris, <=350);
?noassets unaffected (amp is fleet-gated dressing → 0 props, band placeholders,
no crash). No other code — continuity + the ratified sit-clip deferral are closed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 10:25:08 +10:00
m3ultra
a0b578477c Lane B round 15: verify hero after A's poster flip + night poster readability (?gigs=1)
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>
2026-07-16 10:11:53 +10:00
m3ultra
35da83c347 Lane A round 15: frontage poster +Z street-face flip (ledger #1) + gig golden re-pin
R14 review found every venue's own-frontage poster on the building's −Z BACK since R13 (~16 m
behind the street face, B measured 15.9 m) — invisible from the street, why queue_night framed no
poster. Ledger #1, A-first (B's hero re-shoot + F's tour hang off this).

- gigs.js buildPosters item 1: flip to the +Z street facade (B's canon: buildings.js facade zf=+d/2
  + venue.js door/queue/camera are +Z) AND ry=lot.ry+π so the printed face points +Z at the queue-side
  camera (else DoubleSide shows a mirrored band name). Proven: pub+rsl frontage posters now sit 0.06 m
  from B's door, printed-face·(+Z street)=1.000. Spine posters untouched.
- Gig golden re-pinned 0x1f636349 → 0x4f4a549d (the round's ONE sanctioned move; posters moved).
  Synthetic golden 0x3fa36874 frozen. §v3 FROZEN marker records the amendment (amendment law).
- selfcheck: the +Z facade is the block-interior side in plan coords, so corner venues (band_room/rsl
  fronting one street with another behind — seed 1 lot#481, 1.58 m from a crossing centreline) seat the
  frontage poster near that street. That's B's building geometry (the door is there too), not a mid-road
  defect — so the no-bitumen assert now EXEMPTS building-bound frontage posters, keeps it for spine
  posters. 400-seed sweep green again: 14264/14264.
- CITY_SPEC §v3 amended (poster prose → +Z facade + ry+π; golden line; frontage/spine carriageway split;
  recorded amendment in the FROZEN marker). LANE_A_NOTES §R15 hands B/F the new golden + a corner-venue
  eyeball note. Convention settled: visible venue face is +Z; selfcheck's −Z 'faces frontEdge' is the
  sim/GLB convention (π-off the visual front, the R13 RY_FLIP ambiguity).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 09:48:17 +10:00
m3ultra
e466491300 Fable (integrator): round-15 instructions — close the v3.0 release (F's carried brief + poster-face fix + amp fix)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 09:21:39 +10:00
m3ultra
9a65f51a88 Lane D R14 (v3.0): identity continuity — the ped you followed is in the crowd
The last charter promise. A per-venue tonight roster (sim.js _venueRoster) of
who entered a gig venue tonight — surge occupants self-record in _enter, queue
admits relay via citizens.recordVenueEntry — is consumed by GigCrew.spawn: the
crowd's front slots BECOME the roster identities (same pedIndex, same height),
seeded strangers fill the rest.

- No golden move: both goldens are plan-gen hashes; each crowd slot is an
  independently-keyed rng stream, so a roster override touches only that slot and
  an EMPTY roster is byte-identical to R13 (verified). Roster heights 1.55-1.95m
  stay inside the no-giants [1.4,2.0] gate. Pure bookkeeping: 0 rng, 0 GPU.
- Roster persists across interior exit/re-enter, bounded, auto-clears on the
  setGig(id,false) transition (per-night). Deduped by stable key.
- queue.js: admitOne() returns {pedIndex,height,key} + fires an onAdmit callback
  (auto-drain AND explicit) so F relays every walked-in punter to the roster;
  _spawnAt stashes the identity. band.js: _make returns pedIndex; members carry
  it for F's continuity smoke; crew.spawn is now null-gig-safe.
- Verified: surge 8/8 + queue 4/4 real identities land in the crowd; empty-roster
  == R13; 7-night x 3-venue soak leak geo0/tex0, roster bounded, no identity
  churn; interior 64 draws <=350 (0 new rigs); ?noassets placeholders, 0 fetch.
- F seam in LANE_D_NOTES: crew.spawn({roster}) + queue onAdmit relay + the
  tonightRoster(venueShopId) accessor.
- Debt #2 (sit clip): investigated, deferred to v3.1 — the clip converts+binds
  (tailnet Sitting_Idle.fbx -> 394KB sit.glb) but a real seated pose is ~1.2m
  stature (fails F's no-giants floor) and needs a _rotWithHips loader + replant
  (shared rig-stack) + an F smoke exemption; not a freeze-week change. SEAT_DROP
  hack kept (reads seated from the money-shot front).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 09:04:06 +10:00
m3ultra
eee60e05a5 Lane B (Streetscape) round 14: v3.0 release — alpha-alias retirement + tour audit + queue_night hero (?gigs=1)
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>
2026-07-16 08:43:22 +10:00
m3ultra
62e38c5df8 Lane C R14 (v3.0 release): venue audit + docs freeze + guitar_amp ruling
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>
2026-07-16 08:40:42 +10:00
m3ultra
a3911a4590 Lane A round 14: v3.0 release — 400-seed district invariant sweep + CITY_SPEC §v3 frozen
Release round: harden + freeze, no new systems. No golden moved (synthetic 0x3fa36874, gig
0x1f636349 both re-verified frozen); selfcheck.js is the only code touched, so no seeded generation
stream gained a draw (release-round law).

- selfcheck.js: factored the district checks out of gigSuite into districtInvariants(plan,label)
  (behaviour-preserving — hero-seed gigSuite runs byte-identical), then added a 400-seed synthetic
  sweep + the large edge seeds asserting the full district contract each (2-4 venues, >=1 pub, never
  the openLate shop, no band twice/night town-wide, per-venue 4-6 nights, every poster off the
  carriageway). Asserts the seeded count spans {2,3,4} across 400 seeds (146/121/133 — range is
  exercised, not pinned). osm graceful placement: katoomba (19 shops, no warehouse district) still
  lands 2-4 valid venues incl. a pub for every hero seed. Poster check kept at roadWidth/2 (a literal
  poleOffset compare would false-fail corner posters); added -1e-6 epsilon on the strict boundary.
  ALL GREEN 14264/14264 in ~0.7s.
- CITY_SPEC §v3: final wording pass, marked FROZEN at v3.0 (round 14) with a v2-style marker + an
  explicit carve-out for F's pending alias-line deletion. Fixed the roadWidth prose (full carriageway
  width, not 'half-corridor'). Genres final (pubrock/grunge/covers).

Coordination: the R12 single-venue alias line stays in §v3 for F to delete atomically with the
gig_state.js getters (debt #1) — deleting now would be doc-ahead-of-code (alias still live) and race F.
Flagged to F that the runtime block omits nightOf(id); to B that venue.js:228 is a 2nd bare-string
site. Verified: mutation-tested the sweep (non-vacuous — catches 5-venue/7-night/on-road violations)
+ adversarial pass (goldens frozen, freeze matches code, deterministic).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 08:36:31 +10:00
m3ultra
55f6698fb2 Lane E R14 (v3.0 release): provenance freeze + doc-consistency fixes
Provenance close-out for the v3.0 tag. Verified via a 6-agent inventory+audit workflow
(both adversarial audits PASS, 0 blockers) cross-checked against glb_stat/ffprobe/manifest.

- LANE_E_NOTES: v3.0-FROZEN provenance table + full audio(28)/GLB(38)/skins(96)/packs(3)
  inventories; by-design notes + v3.1 deferrals (street_bin decimation).
- AUDIT.md: add R13 gig-layer finalization section (14k decimation, _hi published, gigKey
  rename + 2 beds, depot publish done) — ledger was stale at R12.
- manifest glb_law string: state the documented <=8k-hero / <=14k-instrument tiers so the
  frozen contract is self-consistent (regenerated; 1-line diff, Gate 3 still 0/0).
- gen_audio: roomtone-video gain 0.3 -> 0.35 to match the shipped manifest.

Gate 3 GREEN; publish.py --verify clean; 0 quarantine assets in manifest; goldens unmoved
(synthetic 0x3fa36874, gig 0x1f636349). No new synthesis (genres final); no poster templates
(no ask from B).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 01:18:40 +10:00
m3ultra
f8ab837985 Fable: R14 kickoff rulings recorded (push done, flag stays opt-in, genres final) + gitignore local session files
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 00:59:42 +10:00
m3ultra
e4e16c34ed Fable (integrator): round-14 instructions — v3.0 release round
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 00:56:00 +10:00
m3ultra
a358c5d9ef Lane F R13 (v3.0-beta, the district): per-venue gig state + walla/applause + queue wiring; qa --strict 6/6
Wires A–E + D's district together and fires it. Seed 20261990 → "Boolarra Heads": 3 venues, 2 playing
tonight (The Exchange Hotel pub gig-pubrock + an RSL gig-covers, one dark), Screaming Utes $10 on the door.

- gig_state.js → PER-VENUE latches off the shared procity:segment spine (one per venueShopId); all three
  hard-won R12 laws kept. New runtime surface window.PROCITY.gigs.byVenue + onOf/openOf/gigOf/coverOf/
  bandNameOf/paidOf(id) + markPaidOf/venueShopIds; the R12 single-venue alias kept for one round.
- interior_mode.js: crowd-walla rides the interior tone layer under the live band bed while `on`; an
  applause sting fires once on the on->done edge. DELETE the GIG_BED bridge — debt #1, and it was a LIVE
  BUG: E renamed pubrock-live->gig-pubrock, so the bridge (gig-pubrock->pubrock-live) pointed at a dead
  key => the band would have mimed in silence. room.audio.gigKey (already the manifest key) feeds directly.
- index.html: per-venue cover charge (a night at two venues is two covers), concurrent per-venue setGig
  surges, and the outdoor VenueQueue lifecycle (D shipped the class + left the street-side seam to F:
  spawn at doors off B's queueZoneFor, drive each frame, dispose by done), exposed as queueCountOf(id).
- interior_scale_check.py: human-size assert now measures STATURE (crown-foot, platform-independent);
  world-crown ceiling-clip assert kept as its own line (debt #6).
- flags_check.py smoke_gigs -> THE DISTRICT: band->4, per-venue loop (every gigKey resolves across 3
  genres, crowd <= its own watchPoints, no-giants by stature), street budget at the busiest venue block,
  the queue assert; plus the R12 determinism/cover/noassets/flags-off arms.
- CITY_SPEC: pin the window.PROCITY.gigs runtime surface. gig_shot.py -> r13 interior + venue_night shots.

qa.sh --strict GREEN 6/6, 0 warn. Interior 63 draws/35k tris; street @ venue block 121 draws/51k tris;
band+crowd stature 1.61-1.81 m under a 4 m ceiling; flags-off fingerprint 0x3fa36874 unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 00:22:03 +10:00
m3ultra
fefbb4b806 Lane D R13 (v3.0-beta): 4-piece + instruments, outdoor queue, multi-venue surge, RY fix
- RY audit (debt #4): the ped GLB fleet's visual front is +Z but the whole
  system assumed -Z (sim heading math, C's pose ry, placeholder, impostor).
  Fixed at the source (rigs.js buildFigure normalises every rig to -Z front)
  and dropped band.js RY_FLIP. Corrects keepers/browsers (faced the back wall)
  and streamed walkers (moon-walked): 223/223 gig + 188/188 flags-off now face
  travel. Visual only, no golden move. keepers.js/placeholder.js/impostor.js
  unchanged (fixed for free). Canonical convention -> LANE_D_NOTES for C.
- Instruments (debt #2): E's manifest GLBs swap over the primitives async
  (placeholder-persists, fleet-gated -> 0 fetch under ?noassets), guitar/bass
  held, mic + kit planted, guitar_amp dressing.
- Drummer (debt #3): 4-piece, seated at C's drums pose (sink + kit occlusion;
  reads from the front/crowd POV - a sit clip is the polish).
- Outdoor queue (new queue.js): seeded 2-6 line at the frontage, drains on
  admitOne() + auto-drain, consumes B's queueZone or a frontage-hugging door
  fallback. F wiring seam documented in LANE_D_NOTES.
- Multi-venue surge (sim.js): setGig -> Set of concurrent venues.
- Interior gig 56 draws <=350; ?noassets+?gigs placeholders, silent-and-fine.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 00:00:05 +10:00
m3ultra
5dac2cac5a Lane E R13: publish decimated instruments + _hi originals to depot
John OK'd direct publish. Pushed the 5 base instruments (14k) + 5 _hi hi-poly originals
via the passwordless tailnet ingress (this box is allowlisted). Public digalot.fyi now
serves the 14k bytes (amp 5.9MB->1.3MB) + the _hi originals; -70% decimation win is live
in production. _published.json 33->38; validate_manifest --depot GREEN. Gate-3 flag cleared.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:12:48 +10:00
m3ultra
46127c7e95 Lane B (Streetscape) round 13: v3.0-beta the district — N-venue frontage + night pass + posters + queue zone (?gigs=1)
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>
2026-07-15 23:11:10 +10:00
m3ultra
82b711f962 Lane C R13 (v3.0-beta, the district): band_room + rsl archetypes, 4-piece band, RY audit (?gigs=1)
- 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>
2026-07-15 23:05:03 +10:00
m3ultra
bf98b41b16 Lane E R13 (v3.0-beta): gigKey rename + grunge/covers beds + instrument decimation
- debt #1: the manifest music key IS the gigKey, always gig-<genreKey>. Renamed
  pubrock-live -> gig-pubrock (files + gen_audio + build_manifest); old files deleted.
  B/F switch readers, F deletes the GIG_BED bridge (both fail soft to silence til then).
- two new gig beds: gig-grunge (band_room, quiet-loud dynamic) + gig-covers (RSL, mellow
  organ-led); procedural/seeded/loopable/$0. New organ() + grungechord() synth helpers.
- decimate the 5 instrument GLBs to 14k tris each (was 43-96k; fleet 236k->70k, -70%) via
  collapse (thin features survive); _hi hi-poly originals kept for depot; thumbs re-rendered.
- manifest regen (validates 0/0 incl --depot); app boots clean flags-off / ?gigs=1 (3-venue
  district, all 3 beds resolve) / ?noassets=1&gigs=1 (0 audio+GLB fetches).
- depot re-publish (14k bytes + _hi originals) gated on John's OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:03:14 +10:00
m3ultra
6fba79a1cb Lane A round 13: v3.0-beta the district (?gigs=1) — 2–4 venues, week schedule, town-wide posters, verge fix
Publishes the multi-venue plan.gigs interface C/D/B/F hang off (half-day handshake, A first).

- pickVenues: seeded 2–4 shops converted in place → pub (spine end) / band_room (warehouse
  fringe) / rsl (off-spine); 4th = 2nd pub at far end. Registry gains weight-0 band_room+rsl
  kinds + venueKind/genreKey/placement. Never the openLate landmark; osm-safe fallbacks.
- gigKey contract (debt #1): gigKeyFor(genreKey) => 'gig-'+genreKey, the single exported
  genre→bed mapping. No table anywhere; F deletes the GIG_BED bridge.
- plan.gigs goes district: 7 nights × every venue, each plays a seeded 4–6 (dark reads true);
  cover skewed by kind; no band plays two venues on one night; custom names spread night-major.
- plan.posters goes town-wide: tonight's playing venues each get frontage + seeded spine run.
- Verge fix (debt #5): new corridor law roadWidth/vergeBand/poleOffset(edge) in registry.js
  (road-vs-verge split of edge.width, published as functions ⇒ base goldens frozen). Posters
  seat on the verge, never bitumen; selfcheck asserts no poster on a carriageway.
- registry pub.interior 'band_room'→'pub' (unread field; avoids collision with band_room type).

Gig golden re-pinned 0xa6ae5a5e→0x1f636349 (multi-venue changed output; in-commit per amendment
law). selfcheck ALL GREEN 3273/3273; scaffold_check + consistency GREEN; flags-off byte-identical.
CITY_SPEC §v3.0-beta + LANE_A_NOTES §Round 13 updated in this commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 22:35:05 +10:00
jing
79852ca220 Fable (integrator): round-13 instructions — v3.0-beta, the district
v3.0-alpha re-verified green (qa.sh --strict 6/6, 0 warn) on the shipped tree. Round 13
opens the beta: 2-4 venues (pub/band_room/rsl), full week schedule, posters town-wide,
the outdoor queue, walla+applause, night-readability pass — all behind ?gigs=1.

All six R12 debts assigned: gigKey contract (manifest key IS the gigKey, gig-<genre>),
D wires E's instrument GLBs, the drummer (band goes 4-piece — John may veto), the
RY_FLIP facing audit, A's poster verge offset, F's stature-gate hardening.

Three items for John, only the depot-publish OK blocks anything.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 21:30:01 +10:00
jing
2498fdc892 Lane F R12: wire the v3.0-alpha gig layer (?gigs=1) — state machine, cover charge, band+crowd, gig audio
F last: five landed lanes → one Friday night. Seed 20261990 → The Thornbury Hotel,
tonight SCREAMING UTES, $10 on the door. qa.sh --strict GREEN 6/6.

- gig_state.js (new, F-owned): quiet → doors (DUSK) → on (NIGHT) → done (DAWN) → quiet.
  Rides lighting's procity:segment event (a poll only sees the segments it samples, and
  missed the night roll entirely); `state` is a getter because B's audio reads it from its
  own rAF while the player is inside a shop.
- ?gigs=1 seam: custom_bands.json fetched in the bootstrap (no fetch flag-off or ?noassets)
  → generatePlanFor(seed, src, {gigs:true, customBands}). 7 of John's 10 names fill the week.
- Cover charge on the R8 buy seam, zero new UI: paid debits once with a toast, re-entry the
  same night is free, broke → polite knockback, free nights walk straight in.
- interior_mode: opts.gig → C's gigKey; D's GigCrew (band 3 + crowd 8, 3 dancing) at C's
  stage/watch points; both disposed with the room (leak-free over 4 cycles).
- Cross-lane fix at the glue: C emits gigKey 'gig-pubrock', E shipped the bed as
  'pubrock-live' — unresolved the pub plays to a silent room and nothing errors. Bridged
  here; C/E/Fable owe CITY_SPEC a contract line. Details + 2 more findings in LANE_F_NOTES §12.
- smoke_gigs (16 gates): schedule determinism, band==3, crowd ≤ watchPoints, dance mix, bed
  resolves, ≤350 draws (47 rig / 171 placeholder), no-giants by STATURE (the band stands on a
  0.32m deck, so world-crown fails a correct band), cover ruling, ?noassets+?gigs.
  Flags-off regression gains a v3 arm: no state machine, no plan.gigs, no pub, no venue geo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 21:09:56 +10:00
m3ultra
f0a0a99207 Lane B (Streetscape): round-12 v3.0-alpha — venue frontage + posters + muffled-gig spill (?gigs=1)
- 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>
2026-07-15 20:15:40 +10:00
m3ultra
888335d633 Lane D round 12: gig band + crowd + patronage surge (?gigs=1)
v3.0-alpha — Friday night at the pub. New web/js/citizens/band.js (GigCrew):
- Band trio on C's stage.bandPoses (deckY), distinct fleet peds (seeded per gig), each with a
  primitive instrument on the chest (guitar/mic/bass; E's GLBs drop in via opts.instrumentFor).
- Crowd (<=8) at C's watchPoints on the gate-protected spawnRig path: dance:false = weight-shift
  idle, dance:true = bounce/sway/step with seeded phase (no metronome).
- Deterministic from citySeed; placeholder crew under ?noassets.

sim.js: setGig(venueShopId, on) gig-night surge — patronage pulls peds from further (GIG_RANGE)
and ducks in harder (GIG_SURGE) at the venue; occupants drain at close per A's closing-time ruling.
Guarded by _gigVenue==null so gig-off is byte-identical (prime flag law; goldens unmoved).

Verified standalone (A withGigs + C buildInterior + D): band 3, crowd 8, dancing 3, all 11 figures
human-sized (1.60-1.83m under a 4.0m ceiling; R10 no-giants holds), band faces audience + crowd
faces stage, deterministic, leak-free (8 cycles, 0 delta). Crew ~40 draws. Surge: venue occupancy
1 -> peak 5, identity stable. Shot: docs/shots/laneD/r12_gig_night.jpg.

Flag for C/F: band.js flips C's watchPoints/bandPoses ry by pi (RY_FLIP) — the fleet mesh's visual
front is local +Z, not the -Z the comments assume. Remove RY_FLIP if C re-fronts the gig poses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:49:07 +10:00
m3ultra
7795780336 Lane E R12 (v3.0-alpha gig layer): 5 instruments + 4 posters + 3 gig audio
Instruments (MODELBEAST flux_local concept -> trellis_mac -> normalize):
electric_guitar, bass_guitar, drum_kit, guitar_amp, mic_stand -> manifest
fittings + thumbs, published to the tailnet depot. All 5 reconstructed
cleanly (thin mic-boom + cymbals survived); heavy tris (30-96k, amp the
outlier) accepted like the R3 props. gen_props.py gains --batch;
gig_instruments.json + gig_norm_batch.json + _gig_results.json.

Posters (flux_local, gen_skins.py --posters): poster-xerox/screenprint/
grunge/retro -> skins.poster with nameZone for band-name overprint, blank
name-band (no baked text) like blank-signboard facades.

Gig audio (procedural, gen_audio.py): music-pubrock-live (original 90s
pub-rock riff), ambience-crowd-walla, sfx-applause -> manifest audio,
flagged gig:true for F. Pack now 26 assets, 9.1 MB of 25.

build_manifest reads _gig_results.json + emits skins.poster + gig audio;
validate_manifest green (--depot 0 err, all live). Provenance in AUDIT.md
(section Round 12); README + E-progress updated. Touched no other lane's
files. F owns the v3.0-alpha tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:44:48 +10:00
m3ultra
05e020e3b8 Lane C: round-12 pub venue — archetype + watchPoints + audio.gigKey (?gigs=1)
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>
2026-07-15 18:59:48 +10:00
m3ultra
acf734a1e5 Lane A round 12: v3.0-alpha gig layer (?gigs=1) — venue, plan.gigs, band names, closing-time debt
Publishes the gig interface the whole round hangs off (A runs first). Everything is
behind ?gigs=1 as a POST-HOC augmentation (gigs.js withGigs, applied by the selector),
so generatePlan is untouched and all v2 goldens stay frozen (synthetic 0x3fa36874, osm
melbourne 0x34cfdec0, katoomba 0x0f652510). Source-agnostic (synthetic + osm).

- Venue: one 'pub' per town — a spine-end plain shop converted in place (keeps lot
  id/geometry, enterable), shop.venue=true, never the openLate landmark. Registry gains
  a weight-0 'pub' type (interior:'band_room' for Lane C) → never auto-placed → base
  plan byte-identical.
- plan.gigs: 7 nightly {gigId,venueShopId,bandName,genreKey:'pubrock',night,startSeg:5,
  endSeg:5,cover}; cover ~half free / half $2-$10 (F charges at the door).
- Band names: bandName(seed) generator (90s pub-rock) + OPTIONAL web/assets/custom_bands.json
  drop-in (priority into the pool; absent → pure generator, no fetch under ?noassets).
- plan.posters: ~6 seeded {id,gigId,x,z,ry} for Lane B.
- Closing-time debt paid: isOpen(shopOrHours,hour) exported (half-open law as code, D consumes).
- map.html?gigs=1: venue ring + poster pins + gig panel line. Flags-off unchanged.

Self-check ALL GREEN 3074/3074 (gigSuite ×2 sources, flags-off≡base, gig golden
0xa6ae5a5e). qa.sh --strict GREEN 6/6. Verified in-browser both modes. CITY_SPEC v3
section + LANE_A_NOTES handshake for C/D/B/F. Atomic pathspec commit (shared-tree race).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:33:53 +10:00
m3ultra
22a0741ad1 Fable (integrator): round-12 instructions — v3.0-alpha, one pub end-to-end
R11 reviewed: clean audio round, v2.1 tagged+pushed by F, E's pack fully procedural
(numpy synthesis, 23 assets, 8.7MB, $0). R12 opens the venues epoch behind ?gigs=1
with John's three charter rulings encoded: crowd = stand-and-watch + seeded ~1/3
dancing; events = mixed free/paid (seeded cover $0 or $2-10, wallet door charge,
knockback on skint, no re-charge same night); band names = generator + optional
web/assets/custom_bands.json drop-in (asset-law compliant, deterministic given
seed+file). A publishes plan.gigs first; C watchPoints; D band trio + crowd;
E instruments/posters/pub-rock bed; B lit frontage + muffled spill; F gig state
machine + door charge + smokes + v3.0-alpha tag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:32:34 +10:00
m3ultra
8c275c711b Lane F R11: wire interior audio beds + audio smokes + gate scope
Interior audio (interior_mode): enter -> PROCITY.audio.playInterior(room.audio) with Lane C's
{musicKey,toneKey} (fade in), exit -> stopInterior() (0.7s fade). Guarded/no-op when
muted/noassets/pre-gesture -- silent-and-happy.

New smoke_audio gate (flags harness, fresh Chromium per the R10 standing law): pre-gesture silence
(ctx not unlocked), 0 boot errors, ?mute=1 muted, ?noassets=1 zero audio fetches, enter/exit
AudioNode leak-free (12 cycles, 8 shops with a music bed, live sources bounded at 5). Gesture via
keyboard -- a mouse-click gesture tripped PointerLockControls in headless.

scaffold_check: scoped the Math.random generation-ban to exempt runtime FX PLAYBACK
(web/js/world/audio.js) -- Lane B's footstep SFX variant/gain jitter is transient, not world
generation (which shop plays which bed is seeded upstream in interiors.js). Noted to B.

Soak with audio on PASS (heap 48MB stable, 0 errors, no drift). qa.sh --strict GREEN 6/6.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 17:13:19 +10:00
m3ultra
f7dd44f55a Lane B (Streetscape): round-11 audio — WebAudio engine (street side)
- 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>
2026-07-15 16:00:31 +10:00
m3ultra
89f278b603 Lane C: round-11 audio contract — room.audio on buildInterior
buildInterior returns room.audio = { musicKey, toneKey }, seeded per shop: keys into Lane E's manifest.audio (interior music bed + room-tone). Lane F's interior_mode plays it, B's audio.js resolves keys->files. Keys not files: buildInterior stays synchronous + asset-free; silence on missing/mute/noassets (house audio law).

Maps mirror the manifest per-type types arrays: record/milkbar/video/dept/arcade always play their bed; other types room-tone-only except a seeded ~1-in-3 general radio (the 'general'-tagged milk-bar bed).

Verified 9 types x 8 seeds: 0 bad keys, 0 nondeterminism, all keys resolve + match manifest type membership, deterministic per shop. Contract + F wiring: docs/LANES/LANE_C_AUDIO.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 15:46:58 +10:00
m3ultra
be9f967d19 Lane E R11 (audio): procedural audio pack — 23 assets, free/on-device
gen_audio.py: a numpy synthesis engine (osc / ADSR / filters / reverb /
seamless-loop crossfade + note sequencer + drum synth). Renders 6 ambience
beds (street day/night, rain, 3 interior roomtones) + 13 sfx (doorbell,
door, till, record-riffle, toast, tram bell/rumble, 6 footsteps) + 4
instrumental 90s music loops (record-shop, milkbar, video-synth, arcade)
-> web/assets/audio/ as OGG/Opus + M4A/AAC. 8.1 MB of the 25 MB budget.

Tool = 100% procedural synthesis (not a neural model): $0, deterministic/
seeded, perfectly loopable, parody-safe by construction. Documented in
README (§ audio) + AUDIT.md provenance.

manifest audio:{ambience,sfx,music} — file + m4a fallback + loop + gain;
interior roomtone/music carry types[] (seed-pick per shop, like facades);
footstep is {surface:[variants]}. build_manifest.py builds it,
validate_manifest.py checks it. qa.sh --strict green (audio 23, 0 err).

Verified technically (peaks <= -0.4 dBFS, all loops seamless, durations)
via spectrogram sheet + numeric — subjective ear-check is John's/F's.

E leads the audio round; F owns the v2.1 tag + push. Not pushed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 14:50:15 +10:00
m3ultra
4b4e040032 Fable (integrator): v3 epoch charter — venues & gigs (John's pick)
Epoch decided: venue district + gig system. Charter defines the vision (seeded Friday
night: posters -> queue -> band room -> crowd with identity continuity), per-lane
ownership (A gig truth in plan, B venue nightscape + night-readability polish, C band-
room archetype + watch points, D band/crowd/queue rigs, E instruments/posters/genre
beds, F gig state machine + tags), three phases (alpha = one pub end-to-end), carried
ground rules, and three non-blocking questions for John. Round 11 (audio) is the
on-ramp; round 12 opens v3.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 14:18:26 +10:00
m3ultra
aa322365a9 Fable (integrator): v2.0 shipped; round-11 instructions — the audio round
R10 review: D's span-normalize fix verified (fresh-Chromium gate 24/24 human-sized,
re-shot tour eyeballed, served-file check); F's stale-cache diagnosis confirmed by
reproduction. v2.0 tagged at 9b1c54e and pushed. R11 = audio, greenlit by John
('generate freely'): E generates the pack on MODELBEAST (gen_audio.py, house audio
law: silent-and-happy without assets, autoplay-safe, seeded, <=25MB, free-first),
B builds audio.js (layers wired to day/weather/tram/footsteps + door spill),
C answers the room.audio contract, F wires interiors + smokes and tags v2.1.
A + D rest. v3 epoch pick pending John (editor / venues+gigs / multiplayer).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 14:08:32 +10:00
m3ultra
9b1c54ea81 Lane F R10: verify giant-rig fix + re-shoot tour + re-frame night_crowd
Verified Lane D's R10 buildFigure span-normalize fix: qa.sh --strict GREEN 6/6 incl. the new
no-giants scale gate (24 interior figs / 6 shops all crown 1.4-2.0m, under-ceiling). The 3.83m I
first measured live was a STALE ES-module cache in a day-old browser tab, not a regression
(served rigs.js + fresh-chromium gate both correct).

Re-shot the v2 tour on the fixed tree: browsers.png now shows human-sized figures (browser at the
rack + keeper at the counter). night_crowd.png re-framed to a readable clean-night "lit VIDEO REGAL
amid CLOSED town" (pulled out of the rain group; reuses night_neon's tighter dist-12 pose).

Honest finding: night_crowd has no visible street crowd and can't without new work. Lane D's night
patronage parks ducked-in patrons hidden INSIDE the shop (they are the interior browsers), and this
seed's video shop is a low-traffic corner (tested: 0 patronage / 0 visible at night). Flagged for D;
a visible outdoor night queue is a v3 mechanic. ~20fps in night captures is a headless software-GL
artifact (scene is light: 128 draws / 65k tris).

Full-default soak PASS (heap 54MB stable, no perf drift, 0 errors). Tour README updated with stable
v2 filenames. v2.0 annotated tag staged separately (push held for John — public release + the
night_crowd caveat on his flagged money shot).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:56:23 +10:00
m3ultra
3432fccd1f Lane D round 10: fix interior giant rigs + no-giants QA gate
R9 blocker: interior rig figures were ~2x too tall (keeper crown 3.83m in a 3.4m room,
clipping the ceiling). Root cause in rigs.js buildFigure: it normalised scale by height/headY,
where headY is the head bone's world Y in BIND POSE — but the Mixamo skeleton origin is the hips
(~mid-body), so headY is head-above-hips (~half the standing height), not feet->crown. Every rig
came out ~1.83-2.0x too tall. (The head does NOT move when posed — bind crown 3.209m vs idle
3.205m — so it's a hips-relative measure, not an animation issue.)

Fix: normalise by the feet->crown span (headY - minY, both already computed). buildFigure(rig, h)
now lands the crown at exactly h above planted feet. Fixes keepers, browser rigs, near-tier street
rigs AND the impostor bake (all ride buildFigure). Verified: all 19 fleet rigs crown==1.75m; live
keeper 3.83m -> 1.82m; determinism + dispose-leak soak unchanged.

Regression guard (required): new tools/qa/interior_scale_check.py (Playwright) enters a sample of
shops, injects browser rigs at browse points, asserts every interior fig crown in [1.4,2.0]m AND
< room dims.H AND feet planted. Wired into tools/qa.sh --strict (run_gate => a giant fails qa).
Proven bidirectional: PASS on the fix (24 figs/6 shops), FAIL on a reintroduced giant. Full
qa.sh --strict: 6 passed, 0 failed.

Re-shot laneD/r10_browsers_fixed.jpg. Figures human-sized relative to doors/fittings: yes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:01:54 +10:00
m3ultra
8bd4676593 Fable (integrator): round-10 instructions — interior giant-rig blocker, v2.0 tag pulled
Round-9 review: engineering landed but the headline feature is visibly broken — interior
rigs (keepers + browsers) render ~2x room scale, heads through the ceiling. Verified live:
head bone at world Y=3.83m in a 3.4m room vs requested 1.58-1.92m. Root cause narrowed to
bind-pose head measurement in rigs.js buildFigure (raw headY 82 at bind vs 180 animated,
~2.2x underestimate -> giant after normalize). Visible in D's own r9 acceptance shot and
F's tour 'browsers.png'; neither lane flagged it. Local v2.0 tag deleted (never pushed;
origin still ends at v2.0-rc). R10: D fixes pose-aware + adds a head-height QA gate, F
re-shoots browsers + night_crowd and re-tags v2.0 on the fixed commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 12:12:55 +10:00
m3ultra
cb3aed196a Lane F R9 F3+F4: v2.0 tour (11 shots) + full-default & all-on soaks + docs freeze
F3: tools/v2_tour.py shoots 12-shot-class tour across flag-groups → docs/shots/v2_tour/ (11 shots,
all un-letterboxed 1280x720) incl. the rain-verandah money shot (night rain + winmap-lit open video
shop + CLOSED dark neighbours), browsers-in-a-shop, dig-real, katoomba, tram_stop + contact sheet.
soak.py gained --flags; full-default soak PASS (37 chunks/20 shops/heap stable/0 errors/leak-free)
and all-on soak (winmap+dig+stock=real+weather=rain+tram) PASS identically.

F4: F-progress round-9 section + FINAL v2 flags table (roster/patronage default-on; dig/winmap/
stock/weather/plansrc/tram/noassets opt-in; goldens frozen). LANE_F_NOTES v2.0 freeze note. CityPlan
v2 contract (A's CITY_SPEC freeze) validated live: selfcheck 1727/1727 + goldens. qa.sh --strict GREEN 5/5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:57:11 +10:00
m3ultra
5a24f8aa52 Lane F R9 F1+F2: interior presence + tram + buy-anywhere wiring; harness graduated + new smokes
Wiring (F owns index.html + interior_mode.js):
 • Interior presence (C->D->F seam): occupancyOf closure -> interior_mode spawns browser rigs at
   C's room.browsePoints (one per patronage occupant, cap 3); freed by exit()'s keepers.disposeAll.
   Door points now carry shopId for D's occupancy truth.
 • Tram (Lane B, ?tram=1): createTram + update in loop (2 draws, non-blocking).
 • Buy-anywhere (Lane C C2): E aimed at a book-spine/toy-box buyMesh buys over the same wallet
   (collapseBuyItem + toast); preload book+toy packs too. Records keep the dig.

Harness: graduated buy-v0 / patronage / book-toy stock warn->STRICT (katoomba golden already
strict). New warn smokes: interior presence (browsers==min(occ,3), dispose clean), shelf-buy
(book spine bought, cash drops), tram (present). Book-stock check now counts isStock OR buyMesh
(C2 tags book spines buyMesh, not isStock). flags_check GREEN 0/0; qa.sh --strict GREEN 5/5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 11:42:44 +10:00
m3ultra
16c4450cd9 Lane B round-9: v2 tram (?tram=1) + tour bookmarks + rain-drop polish
- 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>
2026-07-15 11:09:41 +10:00
m3ultra
23c0667dca Lane E round 9 (E1+E2): VRAM/texture audit + half-res book/toy atlases
E1 memory audit: measured all texture sources (decoded RGBA+mips). Resident VRAM
~240MB default boot / ~420MB worst case (all flags + all shop types); stock packs
the swing. Cheap win: half-res'd book+toy atlases (quick pull-cards, not the deep
record dig — covers verified legible) → stock VRAM 323->181MB, no index/UV change,
re-published to depot. Verdict: fine to ship v2.0; flagged stockpack cache-cap (C)
+ KTX2/Basis (4-8x) for v3. E2 hygiene: validate --depot 0 err, pack-QA 3/3,
provenance-drift clean (27 live), 0 orphan atlases. Numbers + verdict in AUDIT.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:59:22 +10:00