# PROCITY — Lane F progress (INTEGRATION & QA) **Session:** 2026-07-14 · **Author:** PROCITY-F · **For review by:** fable --- ## Round 4 (v1-tag round) — IN PROGRESS Executing Fable's `ROUND4_INSTRUCTIONS.md` Lane F tasks. F1+F2 done & committed; F3/F4 gated on other lanes' critical-path work (E1 ped decimation, B2 shot-harness fix); F5 (tag) follows. | task | status | |---|---| | **F1 setExposure wire** | ✅ **DONE** ([`index.html:245`](web/index.html)) — `citizens.setExposure(renderer.toneMappingExposure)` after `setTimeOfDay`. Boots clean, 0 console errors, exposure animates night 1.18↔midday 0.98. Awaiting D3 verify. | | **F2 storeys-checker fix** | ✅ **DONE** — `permittedMax = max>=2 ? min(max+1,3) : max` (Lane A's rule). Consistency **0 warnings** across 6 seeds; single-storey-type-at-2 still trips. Awaiting A1 confirm. | | **F1+F2 commit** | ✅ `9416d0a` (only my 2 files, atomic), ref `lane-f/round4-wireups`. `.gitignore` (Lane E's `.peds_orig/`) left unstaged. | | **F3 gate-3 tris re-measure** | ✅ **PASS (OFFICIAL).** E1 committed decimated peds (`518678d`, 924k→46k tris, ≤3k each); **D2 signed off** (rigs bind/animate, no explosions, silhouettes read, fleet ≈59.6k at the 24-cap). Re-measured busiest node, pop 200, midday, 12-yaw peak, committed peds → **draws 138 ✅ (≤300) · tris ~31k ✅ (≤200k)**. Baseline was 372k. Gate 3 green. | | **F1 follow-up (D3)** | D3 found+fixed a real double-tone-map bug and stubbed `impostor.setExposure` → my F1 call is now a no-op. Will **remove the dead line at finalization, AFTER D commits** the impostor fix (removing before would regress night brightness in the committed tree). | | **F4 gate-6 shots** | 🟡 **PROVISIONALLY PASSING; awaiting B2 commit to finalize.** B2's `dbg.js` (letterbox `syncSize()` + the 3 new poses `crossroads_busy`/`residential_collar`/`warehouse_fringe`) is done on disk (uncommitted). Ran `shots.py v1_tour` → **10 full-frame 1280×720 shots (no letterbox)**, all poses resolve, night emissives + legible signs, decimated peds render human-scale. Re-capture + commit once B commits `dbg.js` (and B1's closed-facade night shot once B1 lands). | | **F5 tag v1.0** | ⏳ pending gates 3+6 finalized against **committed** upstream + D2 sign-off. qa.sh --strict GREEN 4/4 (static gates). Both blocking gates provisionally verified — tag is close. | --- ## Round 3 (lead lane) — DONE, verified live Executed Fable's `ROUND3_INSTRUCTIONS.md` Lane F tasks. All wiring verified in-browser on seed 20261990. | task | result | |---|---| | **§3.5 hours / closed shops** | `isOpen()` gate on `enterShop`. Midday: open. **Night (22:00): all closed except the openLate video rental** (Video Regal [11,23]) — verified toy shop blocked, video enters. | | **§3.4 `?noassets`** | **Zero network** (Perf API: 0 GLB/depot/manifest/ped-model requests); 100% primitive, legible. | | **§3.4 interior GLB** | `useGLB` → fitting GLBs load from the **3GOD depot** (bookshop shelves, +8 meshes, visually confirmed). | | **§3.4 rig fleet** | 19 ped GLBs → peds **and** keepers upgrade placeholder→**GLB rigs**; **leak-free** (shared-cache proven, cycle2/3 flat). | | **`--depot` on qa.sh** | `validate_manifest.py --depot` = 0 err (16 GLBs live). **qa.sh GREEN 4/4.** | | **Gate 2 soak** | **PASS** both modes — assets: 20 interiors leak-free (+GLB-cache warmup), heap 98MB stable; noassets: 37 chunks, heap 15MB. 0 console errors. | | **Gate 4 asset-free** | **PASS.** | | **Gate 6 shots** | `docs/shots/v1_tour/` (10 shots) + contact sheet captured; letterbox + 3 fallback bookmarks are Lane B dbg.js. | **Findings → other lanes** (details in [`LANE_F_NOTES §9`](docs/LANES/LANE_F_NOTES.md)): - **D/E:** rig ped GLBs are **tri-heavy** (~45k each) → gate 3 tris **~279k > 200k** budget (draws fine ~200/300). Decimate the ped GLBs; F holds `?pop=140` until then. - **B:** add 3 shots bookmark poses; fix the headless composer letterbox in `DBG.shot()`; render the §3.5 closed-facade visual (dark windows + CLOSED plate; predicate `window.PROCITY.isOpen`). - Fixed **5 F-owned harness bugs** so `shots.py`/`soak.py` actually run (DBG async-poll, `DBG.plan`→`PROCITY.plan`, `enterShop` bare-id, `shop.lot` is an id, midday-pin + GLB-cache warmup + budget→warning). **Git:** working tree synced to canonical `main` (862bbcd) mid-session — my R2 work is committed as `aa4ed4f`. R3 edits below are staged by pathspec (see Housekeeping). Nothing pushed. --- ## TL;DR (round 2 — for context) All five lanes (A–E) landed; F stood up the QA harness, **adversarially reviewed and fixed its own tooling**, then wired the lanes into **a walkable, living town** — interiors, shopkeepers, and street crowds all integrated and verified live: 1. **Interiors — every door opens (§3.2).** A door opens into a themed, seeded, self-lit 90s-AU interior; walk it, walk back out (or Esc), room disposes. Verified across **all 9 shop types**, **leak-free**, worst build **8.4 ms**. F-owned bridge [`web/js/world/interior_mode.js`](web/js/world/interior_mode.js). 2. **Shopkeepers (§3.3a).** A keeper stands at the counter of every shop and **turns to greet** you; disposed with the room, **leak-free over 5 cycles**. (Asset-free placeholder; rig-fleet upgrade later.) 3. **Street crowds (§3.3b).** Deterministic pedestrians walk the footpaths (`graph = plan.streets` directly), density follows time-of-day (busy midday, empty at night), LOD-tiered. **Draw budget holds** — worst main-street view **~191 draws** (budget 300). Shell wiring in [`index.html`](web/index.html). 4. **Plan swap (§3.1)** + **facade skins fix** (prior pass): boots on Lane A's real town, textured. `tools/qa.sh` is **GREEN (4/4 gates, 0 skipped)**. Remaining: manifest GLB upgrades + `?noassets` (§3.4 — also upgrades keepers/peds to shared rigs), hours/closed-shops (§3.5), draw-budget shave. Scoped in [`docs/LANES/LANE_F_NOTES.md`](docs/LANES/LANE_F_NOTES.md) §3.4–§3.5,§7. --- ## Lane readiness — ALL COMPLETE ✅ (`node tools/qa/scaffold_check.mjs`) | Lane | status | notes | |---|---|---| | A CITYGEN | **5/5** | plan.js, registry.js, names.js, selfcheck.js, map.html — determinism gate green, verified in-browser | | B STREETSCAPE | **4/4** | index.html shell, chunks.js streamer, buildings.js, fixture_plan.js — walkable town verified live | | C INTERIORS | **2/2** | interiors.js (`buildInterior`), interior_test.html | | D CITIZENS | **3/3** | rigs.js, sim.js (`CitizenSim`), keepers.js (`KeeperManager`), citizens_test.html | | E ASSETS | **3/3** | manifest.json (validates green), validate_manifest.py, AUDIT.md + pipeline | --- ## What F built / did this session ### QA harness (F-owned, `tools/`) — trustworthy, all green | file | what | state | |---|---|---| | `tools/qa.sh` | gate runner; `--strict` = v1 umbrella | ✅ 4/4 green | | `tools/qa/scaffold_check.mjs` | scaffold + PRNG determinism (golden-locked) + live readiness matrix + plan-determinism | ✅ | | `tools/qa/consistency_check.mjs` | cross-lane gate: plan ↔ registry ↔ assets ↔ manifest | ✅ | | `tools/shots.py` · `tools/soak.py` | Playwright beauty-tour + 10-min soak/budget/`--noassets` (gates 2,3,4,6) | ✅ ready; need Lane B `window.DBG` hook (§4) | ### Adversarial self-review (Workflow, 23 agents) Ran a 4-auditor + verifier workflow against F's own scripts + runbook. It confirmed **14 real defects in F's tooling** (false-confidence checks + wrong API assumptions). **All applied:** - `scaffold_check`: JSON round-trip was a **tautology** (fixed → real deep-compare w/ `-0` norm); Math.random-ban regex had **false negatives** (fixed → anchored to comments); irange golden check re-seeded per draw (fixed → single stream). - `consistency_check`: added a **storeys-vs-registry-range** check, fixed a dead late-night branch, removed a dead metric. - `soak.py`: heap heuristic no longer silently passes when heap isn't reported; shop count now requires **verified interior loads** (not just `enterShop` calls); `--minutes` now honored. - `shots.py`: fixed an `IndexError` on a trailing `--seed`. - **Runbook** (`LANE_F_NOTES.md`): corrected against the **real landed APIs** — `chunkIndex` returns `{chunkSize,chunks}` (not callable); chunks is a `createChunkManager` **factory** with no lifecycle hooks; `CitizenSim` is **graph-driven, not per-chunk**; keepers use `spawn/remove/disposeAll`. ### Integration passes (verified live in-browser) - **`web/js/world/interior_mode.js`** (new F-owned bridge) + thin marked seam in `index.html` → **§3.2 interiors: every door opens.** `enterShop` looks the shop up in the plan, attaches its lot dims, calls Lane C `buildInterior`, and switches to a new `interior` mode that renders the room in its own scene and walks it via the room's occupancy grid. Exit on walk-out / `procity:exitShop` / Esc → `dispose()` + player restored to the door. **Verified:** door → Toy Shop renders; exit state-machine correct; **leak-free** (134 geo/37 tex → 217 loaded → 134/37 after dispose); all **9 shop types** `ok+pathOK`, worst build **8.4 ms**; **0 console errors**. - **Keepers (§3.3a)** — wired into `interior_mode.js`: `KeeperManager` (no fleet → placeholder actor), spawned at the counter stand pose (`places.find(p=>p.userData.keeperStand)`), ticked in the interior loop, `disposeAll()` on exit. **Verified:** 11-mesh keeper at the counter, **greets** the player (turns 0.21 rad, eases back), **leak-free over 5 cycles/5 types** (net growth 0). - **Citizens (§3.3b)** — `CitizenSim` in `index.html`: `graph = plan.streets` (no adapter needed), `setPopulation(140)` (`?pop=`), `setTimeOfDay((seg+frac)/6)` + `update(dt)` in the street loop, `visibilitychange→setPaused`. Fixed a NaN bug (`getClock().hour` is a string). **Verified:** 96 active midday, peds walk footpaths ~1.5 m/s, budget-safe (worst **~191 draws** across all main edges). - **`web/js/citygen/index.js`** (barrel) → game boots on Lane A's real generated town (was the fixture). Verified: console "using Lane A generatePlan", HUD "Boolarra Heads · 493 shops". - **`web/js/world/skins.js`** (1-line chokepoint fix) → `facadeMat` normalizes full-filename skins. Verified: `facade-*.jpg` requests now **200 OK**, town textured (was all flat-grey). ### Docs (F-owned) - `docs/LANES/LANE_F_NOTES.md` — integration runbook (real APIs, wiring steps, QA gates, DBG hook request). - `docs/V2_IDEAS.md` — parked scope (content firehose, override layer, weather, venue, …). - `docs/shots/` — reference-shot tree (the other lanes are already dropping acceptance shots into it). --- ## Findings for the lanes (F flags; the two blocking-visual ones are already fixed) | # | lane | finding | status | |---|---|---|---| | 1 | B | shell imported non-existent `js/citygen/index.js` → ran on fixture | **fixed by F** (barrel) | | 2 | B | `skins.js facadeMat` double-wrapped full-filename skins → facades 404 | **fixed by F** (normalize) | | 3 | B | street measures **~334 draw calls** at spawn (radius 3) — over CITY_SPEC ≤300 | open — shave (radius 2 or more merging) | | 4 | A | ~10% of shop names have a **doubled possessive** ("Tex's's Toys") — `names.js` | open (cosmetic) | | 5 | A | some shops have **storeys outside the registry type range** (e.g. video at 2, range [1,1]) | open — confirm corner-anchor intent | | — | contract | `facadeSkin` is a full filename in the registry but skins.js expected a bare key | **worth a CITY_SPEC line** so ground/awning/interior skins avoid the same trap | --- ## Remaining integration (scoped in LANE_F_NOTES §3; ready to execute) 1. ✅ ~~**Interiors (§3.2)**~~ — **DONE**. 2. ✅ ~~**Citizens + keepers (§3.3)**~~ — **DONE** (both verified live; see Integration passes above). 3. **Manifest + `?noassets` (§3.4)** — GLB upgrades from `manifest.json`; primitive-fallback flag. Doubles as the **rig-fleet upgrade** that makes keepers/peds cheap (shared meshes) so `?pop=` can rise. 4. **Hours / closed shops (§3.5)** and the **draw-budget shave** (finding 3). 5. **Full QA gates 1–4,6** once Lane B exposes the `window.DBG` hook (§4) my harnesses drive. *Next natural step is §3.4 (manifest + `?noassets`) — it's the asset-free gate AND the fleet upgrade that upgrades placeholder keepers/peds to shared GLB rigs. §3.5 (hours) is a small data-driven follow-on.* **Note on verification:** pointer-lock doesn't engage in the automated browser, so a real *walk* is best playtested by a human (`cd web && python3 -m http.server 8130` → `localhost:8130?seed=20261990`). F drives/inspects via `window.PROCITY` + JS for programmatic checks. ## Housekeeping - Nothing committed (all working tree). F's edits are minimal, commented `[Lane F integration]`, reversible. **New F-owned file:** `web/js/world/interior_mode.js` (interior + keeper bridge). Shell seam edits in `index.html`: interior wiring (import, bridge create, `enterShop`/`leaveShop`, loop branch, `setMode` lock, Esc-exit, M/P guards, `window.PROCITY` hooks) + citizens (import, `CitizenSim` create + `setPopulation`, street-loop `setTimeOfDay`+`update`, `visibilitychange` pause). Also edited: `skins.js` (facade fix, prior pass). Suggested commit once reviewed — **use a pathspec** (lanes share one tree, see memory): `git commit -- web/js/world/interior_mode.js web/index.html web/js/world/skins.js web/js/citygen/index.js tools docs/LANES/LANE_F_NOTES.md docs/V2_IDEAS.md docs/shots F-progress.md` msg `Lane F: integration — interiors + keepers + street peds + QA harness + barrel + skins fix`. - A local `python3 -m http.server 8130` is running for the smoke test (harmless; kill when done). - Lane prompts hard-code `/Users/jing/Documents/PROCITY`; real path is `/Users/m3ultra/Documents/procity`.