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>
This commit is contained in:
parent
62e38c5df8
commit
eee60e05a5
@ -1,5 +1,76 @@
|
|||||||
# LANE B — NOTES (measured)
|
# LANE B — NOTES (measured)
|
||||||
|
|
||||||
|
## Round 14 (Fable's ROUND14 → Lane B) — v3.0 RELEASE: alias retirement + the tour audit
|
||||||
|
|
||||||
|
Release round — no new systems. Three B files touched (`audio.js`, `venue.js`, `dbg.js`); no world
|
||||||
|
geometry, no rng, goldens frozen (`0x3fa36874` synthetic, `0x1f636349` gig — neither moved). Verified
|
||||||
|
fresh Chromium, seed 20261990, `?gigs=1`.
|
||||||
|
|
||||||
|
### 1. Alpha-alias readers dropped (debt #1 — B first; **F unblocked**)
|
||||||
|
The R12 `window.PROCITY.gigs` scalar alias (`.state/.on/.venueShopId/.cover/.paid/…`) is retired this
|
||||||
|
round. B's readers removed:
|
||||||
|
- **`audio.js`** `venueGigState()` — dropped the alias hop (`g.venueShopId === shopId → g.state`).
|
||||||
|
Now byVenue-only + the clock fallback: `g.byVenue[id]` → else `plan.gigs` night-0 vs the segment.
|
||||||
|
- **`venue.js`** `stateGetter()` — dropped the bare-string arm; reads `gigStates.byVenue || gigStates`
|
||||||
|
(F passes `gigState.byVenue`, confirmed at `index.html:379`). Seed call is now `update(null)`.
|
||||||
|
|
||||||
|
Verified live: F's `gigState.byVenue` reads `{116:'on', 404:'on', 490:'quiet'}` at NIGHT (pub + RSL
|
||||||
|
playing, band_room dark); passing it to `venue.update()` lights the marquee with **no string arm**, and
|
||||||
|
`audio.js` resolves each venue's `gig-<genreKey>` with **no alias hop**. Audio engine loads `live`.
|
||||||
|
|
||||||
|
**→ Lane F (you can now delete the alias):** an alias-surface sweep (all of `web/js/**`, `index.html`,
|
||||||
|
`tools/**`) confirms **CROSS-LANE CLEAN** — no A/C/D/E file reads the scalar alias (interior_mode.js
|
||||||
|
uses `onOf()/gigOf()`; sim.js uses shell-driven `setGig`). The only remaining alias readers are **your
|
||||||
|
own 20 lines** in `tools/flags_check.py` + `tools/qa/gig_shot.py` (`.venueShopId`×12 → `venueShopIds[0]`
|
||||||
|
or an explicit id; `.state`×5 → `stateOf(id)`; `.cover`×2 → `coverOf(id)`; `.bandName`×3 →
|
||||||
|
`bandNameOf(id)`; `gig_shot.py:81` already prefers `stateOf(id)`). Delete the alias getters at
|
||||||
|
`gig_state.js:141–151` + migrate those tool lines in the same commit; `!!P.gigs` existence checks keep
|
||||||
|
working (the per-venue machine still exists). CITY_SPEC §v3 runtime block loses the alias line (with A).
|
||||||
|
|
||||||
|
### 2. Bookmark / tour audit under `?gigs=1` — **all clean, no pose fixes**
|
||||||
|
All 19 bookmarks (16 v2 + `venue_night` + `district_posters` + new `queue_night`) resolve, frame
|
||||||
|
**un-letterboxed**, **0 page errors**, ≤300 draws. The district's in-place venue conversions hijacked
|
||||||
|
**no** bookmark: `night_neon`→"Video Regal" (openLate is never converted), `dig_real`→"Retro Groove"
|
||||||
|
(a real record shop survives — multiple per type). Framing eyeballed clean on the tour spread:
|
||||||
|
`street_noon`, `venue_night`, `queue_night`, `tram_stop`, `district_posters`, `night_neon`. **No dbg.js
|
||||||
|
pose changes were needed** beyond adding `queue_night`.
|
||||||
|
- **Measurement gotcha (re-confirmed):** `DBG.shot` teleports, so shooting many bookmarks in sequence
|
||||||
|
leaves orphan chunks that inflate tris on later shots (saw 238k on `patronage_door`; **42k** on a
|
||||||
|
fresh load / shoot-twice-to-settle). Shoot from a clean load, or twice, for the true per-frame count.
|
||||||
|
- **Observation → Lane D / Fable (not a Lane B fix):** `tram_stop` is a stable **~293k tris** — real,
|
||||||
|
from close-range full-detail GLB ped rigs on the footpath (framing is fine). It's not a venue block
|
||||||
|
(F's tri gate measures at the venue block, ~64k), so it likely doesn't trip the gate, but it exceeds
|
||||||
|
the 200k reference for a tour shot; worth a look if a close ped shot lands in the release set.
|
||||||
|
|
||||||
|
### 3. `queue_night` — John's release hero (`dbg.js`)
|
||||||
|
New bookmark `queue_night` (seg 5 / NIGHT / 'on'): a close 3/4 on the pub door, biased to the venue's
|
||||||
|
`+right` (the queue side). New `poseForVenueQueue()` recomputes venue.js's frontage geometry from the
|
||||||
|
pub lot: `DIST 7 m` out on the street, `SIDE = mw/2 + 2.2 m` to the queue side, eye 2.2 m, looking at
|
||||||
|
the door lifted to y2.7 (catches the marquee). Verified: frames marquee + window glow + streetlamp
|
||||||
|
pools + the queue. **The queue is spawned by the shell's live rAF loop** (`index.html:383` builds D's
|
||||||
|
`VenueQueue` on `openOf(id)`), so F's `gig_shot.py` must drive it **live** (the automation rAF is
|
||||||
|
throttled — I confirmed the pose + D's line by manually spawning `VenueQueue` at the pub queueZone: 2
|
||||||
|
punters seat at the door, facing it).
|
||||||
|
- **→ Lane A (blocks the hero's poster):** `queue_night` frames door + marquee + queue, but **no poster
|
||||||
|
lands in the close frame** — the pub's own-frontage poster is still on A's local **−Z** (the BACK
|
||||||
|
wall, `gigs.js buildPosters` item 1 `-sin,-cos`; measured 15.9 m from the +Z street facade), and the
|
||||||
|
nearest spine poster is 53 m away. Per Fable's "fix poses, don't touch world code," B did **not**
|
||||||
|
work around it. **Flip item 1 to `+sin,+cos`** and the frontage poster seats by the door — in the
|
||||||
|
existing `queue_night` frame with no pose change. (Re-flagged from R13; now it gates John's hero shot.)
|
||||||
|
|
||||||
|
### 4. Poster-repetition call (debt #4) — **FINE, no ask to E**
|
||||||
|
Tonight's 14 posters carry **2 distinct designs** (Screaming Utes / screenprint ×7, The Dead Ringers /
|
||||||
|
xerox ×7 — different skins, different bands). Variety = number of venues playing tonight (one seeded
|
||||||
|
skin per gigId), so a spine run reads as two real band bills, not a repeat. Only a town where a single
|
||||||
|
gig plays everywhere would look monotonous (rare, and reads as "a residency"). No new templates needed.
|
||||||
|
|
||||||
|
### 5. Town-wide streetlamp pools — v3.1 candidate (Fable ruling, no code)
|
||||||
|
Fable ruled the night pools **stay venue-scoped for v3.0** (town-wide needs always-on `furniture.js`
|
||||||
|
changes that fight flags-off parity in release week; venue blocks read fine — `venue_night` proves it).
|
||||||
|
Parked here as a **v3.1 candidate** alongside wind sway and bench-sit loiter. No R14 code.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Round 13 (Fable's ROUND13 → Lane B) — the district reads by night (`?gigs=1`, v3.0-beta)
|
## Round 13 (Fable's ROUND13 → Lane B) — the district reads by night (`?gigs=1`, v3.0-beta)
|
||||||
|
|
||||||
Four B pieces, all gig-gated (flags-off byte-identical, verified). Files: `venue.js` (rewrite),
|
Four B pieces, all gig-gated (flags-off byte-identical, verified). Files: `venue.js` (rewrite),
|
||||||
|
|||||||
@ -205,15 +205,13 @@ export function createAudioEngine(PROCITY, { noassets = false, mute = false } =
|
|||||||
const lot = pub && (PROCITY.plan?.lots || []).find((l) => l.id === pub.lot);
|
const lot = pub && (PROCITY.plan?.lots || []).find((l) => l.id === pub.lot);
|
||||||
if (lot) venues.push({ shop: pub, lot, genreKey: pub.genreKey || 'pubrock' });
|
if (lot) venues.push({ shop: pub, lot, genreKey: pub.genreKey || 'pubrock' });
|
||||||
}
|
}
|
||||||
// Per-venue gig state for the muffled spill, robust across Lane F's alpha→district transition:
|
// Per-venue gig state for the muffled spill (R14: the R12 alpha alias hop is retired):
|
||||||
// 1. F R13 per-venue map window.PROCITY.gigs.byVenue[id].state
|
// 1. F's per-venue map window.PROCITY.gigs.byVenue[id] (the canonical surface since R13)
|
||||||
// 2. alpha alias window.PROCITY.gigs is the single machine → its state for its venueShopId
|
// 2. clock fallback plan.gigs (night 0) vs the current segment (works before F wires / headless)
|
||||||
// 3. clock fallback plan.gigs (night 0) vs the current segment (works before/without F)
|
|
||||||
// Returns null only when there is no gig layer at all (flags-off ⇒ byte-identical, no spill).
|
// Returns null only when there is no gig layer at all (flags-off ⇒ byte-identical, no spill).
|
||||||
function venueGigState(shopId) {
|
function venueGigState(shopId) {
|
||||||
const g = PROCITY.gigs;
|
const g = PROCITY.gigs;
|
||||||
if (g && g.byVenue) { const e = g.byVenue[shopId]; if (e) return typeof e === 'string' ? e : (e.state || 'quiet'); }
|
if (g && g.byVenue) { const e = g.byVenue[shopId]; if (e) return typeof e === 'string' ? e : (e.state || 'quiet'); }
|
||||||
if (g && g.venueShopId === shopId && typeof g.state === 'string') return g.state;
|
|
||||||
const gigs = PROCITY.plan?.gigs; if (!gigs || !gigs.length) return null;
|
const gigs = PROCITY.plan?.gigs; if (!gigs || !gigs.length) return null;
|
||||||
const ton = gigs.find((x) => x.night === 0 && x.venueShopId === shopId);
|
const ton = gigs.find((x) => x.night === 0 && x.venueShopId === shopId);
|
||||||
if (!ton) return 'quiet'; // dark tonight — reads true
|
if (!ton) return 'quiet'; // dark tonight — reads true
|
||||||
|
|||||||
@ -137,6 +137,25 @@ export function installDBG(deps) {
|
|||||||
|| (plan.shops || []).find((s) => s.type === 'pub');
|
|| (plan.shops || []).find((s) => s.type === 'pub');
|
||||||
return shop ? poseForShop(shop, dist) : null;
|
return shop ? poseForShop(shop, dist) : null;
|
||||||
};
|
};
|
||||||
|
// John's release hero: a CLOSE 3/4 on the pub door during doors/on, biased to the venue's +right
|
||||||
|
// (the queue side) so punters' faces read and a verge poster enters frame. The queue + posters are
|
||||||
|
// spawned by the live shell loop when the venue opens (seg 5 = NIGHT / 'on'), so F drives this shot
|
||||||
|
// live; this just frames the door + marquee + queue zone. Geometry mirrors venue.js's frontage.
|
||||||
|
const poseForVenueQueue = () => {
|
||||||
|
const vs = venueShops();
|
||||||
|
const shop = vs.find((s) => (s.venueKind || s.type) === 'pub') || vs[0]
|
||||||
|
|| (plan.shops || []).find((s) => s.type === 'pub');
|
||||||
|
const lot = shop && lotOf(shop); if (!lot) return null;
|
||||||
|
const ry = lot.ry || 0, fx = Math.sin(ry), fz = Math.cos(ry), rx = Math.cos(ry), rz = -Math.sin(ry);
|
||||||
|
const w = lot.w || 8, d = lot.d || 10;
|
||||||
|
const cx = lot.x + fx * (d / 2), cz = lot.z + fz * (d / 2); // door centre on the street (venue.js frontage)
|
||||||
|
const mw = Math.min(w * 0.92, 6.5); // marquee width (queue head ~ +right of it)
|
||||||
|
const DIST = 7.0, SIDE = mw * 0.5 + 2.2, EYE = 2.2; // close standoff, biased to the queue side
|
||||||
|
return {
|
||||||
|
pos: [cx + fx * DIST + rx * SIDE, EYE, cz + fz * DIST + rz * SIDE],
|
||||||
|
look: [cx + rx * (mw * 0.30), 2.7, cz + rz * (mw * 0.30)], // door, lifted to catch the marquee
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Named bookmarks (LANE_F_NOTES §4). seg = day segment index (0 DAWN … 5 NIGHT).
|
// Named bookmarks (LANE_F_NOTES §4). seg = day segment index (0 DAWN … 5 NIGHT).
|
||||||
// Predicates cover both Lane A's taxonomy (dept/stall/record/…) and the fixture's; each falls back
|
// Predicates cover both Lane A's taxonomy (dept/stall/record/…) and the fixture's; each falls back
|
||||||
@ -164,6 +183,7 @@ export function installDBG(deps) {
|
|||||||
// ── v3 gig district (round 13, ?gigs=1): the street money shots F scripts via tools/qa/gig_shot.py ──
|
// ── v3 gig district (round 13, ?gigs=1): the street money shots F scripts via tools/qa/gig_shot.py ──
|
||||||
venue_night: { seg: 5, resolve: () => poseForVenue('pub', 13) || streetViewPose(['main']) }, // ?gigs=1 — lit pub frontage + streetlamp pools + queue + posters at night
|
venue_night: { seg: 5, resolve: () => poseForVenue('pub', 13) || streetViewPose(['main']) }, // ?gigs=1 — lit pub frontage + streetlamp pools + queue + posters at night
|
||||||
district_posters: { seg: 5, resolve: () => streetViewPose(['main']) }, // ?gigs=1 — the spine at night: poster poles + lit venue frontages receding
|
district_posters: { seg: 5, resolve: () => streetViewPose(['main']) }, // ?gigs=1 — the spine at night: poster poles + lit venue frontages receding
|
||||||
|
queue_night: { seg: 5, resolve: () => poseForVenueQueue() || poseForVenue('pub', 11) || streetViewPose(['main']) }, // ?gigs=1 — John's hero: close on the pub door at 'on', queue + marquee + poster, punters facing the door
|
||||||
};
|
};
|
||||||
|
|
||||||
const DBG = {
|
const DBG = {
|
||||||
|
|||||||
@ -185,13 +185,13 @@ export function createVenuePresentation(plan, skins, scene, { assetBase = 'asset
|
|||||||
|
|
||||||
scene.add(group);
|
scene.add(group);
|
||||||
|
|
||||||
// ── per-venue state → frontage glow. Accepts F's per-venue map { [venueShopId]: state }, a Map, an
|
// ── per-venue state → frontage glow. F passes its per-venue map `gigState.byVenue`
|
||||||
// { byVenue } wrapper, OR a bare state string (alpha compat → the primary pub). Idempotent; the shell
|
// ({ [venueShopId]: 'quiet'|'doors'|'on'|'done' }); a Map or a { byVenue } wrapper are also accepted.
|
||||||
|
// (R14: the R12 alpha bare-string arm is retired — F wires the map since R13.) Idempotent; the shell
|
||||||
// calls it every street frame, so pool/glow ramps and the night baseline lerp here. ────────────────
|
// calls it every street frame, so pool/glow ramps and the night baseline lerp here. ────────────────
|
||||||
function stateGetter(gigStates) {
|
function stateGetter(gigStates) {
|
||||||
if (gigStates == null) return () => 'quiet';
|
if (gigStates == null) return () => 'quiet';
|
||||||
if (typeof gigStates === 'string') return (id) => (id === primaryId ? gigStates : 'quiet');
|
const map = gigStates.byVenue || gigStates; // F passes gigState.byVenue (per-venue map)
|
||||||
const map = gigStates.byVenue || gigStates;
|
|
||||||
return (id) => {
|
return (id) => {
|
||||||
const v = map instanceof Map ? map.get(id) : map[id];
|
const v = map instanceof Map ? map.get(id) : map[id];
|
||||||
if (v == null) return 'quiet';
|
if (v == null) return 'quiet';
|
||||||
@ -225,7 +225,7 @@ export function createVenuePresentation(plan, skins, scene, { assetBase = 'asset
|
|||||||
if (poolMesh) poolMesh.visible = poolMat.opacity > 0.01;
|
if (poolMesh) poolMesh.visible = poolMat.opacity > 0.01;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update('quiet');
|
update(null); // seed: no gig states yet → every venue quiet (frontage dark, pools follow night)
|
||||||
|
|
||||||
function dispose() {
|
function dispose() {
|
||||||
for (const d of disposables) d.dispose && d.dispose();
|
for (const d of disposables) d.dispose && d.dispose();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user