Gate table (LANE_F_NOTES §4) rewritten to R4 all-green with measured evidence:
1 determinism (selfcheck 1301/1301, fingerprint 0x3fa36874) · 2 soak (37 chunks/20 shops,
heap 38->38MB, 0 errors, leak-free) · 3 budget (draws 138/tris 31k, decimated peds) ·
4 asset-free (heap 13->13MB, 0 net) · 5 selfchecks (qa.sh --strict 4/4, 23 GLBs on depot) ·
6 shots (10 full-frame 1280x720, no letterbox, night closed-facade + real interiors).
shots.py: interior tour shots (record/opshop) now capture via DBG.enterShop(id) directly —
they were passing {type} to enterShop (needs id) then calling shot() (which forces street
mode), so both showed streets. Now they show the themed interiors with keeper + hero props.
Verified by a 6-auditor adversarial v1-readiness workflow -> GO.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
179 lines
13 KiB
Markdown
179 lines
13 KiB
Markdown
# PROCITY — Lane F progress (INTEGRATION & QA)
|
||
|
||
**Session:** 2026-07-14 · **Author:** PROCITY-F · **For review by:** fable
|
||
|
||
---
|
||
|
||
## 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`.
|