293a82c5e8
28 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
293a82c5e8 |
R42 THE LOOK: five lane-runs — the pub is dressed, the decks read, and the town is cast
John looked at R41's proof shots and named three faults. All three are fixed, at zero draw cost, and every lane corrected somebody's numbers on the way — including its own. E-LOOK (§42.1+§42.2a) — THE PREMISE WAS WRONG. "The pub props have no texture" (my brief, quoting E's own R41 note) is false: all 37 carry COLOR_0 and three.js renders it. The colour was BLEACHED — jukebox at saturation 0.02, 15 assets under 0.05; what the source library called colour was baked AO. So the fix was a palette imposed on colour already present, in place: 46 assets, draw delta +0 and tri delta +0 on every one, proved the honest way — the concatenated POSITION/NORMAL/TEXCOORD/index bytes are sha1-identical to R41, so footprints and origins provably did not move. (A first-pass bbox check ignored node rotations and "found" 3 phantom violations; thrown out for the byte comparison.) The banquette was 1990s office teal and went burgundy; the beer umbrella was white and went brewery green. THE DECK, diagnosed before being touched: 7 greys, chassis 0.05 luminance on a 0.033 bench = 1.21:1, and the one high-contrast feature was INSIDE-OUT (white ring around a dark disc; a turntable is a dark record on a light platter). Now Technics silver at 6.74:1, black vinyl, red start/stop. Node contract re-read from the shipped GLB: 4/4 + 1/1 PASS. Filed to R43, not fixed: deck_1200_rigged has NO PLINTH (bottom 43mm of 119mm lost to R41 join damage). E-CAST (§42.3) — 19 of 24 ship. Rejected: comical_luchador_01 (Mixamo Ch43, purple mask reading EL CHUPACABRA, identified from the file's own material name), a 3-heads-tall cartoon child, a robed wuxia elder, a WW2 infantryman — and dj_phrtt_01, AN UNCLOTHED BODY whose only texture is a bare-skin atlas, which was in the DEFAULT crowd and live on the depot. It is the R41 deny-list's failure class through a different door: an innocent name from another pipeline. Only rendering all 24 and LOOKING found it. Ruling 2 (prefer CC0) was REFUSED ON MEASUREMENT: Quaternius is 25 nodes / 23 joints and ZERO of 64 canonical tracks bind — it would have loaded silently and never animated. Replacements came from Mixamo's Ch## pool, filtered to the contract-clean 65-bone family (candidates ran 65..99 bones; named characters carry facial/hair bones). THE LICENCE GAP WAS UNREAD, NOT MISSING: every source FBX carries ApplicationVendor "Mixamo, Inc." internally. Adobe royalty-free, no attribution owed. B's amber rows are now real. B (§42.5) — MY ASSIGNED FIX WAS USELESS AND B PROVED IT. document.fonts.ready shipped, then measured: the atlas canvases are already byte-identical across boots, the game ships NO webfonts (document.fonts.size === 0), and ready fires 50ms BEFORE the first fillText. The real cause of unreproducible bookmarks is the wall-clock CROWD — 983 changed px of 921,600, ALL in the pedestrian band; 0 px with the crowd out. New DBG.freeze() takes stable bookmarks 2/5 -> 5/5. Also found: ?pop=0 boots 140 citizens (0 is falsy against the default). THE BENCH: D's filing correct on both counts. Front-vs-road 90.0deg -> 0.0deg, min=med=max over 60/60 instances; the streetlight arm now reaches 1.05m over the road where it reached 0.00. Both used a base yaw that pointed +Z down the street while their own comments claimed otherwise — the side term was already right, which is why it survived 41 rounds of reading. Also: on any box with CDN access 9 of 60 benches are the depot GLB, 90deg out from the house law — normalised at the geometry, once, at load. benchStops(plan) exported as one truth. C (§42.2b) — 122 vs 123 WAS THE CAMERA ASPECT, and nobody was wrong. Draw counts are post-frustum-cull and the sweep camera inherits the window aspect: 1.25->116, 1.60->122 (C's harness), 1.778->123 (F's), 2.37->124. Pinned MEASURE_ASPECT=16/9 with a 1.25 control. E's "keep the bench dark" advice was measured and declined with reason (deck-vs-bench was already 4.73:1, over threshold). "Reads as a black box" is a claim about pixels, so C measured pixels: near-black in the booth crop 57.5% -> 26.7%, distinct colours 228 -> 389. Bench rebuilt 3->7 boxes with an open record bay; headphones on the mixer; faceDoor aims booths at the player's entry — alignment within 45deg went 49% -> 92%. Two bugs found by looking: a fitting could be planted INSIDE A WALL (0.77m of a 0.86m half-depth in plaster), and every booth part sat 25mm sunk into its own worktop. D (§42.4) — five swaps IN PLACE at the same index (pickRig indexes these arrays and pedIndex is in the identity signature and the impostor atlas; removal would renumber the town). Identity signature pre- vs post-swap: 0 differing lines of 150 — who each citizen is did not move, only which body they wear. dj_phrtt_01 verified gone AT THE WIRE, not from source: a fresh default boot fetches 32 ped GLBs, none retired. THE CONTROL ARM FOUND A 41-ROUND-OLD BUG: the ped being RETIRED, comical_boy_01, binds only 3,132 of 3,460 tracks — six thumb bones lack the mixamorig prefix. It had been silently dropping six tracks per clip since it shipped. Testing the thing being thrown away found it. Imported B's benchStops mid-round: sitters now 0.0deg to the road, signatures byte-identical across the rewire. Corrected F's filing: the browse smoke was flaky-by-construction (a 16-25s race against a live sim), not deterministically red. F (§42.6) — qa.sh --strict 24 passed / 0 failed / 0 warn / 0 skipped. New Gate 11: period law (0/5 banned; CONTROL: R41's roster trips all five) and roster licence (24/24, 0 unverified; CONTROL: an amber row turns 20 red). r41_shots.py promoted warn -> strict. R41'S BYTE-HASH BAN IS REVERSED AND ITS STATED REASON WITHDRAWN AS WRONG. A gate may pin a hash under five in-run assertions (classic+flags boot, freeze().stillLive all-false, a second freeze removing 0 draws, settle until DBG.info() stops changing, hash with the dbg panel hidden): 5/5 bookmarks now pin to one sha256 over 3 fresh boots. Two findings got it there — the chunk streamer (a fixed settle is a bet on load) and the fps readout, which with everything else frozen was the last thing moving at 53-62 px. ?pop=0 fixed (Number.isFinite) — a no-op for 35 rounds. Three red flags_check gates fixed. Street: noon 282 · NIGHT 291/300 — the nine-draw margin INTACT, every R41 row reproducing to the digit. Interior at pinned 16:9: 123 @ dept/auto, margin 227. selfcheck 157,647/157,647, 0x5f76e76 unmoved. No tag — John's playtest rules the epoch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
78f49f7113 |
Lane D R41 §41.3: the town stops walking — 99.3% to 78.1%, at zero draws
THE ROUND IN ONE MEASUREMENT (12 samples x 146 active, ?clips=0 vs default — a new flag that turns off the library and nothing else): walking 99.3% -> 78.1% · bench-sit 0 -> 9.5% · lean 0 -> 7.1% · stopped in own idle 0.4% -> 5.1% · DISTINCT CLIPS ACROSS THE CROWD 4 -> 20. The town was 99.3% people walking because standing still had nowhere to happen. Wiring: new postures.js + clipbank.js. idles.glb (10/10) drives a per-citizen deterministic idle on every near-tier actor plus the seeded shopkeeper. locomotion gives 33.7% of walkers a shopping bag. sitlean (8/8, lazy) puts 4 sits on Lane B's ACTUAL benches and 4 leans on shopfront walls. browse (5/8, lazy) is a real BROWSE state at C's browse points, seeded per (shopId, slot). venue (5/6, lazy) widens the gig crowd, plus a publican pouring and a record keeper in headphones. social (0/8) is never fetched — two-person conversation needs a paired state machine, filed to R42. Cost: boot = 4 requests, 1.24 MB / 16 clips resident; the rest lazy on first need; heap delta +3.34 MB; mixer median 0.1 ms both arms. ?clips=0 / ?classic=1 / ?noassets=1 fetch ZERO clips — not even clipbank.js (dynamic import). No shell edit needed. DRAWS: +0 on every bookmark (street_noon 193, crossroads 108, night_crowd 128, market_square 94, night_neon 111, interior 110 — identical both arms). Ruling 4 respected exactly. DETERMINISM: 150 citizens, two fresh contexts, byte-equal posture signature. Controls: seed+1 differs; EVERY clip GLB delayed 2 s -> identical signature (posture is a pure function of (citySeed, id), never of residency). 6 new streams collide with none of the 12 pre-R41 keys. TWO FINDINGS THAT CHANGED THE DESIGN: the idle pool was INVISIBLE — wired only to the R17/R29 node loiter, so only 0.8% of citizens were ever stopped; and the lean never fired at all (0 in a 9 s run). Both moved to the patronage stride check. Bench stations are GATED not trusted: 14/14 derived stations coincide with real instanced geometry within 2 cm, and the control (same stations offset 2 m) matches 0/14. Filed to B: one benchStops(plan) export retires the mirror, and furniture.js puts the bench's front ALONG the street rather than facing the road, contradicting its own comment. Leak: +0 geometries, +1 texture over 6 enter/exit cycles. Goldens 157,647/157,647, 0x5f76e76. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3e1ff312a5 |
Lane D R40 §40.5: the peds come in the front door — 100% on every real town
Verification first, and B's R39 heading fix did NOT clear the gate alone. Measured today (tools/qa/door_footpath_check.mjs, new): synthetic 447/493 foot (90.7%) · katoomba 71/72 · fitzroy 138/139 · bowral 28/30 (93.3%) — from R39's 0/493, 0/72, 0/139, 0/30. Two residue species, handled differently ON PURPOSE: 1. A 0.85m kerb miss on real towns — plan_osm's setback puts the facade past the corridor edge, so the shell's d/2+0.6 door point lands just off the verge. Fixed by new D-owned door_snap.js, applied in sim.setShops: clamps each door into the registry vergeBand of its nearest footpath-bearing edge, 6m cap. Corpus: fixes 4, breaks 0. Live-shell verified (493 points, 2 moved, max 5.41m — matches node exactly). Real towns now 72/72, 139/139, 30/30. 2. The synthetic's 36 strict misses are market stalls and arcade shops WHOSE FRONT IS THE MARKET SQUARE. An uncapped snap would 'pass' them by teleporting a door 59.85m to a street they do not front — passing the gate by breaking the truth it measures. The gate instead scores walkable front ground (footpath ∪ market/arcade block ground) = 473/493 (95.9%) and reports the strict number alongside. The check ships its own falsifiability CONTROL (the R8-R39 back point must score under the floor: reads 0.4-13.3%) and a fix-only arm (clamp breaks 0, asserted forever). Deterministic. Remaining 20 synthetic misses are artefacts of the fixed nudge at index.html:433-437 — not D's file; measured, exact fix documented for F. Goldens untouched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2fd4c1cf79 |
Lane D R36 w2.5 (Fable ruling): CLASSIC KEEPS ITS PEOPLE — the 5 DJ bodies gate out of ?classic's pool
|
||
|
|
10025d4082 |
Lane D R29 (v6 Spike 1): look.glb bound and wired — peds glance, feet planted (wave 0)
The spike reaches the game. E's look.glb (mesh-free, 65 joints, 6.5s 'Look') is bound
through the fleet gate; street peds now glance around during window-shop stops. `lean`
is absent and never existed (E's R28 measurement). Goldens untouched — clips sit outside
every plan hash; the synthetic anchor stays R27's amended 0x5f76e76.
WIRED: loadPedFleet(base, {sit, look}) -> fleet.lookClip, the exact twin of the R16 sit
gate; the shell passes look:!CLASSIC so ?classic fetches NOTHING (a raw fetch would have
breached the zero-fetch-delta covenant — E flagged it, the gate is the answer).
makeActor gains lookA, played only on setLooking(true) — crossfaded (0.3s), not snapped
like sit, since idle->idle-variant reads naturally and there's no replant for a fade to
fight. sim.js gains a dedicated `glance` rng stream, rolled ALWAYS (deterministic) but
only flipped when a clip exists => classic inert at the source. Mutually exclusive with
bench-sit (sit rolls first at 35%, glance takes 40% of the rest). RigPool threads
lookClip; release snaps the glance off so no rig is pooled mid-look.
THE FINDING — my own prediction was wrong, and the measurement caught it. I wrote that a
STANDING clip needs no foot replant ("no hip descent to recover — that trap was sit's
alone"). Measured over the full loop: idle keeps the lowest bone within 4cm of the ground
(-0.04..0.00); look.glb ranges -0.009..+0.205 — the ped HOVERS up to 20.5cm, drifting
through the loop. Same trap, different coat: _rotOnly drops the Hips POSITION track for
rig-height independence, so the clip's authored weight-shift dip can't move the hips and
comes out as the FEET RISING. Sit's one-time replant can't fix it — the float varies per
frame.
FIX: plantFeet() — the per-frame twin of sit's replant. Reset to bind plant -> measure
posed feet -> drop inner by float/scale. ABSOLUTE (reset->measure->correct), never
incremental, so it cannot drift. Reproduces the authored motion exactly: the hips dip
relative to the ground instead of the feet leaving it. Scale-aware like sit's. Foot bones
cached once; cost paid only by glancing peds, on frames their mixer ran (both mixer sites
— the drummer's post-mix lean taught that coupling rule).
PROOFS: foot float 0.205m -> 0.000m (pinned); head yaw sweep span 1.735 (-0.85..+0.89) so
the glance still animates; ?classic — no look fetch, no Look action on any rig, glance
never flips (0); identity signature unchanged, no glance term; sit AND glance never
simultaneous (0); 0 NaN; goldens 0x5f76e76 untouched. A glancing ped is NOT tagged
seated/posed — standing pose at standing stature, so F's no-giants gate needs no arm.
D->F: the pose gate HAS ITS SUBJECT — un-SKIP it. Fresh ?localdepot=1 boot shows a ped
glancing on the footpath, head sweeping, feet planted.
Spike 2 readiness: plantFeet() is the general machinery the brief asked for ("data, not
new code") — riffle and wall-lean should land as clip + roll; the lean's wall-contact
placement is the only genuinely new part.
FLAGGED (A's file, A rests): selfcheck.js:301 still says "the synthetic golden above stays
0x3fa36874" while line 267 pins the amended 0x5f76e76. A stale comment, not a rule — but
the same species as the epoch's five holds, so: flagged, not touched.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
afad68b114 |
Lane D R28 (v5.1): instrument LOD — KILLED with the measurement (ledger #4)
E: STOP — do not build the _lo variants. That work is unnecessary; the item is dead.
The oldest tri item on the books, killed under the wind-sway rule attached to the brief
("if the measured win is <20k tris in practice, KILL it with the measurement").
MEASURED, from the shipped depot GLBs: each of the five instruments is exactly 14,000
tris; band + amp on stage = 70,000. On paper a 3-4k _lo each "saves" ~52k, clearing the
20k bar easily.
But the rule says IN PRACTICE, and the brief named the reason — "interiors are
close-quarters". So I measured the rooms an LOD would have to fire in (live, all three
venue archetypes, interiorMode driven by hand since rAF is throttled):
pub 9.7 x 9.7m, diagonal 13.7m, 12522 tris, 38 draws
band_room 8.9 x 9.6m, diagonal 13.0m, 11699 tris, 35 draws
rsl 12 x 9.4m, diagonal 15.2m, 15115 tris, 38 draws (the biggest)
VERDICT: practical win = 0 tris. A player can NEVER be more than 15.2m from the band —
corner-to-corner in the largest venue, and the stage sits at one end so the real max is
shorter. An LOD is a distance trade; inside a <=15.2m room the band is never small — it
is the subject of the gig and of F's tour money shot. Any sane threshold (15-25m) never
fires; an aggressive 8m one fires in half a room at a distance where a 3-4k _lo is
visibly worse with no perceptual cover. The win isn't "small", it's STRUCTURALLY ZERO —
the distance an LOD needs does not exist in this game. Off the backlog forever.
No budget motivates it either: a venue interior is ~12-15k tris, ~85k with the band —
inside the 200k stress ceiling E's R22 tri diet restored, at 35-38 draws vs <=350.
SIDE-OBSERVATION for E (not a proposal, no breach motivates it): all five instruments
are EXACTLY 14,000 tris — a decimator target, not a measurement of the objects. A mic
stand does not need 14k. If instrument tris ever do drive a real breach, the lever is a
flat re-decimation by object complexity (mic stand -> ~1k), which beats any LOD because
it needs no distance. Filed so the next tri hunt starts from it.
Spike 1 (ledger #1) pending E's lean.glb — look.glb has landed, lean.glb not yet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
47f05ecaa8 |
Lane D R23 (v5.0-alpha): the GIG_RANGE chunk-neighbour fix — scoped to the gig path (ledger #6)
My carried v4.x finding, fixed post-release as scheduled. Runtime-only: no plan, no
golden, no flag, no fetch. selfcheck ALL GREEN 161300/161300, 0x3fa36874 frozen.
THE FINDING GREW WHILE IT WAITED: filed at 8.7% (measured at katoomba's isolated pub);
A's R21 cluster bias made it WORSE — venues now sit inside the retail cluster where peds
converge from every side, so 42.6% of in-gig-range peds (5094/11971) were chunk-blind.
THE OVERRIDE (measurement wins): the brief asked for "extend to chunk + 8 neighbours"
AND "byte-identical flags-off". I built the literal version and measured that those
cannot both hold: on the synthetic town (what ?classic=1 boots, gig layer absent) a full
3x3 scan sourced 127 of 855 finds (14.9%) from neighbour chunks — finds v2 never made.
The frozen v2 crowd would shop ~15% more. Covenant breach, in a clause of the same brief.
So the fix is scoped to the GIG path — which is what I actually filed:
- ordinary shops: own chunk only (v2 semantics, frozen — noticed from its own block)
- gig venues: the full 34m radius, honest across chunk edges ("follow the sound" is the
whole reason GIG_RANGE 34 > PATRON_RANGE 18)
- no gig on -> _gigVenues empty -> neighbour loop skipped entirely -> ?classic and every
flags-off boot take the IDENTICAL code path and cost to v2. Byte-identical BY
CONSTRUCTION, not by measurement luck.
Both ranges < CHUNK(64) so 3x3 is exact, not approximate; fixed dz/dx order keeps ties
deterministic as the old single-list scan was.
BEFORE -> AFTER: cross-chunk in-range peds seeing the gig 0% (structural: v2 scanned only
the ped's own chunk) -> 100% (katoomba 4/4, fitzroy 11/11). Same-chunk unchanged 100%.
Classic neighbour-sourced finds: 0 (127 under the rejected full scan). Determinism
identical. 0 NaN on katoomba/fitzroy/synthetic. Sim 0.056 -> 0.057 ms/frame (+2%, i.e.
0.006% of a 16.7ms budget); lookup 0.58us unchanged with no gig, 1.3-2.7us with a gig on
(fires per PATRON_STRIDE, not per frame). Fitzroy clean at 376 peds.
CARRIED, documented: PATRON_RANGE keeps v2's own chunk-blindness — fixing it costs the
classic covenant, and the covenant wins. A frozen v2 quirk now, not an oversight.
Known minor: a scheduled-but-closed gig still runs the loop for nothing (0.58->1.3us).
D->F: no blocker for v5.0-alpha; classic untouched by construction.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
15ff53685f |
Lane D R22 (v4.0): citizens at pack scale — fitzroy stress PASS + the thin-tail clustering finding (ledger #5)
Against A's pack absorb (
|
||
|
|
01c925816e |
Lane D R21 (v4.0-beta close): relocation verify — A's venue cluster bias PASSES (ledger #4)
Verified A's venue cluster-adjacency bias (
|
||
|
|
0d992803c5 |
Lane D R20 (v4.0-beta): citizens at density — five-town verdict + the main-street relocation finding (ledger #7)
Re-ran everything against A's absorbed graph (
|
||
|
|
62cbb955b1 |
Lane D R20 (v4.0-beta): the density A/B + correcting my own sparsity misread (ledger #7, part 2)
SELF-CORRECTION first. My part-1 note called the 95-98% patronage null rate "sparsity-throttled" and made it the headline metric. Both halves were wrong: (1) it was measured at 21:00, when only 4 of 69 shops are open — retail is shut BY DESIGN, so a high night null is correct behaviour, not sparsity; (2) it sampled each town's first venue, and katoomba's is the pub — 1000m from the retail cluster with 1 neighbour. I had parked the camera on the one isolated venue in town. Same town, same seed: at the pub 99.4% null / 0 visits; on the actual main street 77.2% / 64 visits. The gig-crowd table stands (it measures the mechanism — 0 NaN, rosters, venue-win — which is location-independent); only my sparsity reading was bad. THE REAL A/B (main street, 14:00, same seed, pre-cache from git vs E's widened): hub density 8 -> 25 shops within 160m; null 90.2% -> 77.2%; total visits 17 -> 64 (3.8x); hero visits 17 -> 19; texture visits 0 -> 45; hero share 100% -> 30% of visits from 26% of shops. THE DIRECTIVE LANDS, measured from the crowd side: the secondhand heroes did NOT lose footfall (17 -> 19). The 45 texture visits are added ON TOP, not taken from them. The street is 3.8x busier while the heroes stay over-indexed. "More alive, not a different game." FILED: (a) venue placement at density — katoomba's rsl/band_room sit in the strip (13/10 neighbours) but the pub is 1000m out with 1; a gig there has no passing retail crowd. Quality observation, A/F's lane. (b) GIG_RANGE is a 34m radius but _nearestOpenShop searches only the ped's own 64m chunk — 8.7% of in-range peds are chunk-blind. Real but small; v4.x candidate, not a mid-beta hot-path change. POST numbers are vs E's committed caches but BEFORE A's absorb (11/80 still overflow- drop). Final re-run + the other four towns once A lands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
85745d2017 |
Lane D R20 (v4.0-beta): gig crowd on the five real towns — pre-density baseline (ledger #7, part 1)
The unblocked half of "citizens at density": the gig crowd's BEHAVIOUR on all five real towns' venues, measured BEFORE E's widening so the after-table is a real A/B. Density re-audit follows once E's caches + A's absorb land. BEHAVIOUR IS CORRECT ON ALL FIVE: 0 NaN everywhere; tonightRoster populates (2-7), so R14 identity continuity holds on real bones; every town generates 3 venues (pub/band_room/rsl) on night hours; and the surge works — whenever a patronage check finds any shop, the gig venue beats ordinary shopfronts (venue-win 100% on newtown/ fremantle/bendigo, 74% katoomba). Castlemaine's 40% is the 6-shop floor, not a leak: 3 of its 6 shops ARE venues, so "other" hits are mostly other venues. FINDING (quantifies Fable's ledger #2 "real towns are sparse"): the crowd is SPARSITY-throttled — 94.9-97.7% of patronage checks return null on every town, because peds spend nearly all their time in shopless chunks (katoomba: 19 shops in ~5 door-chunks of a ~78x78-chunk town). The mechanism is fine; the town has no shops per chunk. The density widening attacks exactly this — null% is my headline before/after metric. FILED (not fixed): GIG_RANGE is a 34m radius but _nearestOpenShop searches only the ped's own 64m chunk, so in-range peds across a chunk edge are blind to the gig — 8.7% of in-range ped-samples (852/9740) on katoomba. Small vs the 97% sparsity throttle; not worth a hot-path change mid-beta. Revisit if the widening leaves null% high. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
96b3dea70f |
Lane D R19 (v4.0-alpha close): fragmentation re-measure — A's ruling verified (ledger #3)
Post-fix re-measure of my R18 finding against A's committed connectivity pass
(
|
||
|
|
db33faa628 |
Lane D R18 (v4.0-alpha): citizens on real bones — audit + fragmentation finding (ledger #5)
Audited the citizen sim on real irregular street topology. E landed katoomba_real's real roads (484 ways -> 872 nodes/799 edges) mid-round, so this is measured on the real Katoomba graph plus a crafted irregular proxy. VERDICT: the CityPlan graph contract IS the contract — zero sim changes. On real Katoomba (7.2deg junctions, 1303m edge, 105 components): 0 NaN over 1,095,500 samples, peds footpath-perfect (0 off-footpath), loiter/bench-sit/patronage all fire, chunk streaming works over non-grid, determinism byte-identical (1167 identity sigs, R14 chunk-local law holds). No source touched. FILED FOR A: katoomba_real's graph is 105 components — main holds 58% of street-metres + 18/20 shops, but 42% of street-metres + 2 shops strand (~10% of near-main crowd presence lands on tiny fragments). Primary cause is expected: median fragment 71.5m from main = peripheral/bbox-clipped roads. Secondary (corroborated with Lane B on A's selfcheck fixture): per-way Douglas-Peucker drops collinear junction points + no mid-edge split — bites only the 9/85 fragments <10m from main. Reconciles with B: B verified 126 intersections form (main component); I add the global measurement (still 105 components). A fidelity knob (charter risk #4), not a blocker; sim degrades gracefully (no crash). A owns the connect-tolerance decision. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
64ded4ea01 |
Lane D R17 (v3.2): bench-sit loiter (ledger #2) — the carried R16 stretch
Street peds occasionally sit during a window-shop loiter (verandah/footpath edge). makeActor gains an opt-in setSitting with a SCALE-AWARE re-plant (the R16 spawnRig re-plant was scale-naive; the sim scales these rigs per-citizen), played only on sit so walkers/placeholders/?classic are byte-identical. Seeded via a dedicated benchsit rng stream (no shift to turn/loit/patron; identity signature unchanged). Classic inert at the source (roll gated on sitClip). In-shell (default, seed 20261990): head bone 1.466->1.070, bone span 1.667->1.299 (in seated gate [0.9,1.5]), feet re-plant to y=0 and hold through sit-idle, stand-up restores inner.y 0.929 byte-for-byte, procitySeated tagged, innerRotY:pi throughout. 9 distinct peds sat naturally per soak. Classic: fleetSitClip:false, everSat:0. Plan golden 0x3fa36874 unchanged. Draws 35/tris 6k. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6671cf08f4 |
Lane D R17 (v3.2): the drummer's pelvic-lean (ledger #1)
The R16 seated drummer sat bolt-upright (the sit clip can't carry a pelvic tilt
— Hips.quaternion is unusable on these rigs). Fix: a small constant forward torso
lean applied POST-MIX. spawnRig({seated}) caches the mid-spine bone (seatBone);
seatedLean(spine) rotates it forward ~0.34 rad each frame after the mixer resets
it (constant offset, not accumulation); band.js calls it for m.seated members.
The drummer leans into the kit — head 0.28m forward of the hips, reads as a real
drummer from the side.
Byte-identical (my signature): standing rigs get no seatBone (found only in the
seated block) and seatedLean runs for seated figs only. Verified with the lean
live — walkers 188/188 face travel, keeper standing rig (stature 1.718,
hasSeatBone:false, innerRotY pi). No existing consumer moves.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
ab7a8d0edf |
Lane D R16 (v3.1): the drummer sits + backline unification (ledger #2, #5)
Ledger #2 — drummer sits. E's sit.glb is wired into the shared rig stack: - FINDING: Fable's prescribed _rotWithHips (keep Hips.quaternion) MANGLES the pose in-shell (head folds to hip height / laid flat) — the fleet rigs' bind Hips orientation is incompatible with the Mixamo clip's, exactly what _rotOnly documents. So the sit clip rides _rotOnly (drops Hips.quaternion) like every clip; _rotWithHips removed. The seated read comes from the leg bends + a new spawnRig({seated}) foot-replant (opt-in; standing spawns skip it). - Drummer uses fleet.sitClip when present (retires SEAT_DROP), tags fig.userData.procitySeated=true (F's gate). Stature ~1.1-1.3m in [0.9,1.5]; reads seated from the crowd POV (kit hides the legs). Graceful SEAT_DROP fallback when sitClip absent (?noassets / before F wires {sit}). - BYTE-IDENTICAL proof (load-bearing): with sitClip null AND loaded, keepers are standing rigs (stature 1.718, innerRotY pi, replanted:false) and walkers 188/188 face travel. Parallel/opt-in path; _rotOnly + makeActor untouched. - F seam: loadPedFleet(base, {sit}) — pass sit:<gig active> (false under ?classic → no sit.glb fetch, classic covenant intact). Default off, graceful. Ledger #5 — backline unification. _addBackline plants E's guitar_amp at C's stage.backline[0] (== D's R15 pose, 0.75m bass clearance) instead of a hardcoded pose. C dropped its primitive ampStacks, so D owns the backline: placeholder- persists (primitive amp → GLB swap) with the primitive as the ?noassets fallback. Verified: GLB swaps, primitive under noassets, no crash, 0 fetch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
43edabfe56 |
Lane D round-7: validate ped-merge → GO for roster flip + full-density defaults + escape hatch
Lane E's R7 merge (
|
||
|
|
5db3155991 |
Lane D round-6: harden streamed roster + default-on readiness memo
Flag ?roster=stream stays default-off; v1 path byte-identical (citizen-0 = R4 golden, passes F1 flags-off regression). Full evidence memo in LANE_D_NOTES for the R7 default-on decision. - Soak (in-shell, real town): 242 chunk builds/disposes over 3 walks -> 0 GPU geom/tex delta; 16 shop enter/exit -> 0 delta; heap oscillates 50->77->54MB (GC, no leak); 188 chunk-keyed identities re-derive from seed; 0 console errors. - Hours-aware density: added setNightLivelyChunks + NIGHT_LIVELY_FLOOR so the open-late video block stays lively at night (31->16) while ordinary streets go near-empty (65->6). F call-site documented (openLate lot -> chunkKey via sim.chunkKeyAt). - Composition with ?dig=1: roster is street-tier, inert while interior/dig open (frame loop is street-branch-only); enter/exit record shops leak-free with stream on. No shared state with any v2 flag -> all-on combo safe. - Budget gap found + made safe: each decimated ped is 8 sub-meshes / 2 materials = ~7 draws/rig, so full-density stream (perChunk 16) hits 356 draws (>300 street budget). Set default perChunk 8 (291 draws, budget-safe today). The clean unlock for full-density default-on = merge ped sub-meshes by material (8->2 -> ~2 draws/rig -> perChunk 16 fits ~260); documented as R7 work, F1-safe (v1 spawn view has ~0 near-rigs). Only web/js/citizens/sim.js + web/citizens_test.html changed (+ NOTES/progress). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
93a3168a99 |
Lane D round-5: chunk-streamed roster (v2) behind ?roster=stream
Implements the R3 design note (was design-only). Default-off; the v1 whole-graph path is byte-identical when the flag is off (shell citizen-0 signature matches the R4 golden exactly). - chunk-local identity keyed (seed, chunkKey, i) — same seed + chunk -> same residents, independent of town size / visit order; home edge picked from that chunk's edges. - windowed spawn/despawn: hook-driven via Lane B's onChunkBuilt/onChunkDisposed (sim auto- detects and stops polling) + a camera-poll fallback that needs zero Lane B changes. - global near-cap + mixer stagger + rig pool + impostor layer unchanged, run across live chunks. - owner-chunk despawn (no cross-boundary re-keying); per-chunk time-of-day thinning (hours-aware). Proven on a 9x9 fixture grid: constant far-field density (~58-129 within 70m at spawn AND 150m out, vs v1's uniform ~12-15); deterministic (507 chunk-keyed identities re-derive from seed); leak-free (2 full grid walks / ~380 chunk cycles -> 0 geom/tex delta, pool capped 30); budget unchanged (near-cap 24 + 1 impostor draw, 2.31ms/frame). qa.sh --strict GREEN. Only web/js/citizens/sim.js + web/citizens_test.html changed. Flag + shell call-site documented in LANE_D_NOTES for Lane F to wire web/index.html. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a5e4b64a9d |
Lane D round-4: in-shell verify (D1) + decimated-ped validation (D2) + impostor tone-map fix (D3)
D1: peds+keepers upgrade placeholder->rig in the shell; 12 enter/exit shops leak-free (renderer.info.memory back to exact baseline); determinism holds across reload; ?noassets fully placeholder with zero ped fetches. D2 (gate-3 critical path): validated Lane E's decimated fleet — all 19 peds <=3k tris (1564-2805, avg 2450), rigs bind+animate (skinning/skeleton preserved), 0 broken meshes under eviction churn, silhouettes+identity intact, atlas bakes clean. Near fleet ~59.6k tris at the 24-cap (was ~1.2M) — F clear to re-measure gate 3. D3: fixed a real bug found only in-shell — the impostor self-tone-mapped (toneMapped:false + in-shader ACES), correct on the direct-canvas test page but DOUBLE-tone-mapped under the shell's EffectComposer/OutputPass. Reworked to a standard toneMapped:true material outputting linear via three's own tonemapping/colorspace chunks, so it matches the near rigs on both render paths. setExposure is now a no-op (exposure is global). Verified noon+night in-shell. Only web/js/citizens/impostor.js changed (+ NOTES/progress/R4 shots). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
0985b05790 |
Lane D (Citizens): round-3 support — setExposure day/night hook + design notes
Fable round-3 §Lane D (all three tasks): - sim.js: add CitizenSim.setExposure(e) passthrough so mid-tier billboards track the shell's per-segment renderer.toneMappingExposure (lighting.js animates it); stored so it survives the placeholder->rig atlas re-bake. Verified: uniform tracks 0.55<->2.3 and persists across the fleet upgrade. - Keeper GLB-rig upgrade contract verified leak-free (my side): 15 enter/exit cycles with a fleet-backed rig keeper leave renderer.info.memory geo/tex exactly at baseline. Enabling it in the shell is one arg (pass `fleet` to KeeperManager) once F's §3.4 lands. - LANE_D_NOTES: exact Lane F call sites for setExposure + keeper fleet-upgrade, and the chunk-streamed roster v1.5 design note (chunk-local identity, windowing, ownership/hand-off, budget, opt-in migration) — design only, no implementation. Code touches only sim.js; no sibling files edited. Determinism still passes, near cap 24, mixer 0.3ms, no console errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
9eb1acc61b |
Lane D (Citizens): deterministic LOD crowd — rigs/impostors/keepers + test page
Populate the town at city scale, on budget, deterministic per-citizen identity: - rigs.js — ported 90sDJsim rig stack: mixamorig canonicalisation so one shared walk clip drives all 19 peds, head-bone height-normalise, feet-plant, pooled near-tier actors with walk<->idle crossfade - impostor.js — 4-yaw sprite-atlas baker + instanced billboards: whole mid crowd in 1 draw call, tone-matched to the ACES near rigs - sim.js — deterministic roster, footpath lanes off the street graph, near/mid/far LOD with hysteresis + hard 24-cap, staggered mixer budget, time-of-day density - placeholder.js — seeded low-poly box humanoids (frame-one population + ?noassets) - keepers.js — one keeper per shop at the counter, idle + greet-turn - 21 ped GLBs (byte-identical from 90sDJsim), citizens_test.html harness, LANE_D_NOTES.md, 5 beauty shots Verified in-browser: 200 citizens at max mixer 0.2ms (budget 2ms), near capped 24, determinism holds (200 identities match seed), no T-pose, ?noassets crash-free. Consumes Lane A plan.streets with zero adapter. Six adversarial-review bugs fixed (non-deterministic fleet order, shared-resource disposal on pool eviction, impostor colour-management). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |