selfcheck ALL GREEN 156,352/156,352; consistency green. 51 goldens re-pinned in this one commit per the amendment law. scaffold_check is RED and CANNOT be green from here — the covenant hashes are duplicated in LANE F's files; exact values handed to F in LANE_A_NOTES §R27w5 (I don't edit other lanes' files). THE RULING'S PREMISE WAS WRONG, AND THE WRONG HALF WAS LOAD-BEARING. Wave 5 says "synthetic follows B's canon so every golden has been green over a wrong product since R18". Half right. Synthetic does NOT follow B's canon -- it is broken identically, and so is the marched path, and so are all three checked-in fixtures. It is not "every real town since R18". It is EVERY TOWN, EVERY PATH, SINCE v1. The ruling told me to measure the marched path rather than assume it was clean "because that's how this one survived nine rounds" -- so I measured all three, and the same discipline caught the premise itself. MEASURED FIRST, IN B'S CANON (+Z = the facade), BEFORE TOUCHING ANYTHING: synthetic seed 20261990 0 toward / 681 away (dot = -1.0000, exactly anti-parallel) marched katoomba/fremantle/godverse, fixtures melbourne/katoomba/silverton 0 toward, all away real-roads katoomba 0/72 <- B's number, reproduced 637 of 681 synthetic lots had their facade pointing at NO STREET AT ALL (44 hit a different street by corner coincidence). Then I confirmed it with my own eyes rather than trust the arithmetic: booted ?classic=1, stood on the synthetic main street at lot 0 -> three blank grey boxes. Walked BEHIND them into the block -> NUMBAT PLAYTHINGS, sign/door/windows/awning, facing the dirt. The classic covenant town has been a row of back walls since v1. After the fix, same camera, same seed, same ?classic=1: CROWN TOYS & GAMES · MARBLES & KITES · NUMBAT PLAYTHINGS -- a strip of shopfronts facing the road. FOUR SITES, ONE SIGN, AND EVERY ONE OF THEM SAID SO IN ITS OWN COMMENT: plan.js:122 synthetic strip "facade faces back down the outward normal, to the street" <- it didn't plan.js:244 market row "the facade then faces -(outward) = +x" <- it didn't plan_osm:330 marched avenue "facade faces +z (north) to the avenue" <- due south plan_osm:443 real roads B's proven one-liner (B measured it, then reverted it -- A's file) All four were atan2(outward) where the intent was atan2(-outward). The code never did what its comment said, and CITY_SPEC:71 blessed the result by writing the SIM convention into the LOTS contract. Nobody was wrong; the spec was. After: synthetic 681/681, marched + fixtures 100%, real-roads katoomba 72/72. THE COVENANT MOVED -- JOHN RULED IT, I DIDN'T. Fixing synthetic necessarily moves 0x3fa36874, frozen "forever" since R16. That is not Lane A's call, so I stopped and asked with the evidence. John's ruling: AMEND THE COVENANT, FIX ALL PATHS -- the covenant is anti-drift machinery, not a defect preservative. 51 pins in this commit: classic/synthetic 0x3fa36874 -> 0x5f76e76 gig 0xb1d48ea1 -> 0xec7a2d39 fixtures melbourne 0x9c7e76b3 · katoomba 0xf3aafec8 · silverton 0x6d74c4 23 real towns base + gig (46) Verified byte-identical across two fresh processes; pack-xor 0xa5058322. CITY_SPEC records the amendment as a ONE-TIME, ruling-gated precedent -- from this hash forward the law reads as it always did. A SECOND BUG THE FIX EXPOSED (fixed here, counted). buildRealRoads seated blocks at KERB = 4 m from the CENTRELINE, but a `main` carriageway is 10 m wide -- its kerb is at 5 m. EVERY MAIN-STREET BUILDING HAS STOOD 1 m INSIDE THE ROAD SINCE R18. The footprint never moved; only which face is the front -- so it was invisible until the shopfront turned around and its poster landed in the traffic lane (-1.07 m clearance, 6 real failures). Blocks now seat behind the kerb per A's own published corridor law (roadWidth/2 + FOOTPATH). Pack drops 6.4% -> 6.6%, counted, not hidden. THE CROSS-CONVENTION GATE -- built to F's lesson, not to a spec line. F proved that measuring lots against CITY_SPEC:71's own convention is SELF-AGREEMENT: 72/72 "facing" over a town of blank walls. So this gate restates nothing. It replicates LANE B'S OWN maths from buildings.js (toWorld(lot, 0, y, d/2 + 0.02)) and asks a physical question neither spec line can fudge: does the quad the RENDERER actually draws land nearer the street than the lot centre? It fires if A's ry sign drifts OR if B's zf sign drifts. It would have caught this on day one of v1. CITY_SPEC amendments: the lots contract now states facade/door/frontage = local +Z; the SIM/rig convention is documented separately as the different thing it is, with the explicit rule -- never assert a lot's facing against a spec line, assert it against the geometry the renderer draws. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| docs | ||
| pipeline | ||
| priorwork | ||
| tools | ||
| web | ||
| .gitignore | ||
| B-progress.md | ||
| C-progress.md | ||
| D-progress.md | ||
| E-progress.md | ||
| F-progress.md | ||
| G-progress.md | ||
| README.md | ||
PROCITY
A standalone, procedurally generated, fully walkable 90s-Australian shopping town — every building enterable (the Vuntra City trick), every interior seeded and themed: record stores, op shops, toy shops, book barns, video rental, pawnbrokers, milk bars, market stalls. Built on the proven house stack (three.js r175 vendored, plain JS, no build step) and the asset DNA of 90sDJsim + thriftgod. v1 is the system; the GODVERSE/BaseGod real-item content plugs in later.
Run
cd web && python3 -m http.server 8130
# http://localhost:8130 (game shell — Lane B)
# http://localhost:8130/map.html (2D plan debugger — Lane A)
Read first
docs/CITY_SPEC.md— the treaty: schema, units, seeds, budgets, file ownership.docs/RESEARCH.md— what the parent repos already solved, with exact paths to port from.
The lanes (parallel Opus 4.8 sessions)
Each lane is a self-contained prompt. To run one, start an Opus session in this repo and say: "Read docs/LANES/LANE_X_….md and execute it." A–E are parallel-safe (disjoint files, standalone test pages); F integrates after they land.
| lane | mission | owns |
|---|---|---|
| A — CITYGEN | seed → CityPlan data (streets, blocks, lots, shops) + 2D map | js/citygen, js/core/registry.js, map.html |
| B — STREETSCAPE | chunk-streamed instanced 3D town + game shell | index.html, js/world |
| C — INTERIORS | every door opens: seeded themed shop interiors | js/interiors, interior_test.html |
| D — CITIZENS | rigged-near / impostor-far NPCs + shopkeepers | js/citizens, citizens_test.html, models/ |
| E — ASSETS | audit ultra's library, normalize GLBs, skins, manifest | pipeline/, assets/ |
| F — INTEGRATION | wire A–E into one seed-to-town game + QA gates | (after A–E) |
Already in the repo
web/vendor/— three.js r175 + addons (vendored from 90sDJsim; no CDN at runtime).web/assets/gen/— 69 generated texture skins (25 shopfront facades, 10 skies, 10 grounds, 8 wallpapers, 16 interior surfaces) inherited from thriftgod + 90sDJsim, style-locked.web/js/core/— frozen shared modules:prng.js(seeded-everything law),loaders.js(fail-soft promise-cached GLB/texture + 3GOD depot),canvas.js(text planes).
House laws (short form — CITY_SPEC has the fine print)
Seeded everything, Math.random banned in gen code · the game must run with zero assets ·
instancing from day one · canvas text, no font files · characters = shared base rigs + one
clip bank, canonical sources live outside this repo · 🟢 web-ok licensing only.
v3.1 — THE FLIP: the town shows its best by default
The Friday-night layer soaked through alpha, beta, and the v3.0 release — so v3.1 flips it on by default, and the mature v2 flags flip with it. Boot the plain URL and each town seeds 2–4 venues (pub, band room, RSL) with a full seeded week of gigs, town-wide posters, and a Friday night that reads: a 4-piece band (trio + a seated drummer) with real instruments, a mixed crowd, an outdoor queue, a per-venue cover charge, muffled gig spill + walla and applause, town-wide streetlamp pools, and identity continuity — the ped you followed in is in the crowd. Plus weather, the tram, and the parallax interior-window shader, all live by default.
The covenant moved, it didn't disappear. ?classic=1 boots the exact v2 town — byte-identical
forever (synthetic golden 0x3fa36874, zero gig layer, zero fetch delta). That is the new frozen
regression target; the default boot is deterministic to the gig golden 0xb1d48ea1. Asset-free
(?noassets=1) composes with the default boot and stays silent-and-fine.
Flags — the four headliners are ON by default, each with a =0 opt-out; ?classic=1 is the
master off:
| flag | default | what |
|---|---|---|
?classic=1 |
off | the exact v2 boot — all four below off, byte-identical to the frozen baseline |
?gigs=0 |
on | the gig district — venues, week schedule, band/crowd/queue, cover, posters, night pass |
?weather=0 · ?tram=0 · ?winmap=0 |
on | seeded weather · the tram loop · the parallax interior-window shader |
?roster=v1 · ?pop=N |
stream | chunk-streamed citizen density is the baseline; ?roster=v1 restores the fixed roster |
?dig=0 · ?stock=real |
dig on | crate-riffle on record bins · real GODVERSE sleeves in the stock |
?live=1 · ?live=<url> |
off | tier 2 — live stock from the GODVERSE server (sold-in-the-real-shop means gone in the game). Opt-in by design: absent ⇒ byte-identical to tier 1, and the game never asks a question it has no reason to expect an answer to |
?noassets=1 · ?plansrc=osm · ?mute=1 · ?dbg=1 |
off | asset-free (zero network) · OSM plan source · silence · the window.DBG capture/soak harness |
?plansrc=osm&town=<key> |
— | boot a real Australian town: fixtures melbourne/katoomba/silverton, or a real OSM cache bendigo_real/castlemaine_real/fremantle_real/katoomba_real/newtown_real (ODbL, web/assets/towns/SOURCES.md). REAL ROADS: a cache with roads[] (schema v2) builds the CityPlan street graph from the town's actual OSM streets; without roads[] a cache marches onto synthetic avenues. Or just pick a town from the HUD selector — no URL needed |
v4.0 — THE REAL MAP: the towns are the product
23 real Australian towns — 1,210 real shops, every state and territory — on their actual streets. Not "inspired by": Fitzroy's shops sit on Fitzroy's roads, at their real positions, because the pipeline eats OpenStreetMap and marches it through the same CityPlan contract the procedural town uses. Pick one from the in-HUD selector and walk it. Everything built across v1–v3 comes along unchanged — the venues and their seeded week of gigs, the 4-piece band with the seated drummer, the crowd that follows you into the pub, the interiors behind every door, weather, the tram — because they all hang off the plan contract and never had to know the geography got real.
The towns run from meccas (Fitzroy, 160 shops) to the thin tail (12), at real retail density: the
secondhand heroes keep their footfall while the street around them gets ~4× busier — texture, never a
takeover. Venues bias to the retail heart. The tram only runs where it fronts a real high street (elsewhere
it was honestly "a highway bus", so it's fenced). Everything stays deterministic from the seed, silent
under ?noassets=1, and ?classic=1 still boots the exact v2 town, byte-identical forever (0x3fa36874).
The tour: docs/shots/release_v4/contact.html — the Fremantle hero, the
Fitzroy mecca, the thin tail (labelled honestly: the floor is shops-per-street-metre, and Toowoomba is
below it), the synthetic control, and the ?classic=1 covenant made visible. Charter:
docs/V4_REAL_MAP.md · data + licences (ODbL):
web/assets/towns/SOURCES.md.
v5.0-alpha — THE FIRST REAL CRATE: the shops get real too
v4 made the towns real. v5 makes the shops real — and the first one is standing.
Boot ?plansrc=osm&town=redhill_godverse&stock=real, walk down Musgrave Road into Monster Robot
Party (147 Musgrave Rd, Red Hill, Brisbane — a real record shop), and riffle its crate. The records in
it are that shop's real stock: 120 real records off its real point-of-sale, real covers, real titles,
real prices. Buy one and the wallet debits what the sticker says. It's gone for the session and back next
boot — because until the live tier lands, the crate is a file, not a shop's ledger.
Stock is a data tier now, exactly like assets — each rung fully playable, each degrading softly to the one below, so the game never depends on a server to be a game:
| tier | what | deterministic? |
|---|---|---|
| 0 · parody | seeded canvas sleeves (v1) — any boot, always works | yes — the QA baseline |
| 1 · static real | per-shop atlases baked from the shop's own POS | yes — atlases are files |
| 2 · live GODVERSE | ?live=1 — live stock off the real till: sell a record in the shop and it's gone from the game crate |
no — by design |
The offline law: the server enriches, never gates. ?noassets=1 still fetches zero bytes and plays
silent-and-fine; a shop whose atlas is missing falls soft to parody rather than borrowing someone else's
crate; and ?classic=1 still boots the exact v2 town, byte-identical forever (0x3fa36874). The
world stays seeded and golden-gated — only the stock inside it is data.
Provenance: item photos are each shop's own product shots, 🟢 in-house — flagged before any public
or commercial release, and every atlas carries that flag where the QA gate must print it. Real titles
and artists are an in-house amendment to the no-real-trademarks law, on the same footing. Nothing an
in-game purchase does touches real inventory — v5.0 ships sell-sandboxed by ruling; a real reservation
tier is chartered for v5.x, not assumed. Charter: docs/V5_REAL_SHOP.md ·
economy design: docs/G3_ECONOMY_DESIGN.md.
| ?seed=N | 20261990 | town seed |
Release tour: docs/shots/release_v3_1/contact.html — the money shots on
the default boot, plus a ?classic=1 before/after. QA: tools/qa.sh --strict (classic regression +
default-boot gate + smokes + no-giants) --soak (the full-week soak); the seated drummer passes the
no-giants gate at the seated stature band [0.9,1.5] m.