PROCITY/F-progress.md
m3ultra 53f472d0d7 Lane F R3: hours/closed-shops + manifest/rig-fleet/?noassets + --depot + QA harness fixes
§3.5 hours: isOpen() gates enterShop — closed shops locked; at night only the openLate video
rental opens. §3.4: ?noassets (zero-network primitive path, verified via Performance API),
interior fitting GLB upgrades from the 3GOD depot (useGLB), and the rig-fleet upgrade
(models/peds/*.glb) so peds + keepers become shared GLB rigs, leak-free (shared loadGLB cache
proven, not a leak). qa.sh manifest gate now --depot (16 GLBs live) — GREEN 4/4.

Browser QA harness fixes so shots.py/soak.py actually run: DBG async-poll (was racing the async
install), plan via window.PROCITY (DBG.plan unexposed), enterShop bare-id, shop.lot is a lot id,
midday pin (§3.5 else closes shops mid-walk), GLB-cache warmup, budget peaks -> warnings (gate 3
clean pass is authoritative). Gate 2 soak PASS both asset modes; gate 4 asset-free PASS;
docs/shots/v1_tour/ (10 shots) + contact sheet captured.

Findings (LANE_F_NOTES §9): D/E decimate tri-heavy ped GLBs (gate 3 tris ~279k > 200k budget;
draws fine ~200/300). B: add 3 shots bookmark poses, fix headless composer letterbox in
DBG.shot(), render the §3.5 closed-facade visual (predicate window.PROCITY.isOpen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 17:19:11 +10:00

163 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PROCITY — Lane F progress (INTEGRATION & QA)
**Session:** 2026-07-14 · **Author:** PROCITY-F · **For review by:** fable
---
## 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 (AE) 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 14,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`.