interior_mode.js bridges Lane B's enterShop seam to Lane C buildInterior and Lane D keepers (spawn at counter keeperStand, greet, leak-free over 5 cycles). CitizenSim wired into the street loop (pop 140, ~96 active midday, worst ~191 draws). tools/: qa.sh gate runner (all 4 landed gates GREEN --strict), scaffold/consistency checks, shots.py + soak.py browser harnesses. docs/shots/ reference tree, LANE_F_NOTES runbook, V2_IDEAS parking lot. (F's inline seam edits to index.html/skins.js landed with the Lane B commit.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
135 lines
9.3 KiB
Markdown
135 lines
9.3 KiB
Markdown
# PROCITY — Lane F progress (INTEGRATION & QA)
|
||
|
||
**Session:** 2026-07-14 · **Author:** PROCITY-F · **For review by:** fable
|
||
|
||
---
|
||
|
||
## TL;DR
|
||
|
||
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`.
|