Every marker used disableDepthTestDistance: Infinity, so points/billboards on the FAR side of the Earth drew on top of the near hemisphere instead of being occluded — reading as 'dots stuck, not moving with the globe' when you rotate. Changed to 50000 (50km) across all layers: the globe now occludes far-side markers, while you can still zoom right up to one without it clipping into the surface. Also made the billboard layers (aircraft/military/adsb/radius) explicit for consistent behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
149 lines
17 KiB
Plaintext
149 lines
17 KiB
Plaintext
F
|
||
Thanks — that's very helpful. Both parent repos are now present (`90sDJsim` reappeared in the listing), and I have ultra access if needed. Let me quickly ground my shot/soak harness in the actual house pattern (90sDJsim's `tools/shots.py`) since that's the reference F is told to reuse:
|
||
|
||
That's the exact house shot pattern — Playwright driving a `window.DBG.shot(name)` hook, with a contact sheet vs. `before/` and `references/`. Now I have everything I need to author F's deliverables grounded in real contracts. Let me write the integration runbook first (the durable technical spec), then the harnesses, V2 ideas, and the progress report.
|
||
|
||
Now the browser QA harnesses — ready to run the moment Lane B's `index.html` lands. First the tour-shot capture (adapted from 90sDJsim's `tools/shots.py` to PROCITY's DBG contract):
|
||
|
||
Now the soak-test harness — the 10-minute scripted-walk memory/leak/error gate (gates 2, 3, 4):
|
||
|
||
Let me syntax-check both Python harnesses and fix the pointless walrus in soak.py:
|
||
|
||
Now the docs/shots scaffold and V2_IDEAS. Let me create the shots tree with a README, then author V2_IDEAS:
|
||
|
||
Now `docs/V2_IDEAS.md` — the parking lot for everything discovered but out of v1 scope:
|
||
|
||
Now let me re-run the QA suite to get the freshest readiness snapshot (lanes keep moving) before writing the progress report:
|
||
|
||
Lane A's `plan.js` just landed — my scaffold_check now runs the plan-determinism deep checks automatically. Let me see that section:
|
||
|
||
Lane A's `generatePlan` passes F's determinism gate cleanly — 712 shops, town "North Cressy Reach", 2.9ms, JSON-clean. That's a real green QA result against live lane output.
|
||
|
||
Since Lane A's plan **and** registry both exist now, I can run a genuine **cross-lane consistency check** right now (exactly F's job) — do the plan's shop types/skins actually match the registry and the asset set? Let me inspect their shapes:
|
||
|
||
Real cross-lane data to check. I can see two things worth verifying: (1) a toy shop got `facade-boutique.jpg` — is that actually in the registry's `toy` pool? and (2) the name "Tex's's Toys" has a doubled possessive. Let me build a **cross-lane consistency gate** (plan ↔ registry ↔ assets) that runs now against real output:
|
||
|
||
The consistency check surfaced two real cross-lane signals. Let me investigate both properly before reporting — especially `chunkIndex 0/904`, which could be either my probe using the wrong API shape or a genuine Lane A bug that would break Lane B's streamer:
|
||
|
||
chunkIndex returns `{chunkSize, <something>}` — my probe guessed the wrong shape (it grabbed `chunkSize`). Let me read Lane A's actual `chunkIndex` so F's check matches the real API, and confirm the name bug:
|
||
|
||
Now I have the true API: `chunkIndex(plan)` → `{chunkSize, chunks}` where `chunks["cx,cz"].lots` is an array of lot **ids**, and a lot may bucket into several chunks. My probe used `idx[key]` instead of `idx.chunks[key]` — so the `0/904` was **my bug, not Lane A's**. Good that I checked. Let me fix the coverage probe to test it correctly:
|
||
|
||
The consistency check is now correct and **green**: chunkIndex covers all lots, all facadeSkins are within their registry pools, integrity clean across seeds. The only real finding is Lane A's cosmetic doubled-possessive name bug. Let me wire this gate into `qa.sh`:
|
||
|
||
Lane A's `selfcheck.js` also just landed and passes — the QA suite is actively exercising real lane output (3 gates green). Now let me write the requested `F-progress.md`. Let me grab a final fresh readiness snapshot first:
|
||
|
||
Lanes are landing fast (A 4/5, B has 7 world modules but no shell/streamer yet, C 3 support files, D 4 modules, E 2 pipeline files). Core integration blockers remain: **Lane B's `index.html` shell + `chunks.js`, Lane C's `interiors.js`, Lane E's `manifest.json`**. Let me write the `F-progress.md` checkpoint for fable:
|
||
|
||
Now, per the ultracode mandate, let me run an adversarial review of F's deliverables — independent agents that read my QA scripts and runbook, run them against the **live** repo, and hunt for false-confidence, robustness holes, and (most valuable) wiring-contract assumptions that don't match the lane code that has actually landed:
|
||
|
||
The adversarial review is running in the background. While it works, let me check whether the integration blockers (B's shell, C's interiors API) have cleared, since lanes are landing fast:
|
||
|
||
Lane A is now **5/5 complete** (map.html landed). The core blockers (B shell, C interiors, E manifest) remain. Since Lane A is fully done, let me do a real F QA action while the review runs: bring up the server and verify Lane A's `map.html` actually renders towns in-browser (its acceptance criterion), capturing a laneA reference shot:
|
||
|
||
Server's up. Let me load Lane A's `map.html` in the browser to verify it renders a real town (F verifying a landed deliverable):
|
||
|
||
Lane A's `map.html` renders a genuine, legible town — **"North Cressy Reach"** (seed 1234): 22 streets, 35 blocks, 706 lots, 516 shops, 153 chunks. The main-street spine (vertical corridor), the pink dept anchor, the market-square stall grid (center-left), cross streets, and the residential collar (green house lots ringing the edge) are all visible, with shop dots colored by type — record 113, video 94, opshop 82 … milkbar 2, dept 1 (matching the spec's "2–4 milkbars, one dept anchor"). That's Lane A's acceptance criterion verified in-browser by F. Let me confirm a second seed produces a distinct town:
|
||
|
||
Seed 88 gives a completely distinct town — **"Mirboo Springs"**, different spine and cross-street geometry, 521 shops, 4 milkbars. Lane A verified: deterministic, varied, and it reads as a town. Let me check on the adversarial review workflow:
|
||
|
||
The workflow is still running. Let me wait for it to complete since its findings directly improve the deliverables I'm handing to fable:
|
||
|
||
Let me stop polling and check lane progress instead (the review will notify me on completion):
|
||
|
||
The review completed **and** all integration blockers cleared simultaneously — Lanes A/B/C/D are now complete, E has `manifest.json`. Two priorities: (1) the adversarial review found **real false-confidence bugs in my own QA scripts** — I must fix those so F's tools are trustworthy; (2) integration can finally run. Let me read the full findings first:
|
||
|
||
14 confirmed, adversarially-verified findings — the review did its job. The runbook findings (11–14) are especially important now that integration is unblocked: **the real landed APIs differ from what I assumed from the spec** (chunks.js is a `createChunkManager` factory, sim.js has no per-chunk roster methods, keepers uses `spawn/remove/disposeAll`). I need to fix my QA scripts *and* correct the runbook against reality. Let me fix the scaffold_check bugs first:
|
||
|
||
Now fix the shots.py IndexError (finding 9) and the consistency_check issues (4, 5, 6). First shots.py:
|
||
|
||
Now the consistency_check fixes need real data to be correct. Let me inspect how Lane A actually encodes hours/storeys/late-night so my checks are meaningful, not inert:
|
||
|
||
Confirmed — there are off-range storeys (toy/book at 3, video at 2 where its range is [1,1]). That's likely CITY_SPEC's "occasional 3-storey corner anchor" exception, but a video shop at 2 storeys is worth surfacing for Lane A to adjudicate. Let me apply findings 4, 5, 6 to consistency_check — add a storeys check (as a warn), fix the dead late-night branch, and remove the dead metric:
|
||
|
||
Now the soak.py findings (7, 8, 10) — heap heuristic, vacuous shop count, and the no-op `--minutes`. Let me fix these to not give false confidence:
|
||
|
||
Let me read the walk-loop start so I can restructure it to (a) honor `--minutes`, and (b) count only verified interior loads:
|
||
|
||
Now add `import time`, and fix the heap heuristic (finding 7) to not give false confidence when heap isn't reported:
|
||
|
||
Now let me verify all the QA-script fixes compile and still pass against live data:
|
||
|
||
All QA-script fixes are working and now catch real signal (storeys warning fires, late-night positively confirmed, and **Lane E's manifest is now validated** — "every registry facade skin catalogued"). Let me confirm the fixed JSON round-trip check passes on the real plan (it has `-0` in `ry`, which the `-0→0` normalization handles) and run the full suite:
|
||
|
||
The QA harness is now trustworthy — 4 gates green (Lane E's `validate_manifest.py` also landed), and the checks catch real signal instead of passing vacuously. Now the **runbook contract errors** (findings 11–14) — these matter most because I'm about to wire against these APIs. Let me read the *actual* landed integration surfaces:
|
||
|
||
The real APIs differ from the spec-derived ones I documented (confirming findings 11–14). Critically, `index.html` already dispatches `procity:enterShop` and listens for `procity:exitShop` — I need to see how much wiring Lane B already did vs. what F must fill. Let me read the shell and the class APIs:
|
||
|
||
Now I understand the real integration state. Critically, the shell (`index.html:68`) imports `./js/citygen/index.js`, but Lane A shipped `plan.js` — and `enterShop()` (line 133-135) only toasts "interiors coming (Lane C)"; it never calls Lane C's `buildInterior`. **So doors don't actually open, and the game may be silently running on the fixture plan, not Lane A's generator.** Let me verify both, and check whether lanes are still churning (safe-to-wire check):
|
||
|
||
Confirmed three real integration bugs: (1) `citygen/index.js` doesn't exist so the shell **silently falls back to the 14-shop fixture** instead of Lane A's 516-shop town; (2) interiors landed but aren't wired — doors just toast; (3) citizens not wired. Lanes appear settled (nothing modified recently). This is exactly F's job. Let me read the real APIs I'll wire against (and correct the runbook with):
|
||
|
||
`buildInterior`'s return matches my runbook (good — §3.2 is accurate), and `player.teleport(x,z,yaw)` is available. Now let me read the citizen/chunk APIs for the runbook corrections (findings 11, 13, 14):
|
||
|
||
Now I have all the real APIs (confirming findings 11–14: `createChunkManager` factory with no lifecycle hooks, `CitizenSim` graph-based not per-chunk, `KeeperManager.spawn/remove/disposeAll`). Lanes are settled, QA green, and Lane B explicitly left `enterShop` as the wiring seam. Let me **execute the integration**. First, the safe zero-collision win — the barrel that makes the game run on Lane A's real generated town instead of silently falling back to the fixture:
|
||
|
||
Barrel works — the shell will now boot on Lane A's real town. Let me verify live in the browser by loading the actual game:
|
||
|
||
Another real cross-lane bug surfaced immediately: `skins.js` builds paths like `facade-facade-fibro-blue.jpg.jpg` — **doubled `facade-` prefix and doubled `.jpg`**. Lane A's registry stores full filenames (`facade-fibro-blue.jpg`) but Lane B's `skins.js` re-wraps them, so every facade texture 404s to flat colour. Let me confirm the boot used the real plan and see the visual state:
|
||
|
||
The barrel fix worked — **"using Lane A generatePlan"** (was falling back to fixture before). Let me see the town render and click into it:
|
||
|
||
"Boolarra Heads · seed 20261990" — the real Lane A town name confirmed in the shell. Let me walk in and see the 3D street:
|
||
|
||
My click was below the visible area (screenshot is 800×450; I clicked y=469). Also, pointer-lock likely won't engage in an automated browser. Let me use the JS inspection tool to hide the start overlay and confirm the 3D town renders + inspect the live state:
|
||
|
||
The game is **live on Lane A's real 523-shop town "Boolarra Heads"** — 31 chunks streaming, 31 door meshes (raycast targets), 24.7k tris. Two budget/visual findings: **draw calls 337 > 300 budget**, and the skins path bug means facades render as flat colour. Let me see it:
|
||
|
||
The game works — a walkable 90s-AU shopping strip under a dramatic summer-storm sky, HUD reading "MIDDAY 12:30 · Boolarra Heads · draws 340 · tris 25k · chunks 31", doors and awnings and gum trees all rendering. Facades are flat-colour only because of the skins path bug. Let me read `skins.js` to see if that's a surgical contract fix:
|
||
|
||
The bug is clear: `skins.js:60` builds `assets/gen/facade-${name}.jpg`, expecting a **bare key** like `fibro-blue`, but Lane A's registry/plan stores the **full filename** `facade-fibro-blue.jpg`, so buildings.js passes the whole thing → `facade-facade-fibro-blue.jpg.jpg`. Let me confirm what buildings.js passes, then make the robust chokepoint fix:
|
||
|
||
Confirmed: `buildings.js:138` passes `shop.facadeSkin` (full filename `facade-fibro-blue.jpg`) straight to `facadeMat`, which re-wraps it. Ground works because it gets bare keys. The robust, idempotent fix is a one-line normalization at the `facadeMat` chokepoint (works for both bare keys and full filenames):
|
||
|
||
Now reload the game and verify the facades get their real 90s-AU skins:
|
||
|
||
The doubled-path warnings persist — likely the browser cached the old `skins.js` module. Let me check network requests to see what path is actually being requested now:
|
||
|
||
The fix works — network now shows correct single-form paths, all **200 OK** (`facade-besser.jpg`, `facade-stucco-pink.jpg`, `facade-corrugated.jpg` …). The doubled-path warnings were stale console history. Let me see the now-textured town:
|
||
|
||
The facades now render with their real 90s-AU skins (window glazing, shutters, weathered surfaces — all 200 OK). **Two integration fixes delivered and verified live: the game now boots on Lane A's real 523-shop town with textured facades.** This is a strong, verified checkpoint. Let me now correct the runbook against the real landed APIs (findings 11–14) and mark what's wired:
|
||
|
||
Now let me add a §7 to the runbook capturing the live smoke-test findings, then append it:
|
||
|
||
Let me fix that section ordering and run the final full QA pass to capture the end state:
|
||
|
||
Everything has landed — **all 5 lanes complete, QA fully GREEN (4/4 gates, 0 skips)**, and the other lanes even used the `docs/shots/` tree I scaffolded for their acceptance shots. Let me rewrite `F-progress.md` as the authoritative checkpoint for fable:
|
||
|
||
Let me do a final consolidated verification — QA green after all edits, and the running game has no console *errors* (only expected asset-fallback warnings):
|
||
|
||
Zero console errors in the running game, QA fully green, both edits parse clean. This is a solid, verified checkpoint. Here's the handoff for fable.
|
||
|
||
---
|
||
|
||
## PROCITY-F — session complete ✅
|
||
|
||
I'm Lane F (integration & QA). When I started, only the scaffold existed — but **all five lanes landed while I worked**, so I went from "prep the harness" all the way to a **first integration pass with two fixes verified live in the browser**.
|
||
|
||
### Headline results (both verified in-browser)
|
||
1. **The game was silently running on the 14-shop fixture, not Lane A's town.** Lane B imported `js/citygen/index.js`, which never existed (Lane A shipped `plan.js`). I added the barrel → **seed → real 523-shop generated town "Boolarra Heads" boots**, 31 chunks streaming, 31 doors. ([web/js/citygen/index.js](web/js/citygen/index.js))
|
||
2. **Every facade rendered flat-grey** — a cross-lane naming mismatch made skin URLs `facade-facade-…jpg.jpg` (all 404). One-line chokepoint fix → **facade JPEGs now 200 OK, the town is textured.** ([web/js/world/skins.js:55](web/js/world/skins.js))
|
||
|
||
### QA harness — GREEN, and trustworthy
|
||
`tools/qa.sh` runs **4/4 gates green**: scaffold+PRNG-determinism, cross-lane consistency, Lane A selfcheck, Lane E manifest validator. Centerpiece is a **live lane-readiness dashboard** (`node tools/qa/scaffold_check.mjs`).
|
||
|
||
Critically, I **adversarially reviewed my own tooling** (23-agent workflow) and it found **14 real false-confidence bugs in F's scripts** (e.g. the JSON round-trip check was a mathematical tautology; the Math.random ban had false negatives) — **all fixed**. It also caught that my runbook's API assumptions were wrong vs. the real landed code, which I corrected.
|
||
|
||
### Findings handed to the lanes
|
||
- **B:** ~334 draw calls at spawn (over the ≤300 budget — shave radius or merge more).
|
||
- **A:** doubled possessives in names ("Tex's's Toys"); some storeys outside registry range.
|
||
- **Contract:** `facadeSkin` is a full filename in the registry but consumers expected bare keys — worth a CITY_SPEC line before ground/awning/interior skins hit the same trap.
|
||
|
||
### What's left (scoped in [LANE_F_NOTES.md](docs/LANES/LANE_F_NOTES.md) §3, ready to execute)
|
||
Interiors wiring (`enterShop → buildInterior` — the "every door opens" headline), citizens/keepers, manifest GLB upgrades + `?noassets`, the draw-budget shave, and the browser QA gates (need a small `window.DBG` hook from Lane B, requested in §4).
|
||
|
||
**Deliverables to review:** [F-progress.md](F-progress.md) · [docs/LANES/LANE_F_NOTES.md](docs/LANES/LANE_F_NOTES.md) · [docs/V2_IDEAS.md](docs/V2_IDEAS.md) · `tools/qa.sh` + `tools/qa/*` · the two integration fixes.
|
||
|
||
Nothing is committed — all edits are minimal, commented `[Lane F integration fix]`, and reversible. I held off on the interior/citizen wiring since it touches Lane B's core loop and is best playtested with real pointer-lock (which the automated browser can't drive) — **say the word and I'll wire it**, or hand me your next instructions after reviewing.
|
||
|
||
A local server is still up on `:8130` if you want to walk `localhost:8130?seed=20261990` yourself. |