Commit Graph

103 Commits

Author SHA1 Message Date
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
m3ultra
e5d4679471 Lane A round 9: freeze CityPlan v2 contract in CITY_SPEC + closing-time occupant ruling
Ship round. Docs + one selfcheck log-line only; no generator change ⇒ all three goldens
unchanged (synthetic 0x3fa36874, osm/melbourne 0x34cfdec0, osm/katoomba 0x0f652510).

1. CITY_SPEC v2 contract FROZEN — new "CityPlan v2 — frozen producer contract" section: producer
   API, goldens table (keyed seed/plansrc/town) + how to pin a new one, town-key mechanism, osm
   normalization rules, hours/openLate/storeys laws. Matches code as shipped (F diffs claims vs
   code). Refreshed the stale round-6 Plan-sources blockquote to multi-town reality. Layer-1
   changes now require a CITY_SPEC amendment + golden re-pin in the same commit.
2. Recipe sanity — DRY-RAN end-to-end: appended a throwaway Newtown (42 shops), selfcheck auto-ran
   the full parity suite (1931/1932, only golden unpinned) and printed a paste-ready
   `newtown: 0x9045e577,`. Reverted; no 3rd town shipped. Added the selfcheck `⚠ UNPINNED — add to
   OSM_GOLDENS` line so the recipe is mechanical; fixed the recipe wording to match.
3. Closing-time occupant ruling (D's on-call Q) — ratifies + freezes what D's sim.js already does:
   half-open hours, no new entry when closed, occupants DRAIN (finish bounded dwell) never popped,
   player not force-ejected, openLate video is the night crowd. In CITY_SPEC + LANE_A_NOTES. No
   code change asked of D.

qa.sh --strict GREEN; selfcheck 1727/1727.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:56:19 +10:00
m3ultra
34145e24a7 Lane D round-9: interior presence — occupancy truth + browser rigs (C->D->F seam)
Follow a ped into a shop and find them browsing. D owns occupancy truth; C owns browse points;
F wires the handoff. Validated end-to-end in-shell (?stock=real). qa --strict GREEN; v1 untouched.

Occupancy (D1): patronage records who's inside which shop by shopId. New
citizens.occupancyOf(shopId) -> {count, occupants:[{seed,enteredAt,pedIndex}]} (pedIndex = the
exact ped who ducked in, for identity continuity). Cleaned on emerge/chunk-drop/stream-toggle.
Deterministic: 17 shops + occupants byte-equal across two runs (fixed a stale-occupancy leak on
stream toggle).

Browsers: keepers.js gained browse:true (faces the shelf via ry, no player-greet) + pedIndex +
seedKey. Each = a merged ped ~1 draw. 12 enter/exit cycles: count == min(occupancy,3) 12/12,
worst 61 draws <=350 (C's headroom holds), leak-free (0 GPU delta after warmup), disposed every
exit via keepers.disposeAll().

Consistency (D2): inside peds hidden on the street (0 rendered), re-emerge at the door.

F handoff verified by running F's exact interior_mode wiring (enter -> occupancyOf ->
browsePoints.slice(0,min(count,3)) -> keepers.spawn). index.html setShops door points need
shopId:s.id added. Closing-time handled by the dwell model (pending A's explicit ruling).

Evidence: docs/shots/laneD/r9_browsers_in_shop.jpg. Changed sim.js + keepers.js + test page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 10:21:10 +10:00
m3ultra
9c7c65f57c Lane C round-9: draw-headroom note for D's browser rigs (F1 handoff)
Measured worst interior with 3 two-draw rig proxies at browse points:
68 draws (opshop/hall) in the ?stock=real path — browsers add ≤6, ample
headroom. Flags the one tight spot for D/F: pre-existing GLB-on opshop/
hall is 344/350, so keep rigs impostor-cheap if ever stacked on GLB
hero-props there; F's sweep-with-browsers confirms ≤350.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:57:55 +10:00
m3ultra
c68bba8f32 Lane C round-9 C2: buy-anywhere — pull-and-buy on book spines + toy boxes
Book/toy shelves get pull-and-buy over the SAME wallet; records keep the
deep dig. New stockpack.buildBuyableShelf(): a real shelf is merged,
per-item-ADDRESSABLE meshes — one per atlas (all covers drawn from one
seeded atlas → one draw/shelf), tagged noBatch so batch.js leaves them
intact. Aim a spine/box → pull card (title/author-or-maker/$price/band
from the pack index) → BUY debits the wallet, adds to inventory, and
collapseBuyItem() zero-areas the item's quad in place (removed from the
shelf, no geometry churn). Parody stock → no buy mesh → no card. Fail-
soft per pack; atlasPool() keeps each shelf single-atlas (one draw).

Test page: E interacts (bin→dig, shelf→card) + a #shelfBuy pull card;
shelfBuySoak() buys one item per book/toy seed. Validated: raycast→card
→BUY end-to-end (quad collapses to centre, cash/inventory update),
buy-soak 6/6 collapseOk leak geo0/tex0, ?stock=real draws record 41/
book 58/toy 57 ≤350, drawSweep GLB-off 168/on 344 unchanged, placement
determinism 0 fails, qa --strict GREEN 5/5. Shot: browse_buy_r9.jpg.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:56:21 +10:00
m3ultra
5ae635a1e9 Lane C round-9 C1: seeded browse points (room.browsePoints) for Lane D rigs
layout.js placeBrowsePoints(): 1–3 deterministic floor poses in front of
browsable floor fittings, facing the goods. Guarantees (all asserted):
walkable (occ-free, not reserved), reachable from spawn (door→counter
flood-fill), ≥0.6m apart + clear of keeper stand, every archetype (rich
candidate ring — 4 sides×2 gaps + diagonals — plus a nearest-free-cell
fallback so tight/mismatched rooms still yield ≥1). Pure data: no meshes,
no draws; ≤350 law untouched. Exposed as room.browsePoints[]
{x,z,ry,atKind,slotIndex}, same coord frame + ry convention as
counter.stand (contract in LANE_C_NOTES).

Validated headless: 180 type×archetype×seed combos → 0 empties (177×3,
3×1 via fallback), determinism 0 fails, min-sep 0.7m, 0 keeper clashes.
Test page: cyan browse-post markers on the 'path' overlay + HUD count.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:36:26 +10:00
m3ultra
5529d62263 Lane C round-9 handshake: browse-points interface (C→D→F seam)
Publishes decision #1's contract FIRST (before code) so D and F build
in parallel: room.browsePoints[] (0..3, deterministic per shop.seed) —
{x,z,ry,atKind,slotIndex}, same coord frame + ry convention as
counter.stand. Guarantees: walkable, reachable (door→counter flood-
fill), ≥0.6m spaced, every archetype. C adds no meshes/draws; D's rigs
ride the ≤350 interior budget. Includes the D→F→C handoff (occupancy
count → browsePoints.slice(0,min(count,3)) → one rig per point).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:27:12 +10:00
m3ultra
e8f92a0da2 Fable (integrator): round-9 lane instructions — the v2.0 ship round (interior presence, buy-anywhere, tram, tour, docs freeze)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 09:16:59 +10:00
m3ultra
9cc00ad29c Lane F R8: wire town/weather/patronage/buy + graduate harness + new smokes
Shell seams (F owns index.html): A &town=<key> -> generatePlanFor(seed,'osm',{town}) (Katoomba);
B weather (createWeather on ?weather=1; PROCITY.weather={state,intensity}, {clear,0} off; update in
loop); C session wallet bound to the dig BUY (getCash/onBuy in interior_mode); D patronage door
points -> citizens.setShops + ?patronage=0 off-switch + setWeather each frame.

Harness: stock=real + weather=rain graduated warn -> STRICT. New warn smokes: buy-v0 (dig BUY ->
wallet, cash 191->179 bag 0->1), patronage (7 peds visit shop doors/~18s), book/toy stock (6/11
real atlas meshes). Determinism gate: pinned osm/katoomba golden 0x0f652510 keyed on (seed,plansrc,
town) + fixed a hex zero-pad bug the katoomba golden exposed (0x0f652510 vs unpadded 0xf652510).

No patronage baseline re-pin needed (nets fewer draws, within tolerance). qa.sh --strict GREEN 5/5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:09:11 +10:00
m3ultra
3daf8df3ec Lane D round-8: shop patronage v0 + weather reaction
The crowd comes alive. Default-on for the streamed roster (behind ?patronage=0); v1 path
(?roster=v1) untouched — no patron fields, golden identity holds. qa --strict GREEN.

Patronage (D1): per-ped state machine walking -> going (steer to a nearby open shop's door,
seeded ~every 10m within 18m) -> inside (hidden, 5-20s seeded dwell) -> emerge (resumes walk).
Hours-aware: noon = all types (up to ~38 inside, 7 types); night = video-only (the openLate shop
draws the crowd, roll ramps up as streets empty). Deterministic (150 chunk-keyed ids), leak-free
(0 GPU delta over the churn), budget-neutral (inside peds hidden -> draws -1).

Weather (D2): reads Lane B's PROCITY.weather contract (no import). setWeather({state,intensity}).
Rain -> density -56% (40-60% target), walk speed +14%, more sheltering (inside 6->25); overcast
-10%; clear = v1.

Also this session: R7 post-flip shell verification (no-flag boot streams, determinism, leak-free,
?roster=v1 restores golden roster) and pushed main + v1.0/v1.1/v2.0-alpha/v2.0-beta to origin.

F wiring (setShops door-point recipe, setWeather, ?patronage=0) documented in LANE_D_NOTES.
Only web/js/citizens/sim.js + web/citizens_test.html changed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 04:42:34 +10:00
m3ultra
fbc8ffa1c8 Lane C round-8: buy loop v0 + book/toy real stock (?stock=real)
C1 — buy loop v0 (new wallet.js): runtime-only economy — seeded cash
(~$60–200), buy()/broke-gate/in-memory bag, onChange for a cash chip.
World gen untouched (purchases never re-enter the plan/seeded build).
Test page: #cashChip HUD + I-toggle inventory + dig BUY IT button
(pull → bag, cash down, bin depletes); digSoak buys ≤2/visit.

C2 — book spines + toy boxes wired to ?stock=real. stockpack.js keys
each pack to a slot (record→sleeve, book→spine, toy→box); stock.js
shelfLine builds real atlas-UV cover planes for book/toy shelves
(static, no dig), fail-soft per pack. E's packs live: record 350/6,
book 311/4, toy 273/5 (items/atlases).

C3 — validated: draws ≤350 (record 41, book 42, toy 51), determinism
0 fails, leak-free (0 geo/tex delta ×20; buy-soak 12 visits/5 bought,
leakGeo0/tex0), reload resets wallet, flag-off + ?noassets untouched,
qa.sh --strict GREEN 5/5. Shot: docs/shots/laneC/buyloop_r8.jpg.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 04:33:00 +10:00
m3ultra
f952f513d0 Lane A round 8: OSM to parity + a second town (Katoomba) — carried R7 brief, full
The carried brief (slipped R7) lands complete — all four items, qa.sh --strict GREEN.

1. Selfcheck PARITY: extracted structuralSuite(plan,label) and run the FULL invariant suite
   on every (source, town) — synthetic + both OSM towns get identical coverage (storeys,
   one-shop-per-lot, facing, within/cross-block overlap, corridor coverage, determinism,
   exactly-one-openLate). ALL GREEN 1727/1727 (was 1362; OSM went subset → full ×2 towns).
2. SECOND TOWN: Katoomba (Blue Mountains, 19 shops, op-shop/book heavy) — regional contrast
   to inner-Melbourne. osm_fixture.js → OSM_TOWNS{melbourne,katoomba}+DEFAULT_TOWN;
   generatePlanFor(seed, source, {town}); ?plansrc=osm&town=katoomba. Golden 0x0f652510.
   Melbourne 0x34cfdec0 + synthetic 0x3fa36874 UNCHANGED (town key kept off the plan).
3. "Add a town" recipe in LANE_A_NOTES (R8): extract → OSM_TOWNS → pin golden → tell F.
4. Normalization + LOG: importer bends real data to the contracts (unknown kind→opshop,
   hours-clamp so only one shop is openLate, video-preferred landmark w/ fallback) and logs
   it via {report}; selfcheck prints per-town (e.g. melbourne hoursClamped:5, openLate:video).

For F: three goldens to pin, gate keyed (seed, plansrc, town); selector gained {town} — see
LANE_A_NOTES R8. Screenshots docs/shots/laneA/osm-{melbourne,katoomba}.png.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 04:15:12 +10:00
m3ultra
a667283cf3 Lane E round 8: REAL stock packs (record 350 / book 311 / toy 273) live on depot
John unblocked GODVERSE DB access (m1ultra native-Postgres clones, read-only SELECT,
peer auth). All 3 packs rebuilt from real data:
- record 350: discogs_full.inventory (real store stock) join release/release_image,
  real Discogs cover art.
- book 311 + toy 273: dealgod.products by category_path, real product photos + prices.
Metadata parody-transformed (deterministic, no source-token leak -> no real trademarks
in pack text); cover images are real release/product art (read-only, non-economy,
decision #2); book prices seeded (source is info-only, John's call). 15 atlases
published to the depot; indexes committed (the C contract) + staged for ?localdepot;
all pass the pack-QA gate. build_stock_pack.py gained --from-tsv (extract-on-DB-box ->
build-here), portrait 176x256 book cell, seeded-price fallback. qa --strict GREEN 5/5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 04:09:14 +10:00
m3ultra
900b274a9a Lane B round-8: weather (?weather=1) — seeded rain/overcast/clear, exposes PROCITY.weather for D
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>
2026-07-15 02:34:14 +10:00
m3ultra
081755bb71 Lane E round 8 (E1+E2): book/toy stock packs + pack-QA gate
E1: build_stock_pack.py generalized over kinds — record (256x256 sleeves), book
(96x256 tall-thin spines), toy (256x256 boxes), per-kind parody word banks, same
build-time/parody/atlas/index laws. Book+toy sample packs built + staged (?localdepot)
+ indexes committed to pipeline/packs/ so Lane C wires book/toy shelves now. Parody
deterministic + no distinctive-token leak across all 3 kinds.
E2: validate_pack.py QA gate (wired into validate_manifest -> qa gate 3) — bad UV /
empty title / bad price_band / dangling atlas / dup id fails qa (proven). qa strict
GREEN 5/5.
Real 150-250-item packs blocked on GODVERSE_DSN (flagged to Fable); samples are
placeholders in the real index format. No fal spend.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 02:27:50 +10:00
m3ultra
1a20501e55 Fable (integrator): round-8 lane instructions — catch-up (A/B carried) + the town comes alive (patronage, buy loop, weather, pack breadth)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 02:06:34 +10:00
m3ultra
16d4f2b86d Fable R7 review: gitignore pipeline/_stockpack/ (E2 build staging, atlases live on depot)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 02:04:13 +10:00
m3ultra
4feba02732 Lane F R7 F3: v2.0-beta — record tag + flag B/A round-7 slip
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 01:59:28 +10:00
m3ultra
b94f86b49f Lane F R7 F2: harness → strict + wire ?stock=real (real GODVERSE covers in the crates)
qa.sh: flags harness warn_gate → run_gate — flags-off regression + the 4 existing flags +
all-on combo are now STRICT (a harness FAIL fails qa). New flags stay warn-level in-harness.

?stock=real wiring (F owns the shell + interior bridge): shell preloads the record stock pack
(preloadStockPack('record'), fail-soft, off under ?noassets) + passes stockReal to the bridge.
interior_mode builds makeStockAdapter(getStockPack(shop.type)) and passes it to BOTH buildInterior
(static crate sleeves) and dig.open (riffle) — null pack → parody canvas (Lane C fail-soft).

Harness: added stock=real smoke (assert non-parody = batched userData.isStock atlas meshes > 0;
verified 7 real sleeves in the record shop) + weather=1 smoke (auto-skips until Lane B lands),
both warn-level (decision #4). qa.sh --strict GREEN (5 gates); crates now show real covers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 01:56:14 +10:00
m3ultra
0b84560457 Lane F R7 F1: roster flip — streamed roster is now the DEFAULT (prime-law amendment)
The first deliberate flags-off baseline change. On D's GO (43edabf: E1 ped sub-mesh merge
447188a validated → ~1 draw/near-rig → full density 241 worst-street draws <=300, leak-free).

index.html: chunk-streamed roster default-on (chunkStream:{radius:2}); ?roster=v1 restores the
old fixed roster (escape hatch); ?roster=stream still accepted (now a no-op). Hours-aware
setNightLivelyChunks keeps the open-late block lively at night.

Flags-off regression baseline RE-PINNED (same commit, prime-law amendment):
  OLD (roster-off, v1.1):        163 draws, 19000 tris
  NEW (roster default-on, R7):   164 draws, ~66000 tris
Draws barely move — E1's merge makes each near-rig ~1 draw (exactly what gated the flip). The
tris jump is the streamed crowd (D worst-view 65,899); it is frame-variable, so the drift WARN
is now DRAWS-ONLY, tris guarded by the STREET_TRIS_MAX hard cap. PLAN GOLDENS UNCHANGED
(synthetic 0x3fa36874, osm 0x34cfdec0).

Also fixed the harness roster probe (read a nonexistent prop c.streaming → was blind to
streamMode) + flipped the assertion to REQUIRE streamMode on default boot + added a ?roster=v1
escape-hatch check. flags_check GREEN; qa.sh --strict green; 0 console errors both modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 01:41:27 +10:00
m3ultra
3724a65505 Lane C R7 C1: ?stock=real — real GODVERSE sleeves in the crates
The stockAdapter seam built in v1 finally eats. Lane E's stock pack (parody-
transformed Discogs metadata + cover atlas) feeds record-shop bins + the dig
riffle behind ?stock=real. Economy stays a stub (buying = toast).

- Contract handshake (task 1, unblocked E): confirmed E's index schema as-is
  in LANE_C_NOTES (items[{id,title,artist,price,price_band,atlas,uv}]; uv
  origin top-left, C flips V for WebGL; fail-soft; per-type packs).
- stockpack.js (new): preloadStockPack/getStockPack (cached) + makeStockAdapter.
  Atlas texture + material are shared/cached (like depot GLBs); each sleeve is
  a cover PLANE sampling the atlas at its baked UV, so all real sleeves in a
  room batch to ONE draw (record: 59 draws).
- stock.js binFan: real cover planes (else parody canvas). dig.js: riffles real
  covers, pull card shows title/artist/$price/band. interiors.js: opts.stock=
  'real' wires the adapter (warn-once + parody fallback if pack absent). Test
  page reads ?stock=real, preloads record/book/toy, passes the adapter to the dig.

Validated (E's staged 24-sample; real covers drop in unchanged when E gets the
DB): determinism 0/30, leak-free rooms + real dig (0/0 over 25 cycles), draws
<=139 all rooms (record 59), fail-soft on no-pack types, ?dig=1&stock=real
leak-free. Flag-off + ?noassets untouched (procedural path byte-identical).
qa.sh --strict GREEN. F smoke hook + E contract in LANE_C_NOTES. Shot
docs/shots/laneC/stock_real_r7.jpg.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 01:23:23 +10:00
m3ultra
43edabfe56 Lane D round-7: validate ped-merge → GO for roster flip + full-density defaults + escape hatch
Lane E's R7 merge (447188a) made each ped 1 mesh/1 material (~1 draw/near-rig, fleet 116->24 at
the cap) — the gate my R6 memo named. Validated + handed F the GO.

Merge validated: bind+animate/no-T-pose, skinning/skeleton preserved, silhouettes+atlas materials
crisp (hi-vis/suit/kid), impostor bake clean, identity variety + determinism intact. GPU memory
dropped (geom 205->160, tex 141->90).

Flip numbers (full density, perChunk 16, in-shell): worst street view 241 draws <=300 (was 356
unmerged), 65,899 tris <=200k, 17 near-rigs; 30-chunk soak (726 builds/disposes) leak-free, 0 GPU
delta, heap stable. => GO.

D2: enableStream default perChunk 8->16 (full density, the merge affords it); near-cap stays 24.
D3: test page + harness default to stream now; ?roster=v1 escape hatch restores the fixed roster
(verified streamMode false + determinism). No-flag boot -> streamMode true + determinism.
F's web/index.html flip wiring (invert to default-on + ?roster=v1 escape) documented in
LANE_D_NOTES; in-shell no-flag-URL boot completes when F lands F1.

Only web/js/citizens/sim.js + web/citizens_test.html changed (+ NOTES/progress).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 00:51:51 +10:00
m3ultra
0c12dacb6d Lane E round 7 (E2): GODVERSE stock-pack pipeline (parody + atlas + index), proven
pipeline/build_stock_pack.py builds C's ?stock=real pack offline (nothing queries the
dataset at runtime): recordgod (dealgod discogs_release) → curate → parody-transform
title/artist (deterministic, shares no source token — no real trademarks) → atlas WebPs
+ JSON index {id,title,artist,price,price_band,atlas,uv}. Proven end-to-end with
--sample 24 (synthetic sleeves); sample pack staged to web/assets/models/ so Lane C
wires ?stock=real against the real index format now. Real 200-400 pack blocked on
GODVERSE_DSN (dealgod Postgres creds — flagged to Fable) + C's schema confirmation;
one command (--from-db --count 300) once they land.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 00:43:08 +10:00
m3ultra
447188a516 Lane E round 7 (E1): merge ped rigs to ONE draw each (gates roster flip)
Each of the 19 ped rigs carried 1-9 primitives / 1-3 materials (fleet 92 draws,
~116 at the 24-rig near cap). merge_ped.py (Blender) merges each to 1 primitive +
1 atlased material: join meshes -> pack material UVs into a non-overlapping atlas UV
-> EMIT-bake base-colours into one 1024 atlas -> single material. Skinning + skeleton
preserved (65 joints, walk/idle untouched, clips retarget unchanged). Fleet 92->19
draws (1/ped); near-cap 116->24 (79% cut). Verified in vendored GLTFLoader: all 19
load as SkinnedMesh + bind walk; man_suit poses byte-identical to original. Hands to
Lane D (D1) for full validation + full-density numbers, then F flips the roster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 00:33:03 +10:00
m3ultra
15e2cc0a9f Fable (integrator): round-7 lane instructions — roster default-on flip + GODVERSE real stock + weather + strict harness
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:53:54 +10:00
m3ultra
6948372f86 Fable R6 review: land F's refreshed dig shots (re-rendered during harness runs)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 23:47:39 +10:00
m3ultra
c88d8906a2 Lane C R6 C2: map the 3 orphaned fittings (glass_case/magazine_rack/crate_stack)
Published R5, unconsumed until now:
- glb.js KIND_TO_GLB: glassCase->glass_case, magazineRack->magazine_rack,
  and a NEW crateStack primitive (fittings.js — a stack of crates) ->
  crate_stack. yaw 0 (validated on-screen).
- theme.js: crateStack in record + opshop (back-room dressing); glassCase
  added to milkbar; magazineRack added to pawn; milkbar magazineRack moved
  window->wall (dodges the door-counter congestion).
- layout.js: fixed placeNearCounter — it picked one random side and gave up,
  so counter-zone fittings (the glass case) rarely landed. Now it tries both
  sides + offsets, then falls back to a free aisle spot, so a min>=1 fitting
  reliably lands.

Validated (GLB on, baked depot): all 3 load + render planted/scaled/facing
right. Appearance glassCase 12/12 (toy/pawn/milkbar), magazineRack 12/12
(milkbar/pawn), crateStack ~11/12 (record/opshop). drawSweep still <=350
with them on (worst 177 GLB-on / 157 off). Determinism 0 fails, leak-free,
dig (?dig=1) still riffles batched bins (C3 re-verify). Contact sheet
docs/shots/laneC/glb_orphans_r6.jpg. qa.sh --strict GREEN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 23:19:48 +10:00
m3ultra
3b86b0c5b3 Lane F R6: ≤350 interior draw gate + fix interior renderer.info accumulation
Added an interior draw-budget sweep to flags_check.py (decision #2): enter all 9 shop types,
assert <=350 draws/room, dig on so it also confirms C1's batching kept ?dig=1 riffling.

The sweep caught a real bug in interior_mode.js (F-owned): the interior/dig render never called
renderer.info.reset() while the shell runs autoReset=false (for the composer), so
renderer.info.render.calls ACCUMULATED every frame — inflating any interior draw read (and the
HUD were it shown). Fixed: reset per interior frame before both the dig and the walk render.

True per-frame result after the fix: all 9 room types <=350 draws (worst dept 96) — C1 batching
(35981ad) verified. flags_check GREEN (regression + interior budget + 4 flag smokes + all-on combo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 23:10:11 +10:00