# PROCITY — Lane F progress (INTEGRATION & QA) **Session:** 2026-07-14 · **Author:** PROCITY-F · **For review by:** fable --- ## Round 5 (v1.1 close-out + v2 foundations) — IN PROGRESS Lane F role: **v1.1 watch** + v2 flag-seam wiring + QA-harness-for-v2 + shared-tree marshal. Full tracking in [`LANE_F_NOTES §10`](docs/LANES/LANE_F_NOTES.md). | task | status | |---|---| | **fal un-park check** | ✅ Verified already done — `039c179` un-parked fal in Lane E's brief (decision #4 + Lane E task 3: glass-case + bus-shelter + optional magazine-rack, ≤2 attempts, costs logged in AUDIT.md). **Nothing for F to change.** | | **archive R3/R4 instruction claims** (F4) | ✅ Added "SUPERSEDED by R5" banner to `ROUND3_INSTRUCTIONS.md` + `ROUND4_INSTRUCTIONS.md`. | | **v2 flags table** (F4) | ✅ Scaffolded in LANE_F_NOTES §10 (`?plansrc=osm` A, `?winmap=1` B, `?dig=1` C, `?roster=stream` D) — all pending owning-lane specs. | | **F1 tag v1.1** | ✅ **TAGGED.** C1 (`aa9c140`: record_crate fixed + counter_till re-map) + E1 (`c522464`: 6 hero props baked 288k→48k, ≤8k each, live on depot) landed. Verified: depot serves baked props (counter_till 7999, drinks_fridge 8000, listening_booth 7986 tris ≤8k), C's `glb.js` maps them, record/opshop interiors render the **counter_till GLB** with keeper stand pose working + no double till, bins upgraded. Re-captured the 2 interior tour shots (fresh chromium → baked props). qa GREEN. `git tag v1.1` (local). | | **F2 wire `?dig=1`** | ✅ **DONE + verified.** C shipped `dig.js` + the flag but left the in-game input/mode hook to F (LANE_C_NOTES §C2). Wired the consumer pattern into `interior_mode.js` (F-owned): aim at a `userData.kind==='bin'` fitting + press **E** → `createDig`/`dig.open` (per-bin seed via `binSeed(shop.seed,pos)`); the dig owns the frame (render `dig.scene`, no interior walk); WALK OUT / Esc closes → back to the room. Shell seam (`index.html`): `?dig=1` → `dig:` opt; `procity:digOpen` releases pointer-lock (riffle is cursor-driven); unlock→leaveShop guard reads `interiorMode.digActive` so opening a bin ≠ leaving. **Fresh-chromium smoke:** E opens riffle (seeded sleeves + prices render), WALK OUT closes to interior, **leak-free** (steady-state geo/tex flat over 3 cycles), **0 console errors**. Flag off ⇒ no listener/no dig ⇒ byte-identical to v1. | | **F2 — other v2 seams** | B `?winmap` / D `?roster=stream` are self-contained (no shell input hook needed); smoked clean (boot, 0 errors, budget OK). A `?plansrc` not taken. | | **F3 v2 QA harness** | ⏳ determinism gate (first-interior-hash per seed) · flags-off regression check (v2-prime-law enforcement) · v2 smoke → qa.sh warn-gate. Build as flags land. | Base state: v1.0 (`2698b40`), `qa.sh --strict` GREEN 4/4, tree clean. --- ## Round 4 (v1-tag round) — DONE ✅ (all 6 gates green; v1.0 tagged) Executed Fable's `ROUND4_INSTRUCTIONS.md` Lane F tasks. All lanes committed R4; a 6-auditor adversarial v1-readiness workflow returned **GO**; `v1.0` tagged locally on the F finalization commit. | task | status | |---|---| | **F1 setExposure** | ✅ Wired (`9416d0a`) **then correctly removed** (`aad9baa`): D3 (`a5e4b64`) made the impostor `toneMapped:true`, so `citizens.setExposure()` became a no-op tone-mapped globally via `renderer.toneMappingExposure`. Removed only *after* D committed (removing earlier would regress night brightness). Final state: no dead call. | | **F2 storeys-checker** | ✅ `permittedMax = max>=2 ? min(max+1,3) : max` (Lane A's rule, `9416d0a`). Consistency **0 warnings** across 6 seeds; single-storey-type-at-2 still trips. **A confirmed** (`5b8c806`). | | **F3 gate-3 budget** | ✅ **PASS.** E1 decimated peds (`518678d`, 924k→46k, ≤3k each) + **D2 sign-off** (`a5e4b64`, fleet ≈59.6k at 24-cap). Official measure: busiest node, pop 200, midday, 12-yaw peak → **draws 138 (≤300) · tris ~31k (≤200k)**. Baseline 372k. | | **F4 gate-6 shots** | ✅ **PASS.** Against committed B2 (`6323d58`, `dbg.js` letterbox+poses): `shots.py v1_tour` → **10 full-frame 1280×720, no letterbox**; §3.5 **night closed-facade** (CLOSED plates + lit openLate video "VIDEO REGAL") + real **record/opshop interiors** (keeper + hero props). Fixed `shots.py` so interior shots capture via `enterShop(id)` (were falling back to a street bookmark). | | **F5 tag v1.0** | ✅ **TAGGED** on the F finalization commit (gate table all-green + shots committed). Local only — John pushes. | | **audit** | 6-auditor v1-readiness workflow: 5 GREEN (gates 1/3/5/6 + release hygiene) + 1 procedural "land finalization commit first" → resolved. GO. | --- ## 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`.