Lane F R10: verify giant-rig fix + re-shoot tour + re-frame night_crowd

Verified Lane D's R10 buildFigure span-normalize fix: qa.sh --strict GREEN 6/6 incl. the new
no-giants scale gate (24 interior figs / 6 shops all crown 1.4-2.0m, under-ceiling). The 3.83m I
first measured live was a STALE ES-module cache in a day-old browser tab, not a regression
(served rigs.js + fresh-chromium gate both correct).

Re-shot the v2 tour on the fixed tree: browsers.png now shows human-sized figures (browser at the
rack + keeper at the counter). night_crowd.png re-framed to a readable clean-night "lit VIDEO REGAL
amid CLOSED town" (pulled out of the rain group; reuses night_neon's tighter dist-12 pose).

Honest finding: night_crowd has no visible street crowd and can't without new work. Lane D's night
patronage parks ducked-in patrons hidden INSIDE the shop (they are the interior browsers), and this
seed's video shop is a low-traffic corner (tested: 0 patronage / 0 visible at night). Flagged for D;
a visible outdoor night queue is a v3 mechanic. ~20fps in night captures is a headless software-GL
artifact (scene is light: 128 draws / 65k tris).

Full-default soak PASS (heap 54MB stable, no perf drift, 0 errors). Tour README updated with stable
v2 filenames. v2.0 annotated tag staged separately (push held for John — public release + the
night_crowd caveat on his flagged money shot).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-15 13:56:23 +10:00
parent 3432fccd1f
commit 9b1c54ea81
15 changed files with 76 additions and 28 deletions

View File

@ -4,7 +4,34 @@
--- ---
## Round 9 (the v2.0 ship round) — DONE ✅ (v2.0 tagged) ## Round 10 (fix the R9 giant-rig blocker, re-shoot, re-tag) — verify + ship
R9 shipped a blocking regression: interior rig figures came out ~2× room scale (keeper head 3.83 m in
a 3.4 m room) because `rigs.js buildFigure` normalized off the head bone's **bind-pose** Y. **Lane D
fixed it** (R10, commit `3432fcc`): normalize by the feet→crown **span**, plus a new `qa.sh --strict`
no-giants gate (`interior_scale_check.py`). Lane F verify + re-shoot + soak + re-tag:
| task | result |
|---|---|
| **F1 — verify the fix** | ✅ `qa.sh --strict` **GREEN 6/6** incl. the new scale gate: **24 interior figs / 6 shops all crown ∈ [1.4,2.0] m and under-ceiling** (Second Time Redfern, the giant scene: 1.661.86 m). Live-measured too — the 3.83 m I first saw was a **stale ES-module cache in a day-old browser tab**, not a regression (served + fresh-chromium code both correct). |
| **F2 — re-shoot** | ✅ `browsers.png` re-shot: browser at the rack + keeper at the counter, **human-sized** (*figures human-sized vs door/fittings: yes*). `night_crowd.png` re-framed to a readable "lit VIDEO REGAL amid CLOSED town" — **see the honest note below.** |
| **F3 — soak** | ✅ full-default soak **PASS**: 37 chunks, 20 shops, **heap 54 MB stable (no perf drift** from the keeper fix — it's a build-time scale calc), draws 248, **0 errors**. Tri budget still ~327k > 200k (pre-existing rig-model item, D/E decimation — not an R10 change, not the blocker). |
| **F4/6 — docs** | ✅ tour README updated with stable v2 filenames + captions; this addendum is the R10 release note. |
| **F5 — tag** | ⏸ `v2.0` annotated tag staged on the fixed commit; **holding the push for John** given the night_crowd finding (a public release + his flagged money shot). |
**Honest finding — `night_crowd` has no crowd, and it can't without new work.** John flagged it as
near-black/empty. Re-framed it readable (clean night, tight on the neon). But a visible *street* crowd
does not form: Lane D's night patronage parks ducked-in patrons **hidden inside** the shop (they are
the interior browsers in `browsers.png`), and seed 20261990's video shop is a **low-traffic corner**
(tested default streamed roster + patronage-on at night: **0 patronage, 0 visible peds** at the shop).
This is not a framing bug and not (clearly) a regression — it's that the "night crowd" was always the
*interior* presence. A visible outdoor queue is a **v3 Lane-D mechanic** (loiter-outside-the-openLate-
shop). The ~20 fps in night captures is a **headless software-GL artifact** (128 draws / 65k tris is light).
→ Flagged for D: confirm night patronage at the openLate shop still behaves as the v2.0-rc notes claim.
---
## Round 9 (the v2.0 ship round) — DONE (v2.0 tag pulled, re-tagged in R10)
All lanes landed (C browse points + buy-anywhere, D browser rigs, A CITY_SPEC freeze + closing-time All lanes landed (C browse points + buy-anywhere, D browser rigs, A CITY_SPEC freeze + closing-time
ruling, E VRAM audit + half-res book/toy atlases, B tram + tour bookmarks). F wired the one cross-lane ruling, E VRAM audit + half-res book/toy atlases, B tram + tour bookmarks). F wired the one cross-lane

View File

@ -4,31 +4,44 @@ Owned by Lane F (each lane also drops its own acceptance screenshots here).
``` ```
docs/shots/ docs/shots/
laneA/ … A: 5 seeds rendered in map.html (spine, arcade, market, milkbars) laneA/ … laneE/ … per-lane acceptance screenshots (each lane owns its dir)
laneB/ … B: 3 fixed street cameras (P-key shot harness) v1_tour/ … F: the v1 beauty shots (tools/shots.py) — frozen devlog set
laneC/ … C: 9 types × 5 archetypes interior grid v2_tour/ … F: the v2 tour (tools/v2_tour.py) — the CURRENT canonical set (see below)
laneD/ … D: near / mid tiers + busy main street before/ … F: last known-good capture, for side-by-side regression
laneE/ … E: skin contact sheets (new skins vs originals) references/ … real-world reference photos named per shot
v1_tour/ … F: the 10 beauty shots (see tools/shots.py TOUR) — the devlog set v2_contact.html … generated contact sheet for the v2 tour
before/ … F: last known-good capture, for side-by-side regression
references/ … real-world reference photos named per shot (street_noon.jpg, arcade.png, …)
contact.html … generated by tools/shots.py — this-run | before | reference
``` ```
## Capture (Lane F, once Lane B's shell + `window.DBG` hook land) ## v2 tour — stable filenames (do not rename; the v3 site links these)
``` `cd web && python3 -m http.server 8130` then `tools/.venv/bin/python tools/v2_tour.py`
cd web && python3 -m http.server 8130 # terminal 1 → 1280×720 PNGs in `v2_tour/` + `docs/shots/v2_contact.html`.
python3 -m venv tools/.venv # once
tools/.venv/bin/pip install playwright
tools/.venv/bin/python -m playwright install chromium
tools/.venv/bin/python tools/shots.py v1_tour --seed 20261990 # terminal 2
open docs/shots/contact.html
```
Before a risky change, snapshot the good state into `before/` | file | what it documents |
(`tools/.venv/bin/python tools/shots.py before`), then re-run and eyeball `contact.html`. |---|---|
| `street_noon.png` | main strip at midday |
| `crossroads_busy.png` | busiest intersection, peds about |
| `shopfront_detail.png` | verandah + sign + window up close |
| `patronage_door.png` | streamed peds at an open shop's door (Lane D patronage) |
| `rain_verandah.png` | rain outside a lit `?winmap` video-shop window |
| `rain_street.png` | wet strip, rain down the street |
| `tram_stop.png` | the v2 tram paused at a shelter (`?tram=1`) |
| `night_crowd.png` | **VIDEO REGAL glowing amid CLOSED neighbours at night** — the §3.5 hours story (clean-night boot). **NB:** no visible street crowd — see the note below. |
| `browsers.png` | **an occupied shop's interior life** — a browser at the rack + the keeper at the counter, both human-sized (R10 giant-rig fix). *figures human-sized vs door/fittings: yes.* |
| `dig_real.png` | riffling a real-cover record bin (`?dig=1&stock=real`) |
| `katoomba_main.png` | plan-agnostic main strip (`?plansrc=osm&town=katoomba`) |
The v1 tour list (LANE_F_INTEGRATION §Shots): main-street noon, arcade, market square, ### Note on `night_crowd` (Lane F, R10)
milkbar dusk, night neon, warehouse fringe, residential collar, record interior, opshop Re-framed to the tighter, readable "one lit shop in a closed town" composition. It does **not** show a
interior, busy crossroads. Adjust `TOUR` in `tools/shots.py` as the town evolves. standing street crowd, and that is not a framing bug: Lane D's night patronage parks ducked-in patrons
*hidden inside* the shop (they become the interior browsers seen in `browsers.png`), and seed 20261990's
video shop sits on a low-traffic corner, so none gather visibly outside (tested: 0 patronage / 0 visible
at night). The town's night life is the interior presence + the neon-vs-CLOSED mood. A visible outdoor
night queue would need a new Lane-D mechanic (loiter-outside-the-openLate-shop) — parked for v3. The
~20 fps in night captures is a **headless-chromium software-GL artifact** (the scene is light, ~128
draws / 65k tris); on real hardware the night scene is not a perf concern.
## Regression workflow
Before a risky change, snapshot the good state into `before/`, then re-run `v2_tour.py` and eyeball
`v2_contact.html`. **Process rule (R10): any shot containing a humanoid gets an explicit
"figures human-sized relative to doors/fittings: yes" line in the progress note — actually look.**

View File

@ -1 +1 @@
<!doctype html><meta charset="utf-8"><title>PROCITY v2.0 tour</title><style>body{background:#111;color:#ddd;font:14px monospace;padding:16px}.g{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}figure{margin:0}img{width:100%}figcaption{color:#8f8;padding:3px 0}</style><h2>PROCITY v2.0 — 11 shots</h2><div class="g"><figure><img src="rain_verandah.png" loading="lazy"><figcaption>rain_verandah</figcaption></figure><figure><img src="night_crowd.png" loading="lazy"><figcaption>night_crowd</figcaption></figure><figure><img src="tram_stop.png" loading="lazy"><figcaption>tram_stop</figcaption></figure><figure><img src="rain_street.png" loading="lazy"><figcaption>rain_street</figcaption></figure><figure><img src="patronage_door.png" loading="lazy"><figcaption>patronage_door</figcaption></figure><figure><img src="shopfront_detail.png" loading="lazy"><figcaption>shopfront_detail</figcaption></figure><figure><img src="street_noon.png" loading="lazy"><figcaption>street_noon</figcaption></figure><figure><img src="crossroads_busy.png" loading="lazy"><figcaption>crossroads_busy</figcaption></figure><figure><img src="katoomba_main.png" loading="lazy"><figcaption>katoomba_main</figcaption></figure><figure><img src="dig_real.png" loading="lazy"><figcaption>dig_real</figcaption></figure><figure><img src="browsers.png" loading="lazy"><figcaption>browsers</figcaption></figure></div> <!doctype html><meta charset="utf-8"><title>PROCITY v2.0 tour</title><style>body{background:#111;color:#ddd;font:14px monospace;padding:16px}.g{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}figure{margin:0}img{width:100%}figcaption{color:#8f8;padding:3px 0}</style><h2>PROCITY v2.0 — 11 shots</h2><div class="g"><figure><img src="rain_verandah.png" loading="lazy"><figcaption>rain_verandah</figcaption></figure><figure><img src="tram_stop.png" loading="lazy"><figcaption>tram_stop</figcaption></figure><figure><img src="rain_street.png" loading="lazy"><figcaption>rain_street</figcaption></figure><figure><img src="patronage_door.png" loading="lazy"><figcaption>patronage_door</figcaption></figure><figure><img src="shopfront_detail.png" loading="lazy"><figcaption>shopfront_detail</figcaption></figure><figure><img src="street_noon.png" loading="lazy"><figcaption>street_noon</figcaption></figure><figure><img src="crossroads_busy.png" loading="lazy"><figcaption>crossroads_busy</figcaption></figure><figure><img src="night_crowd.png" loading="lazy"><figcaption>night_crowd</figcaption></figure><figure><img src="katoomba_main.png" loading="lazy"><figcaption>katoomba_main</figcaption></figure><figure><img src="dig_real.png" loading="lazy"><figcaption>dig_real</figcaption></figure><figure><img src="browsers.png" loading="lazy"><figcaption>browsers</figcaption></figure></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 KiB

After

Width:  |  Height:  |  Size: 776 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 849 KiB

After

Width:  |  Height:  |  Size: 846 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 KiB

After

Width:  |  Height:  |  Size: 478 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 KiB

After

Width:  |  Height:  |  Size: 808 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 KiB

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 810 KiB

After

Width:  |  Height:  |  Size: 812 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 874 KiB

After

Width:  |  Height:  |  Size: 861 KiB

View File

@ -14,8 +14,11 @@ HOST = 'http://127.0.0.1:8130'
# flag-combo -> [street bookmarks] (each dbg.js bookmark sets its own pose + day segment) # flag-combo -> [street bookmarks] (each dbg.js bookmark sets its own pose + day segment)
GROUPS = [ GROUPS = [
('winmap=1&weather=rain&tram=1&stock=real&pop=200', ('winmap=1&weather=rain&tram=1&stock=real&pop=200',
['rain_verandah', 'night_crowd', 'tram_stop', 'rain_street', 'patronage_door', 'shopfront_detail', ['rain_verandah', 'tram_stop', 'rain_street', 'patronage_door', 'shopfront_detail',
'street_noon', 'crossroads_busy']), 'street_noon', 'crossroads_busy']),
# [Lane F R10] night_crowd on a CLEAN night boot (no rain → the neon reads brighter + fps recovers;
# rain variants already exist as rain_verandah/rain_street). High pop for any passers-by.
('pop=300', ['night_crowd']),
('plansrc=osm&town=katoomba&pop=180', ['katoomba_main']), ('plansrc=osm&town=katoomba&pop=180', ['katoomba_main']),
] ]
# interior shots: flags, then enter + optional dig # interior shots: flags, then enter + optional dig
@ -43,9 +46,14 @@ def main():
boot(pg, flags) boot(pg, flags)
for name in marks: for name in marks:
try: try:
pg.evaluate("(n) => window.DBG.shot(n)", name) # [Lane F R10] night_crowd's dist-16 bookmark reads dark + empty (the openLate video
# shop sits at a dead-end corner and nothing routes patrons to it at night — a real
# engine gap, noted for D). Reuse night_neon's tighter dist-12 pose so the stable
# night_crowd.png filename carries the readable "one lit shop amid a CLOSED town" shot.
pose = 'night_neon' if name == 'night_crowd' else name
pg.evaluate("(n) => window.DBG.shot(n)", pose)
pg.wait_for_timeout(1100) pg.wait_for_timeout(1100)
pg.evaluate("(n) => window.DBG.shot(n)", name) # settle bloom/segment pg.evaluate("(n) => window.DBG.shot(n)", pose) # settle bloom/segment
pg.wait_for_timeout(300) pg.wait_for_timeout(300)
pg.screenshot(path=str(OUT / f'{name}.png')) pg.screenshot(path=str(OUT / f'{name}.png'))
shot_names.append(name); print('shot', name) shot_names.append(name); print('shot', name)