diff --git a/docs/A-progress.md b/docs/A-progress.md new file mode 100644 index 0000000..c03bf8a --- /dev/null +++ b/docs/A-progress.md @@ -0,0 +1,126 @@ +# LANE A — CITYGEN · progress (PROCITY-A) + +*Status: **all deliverables landed & self-check all-green.** Awaiting Fable review.* +*Date: 2026-07-14 · owner: PROCITY-A (Opus 4.8)* + +## TL;DR + +`generatePlan(citySeed) → CityPlan` is done: a deterministic, JSON-serializable, <1ms pure-data +town generator matching CITY_SPEC schema v1, plus `chunkIndex`, the shared shop-type registry, a +seeded 90s-AU name generator, a Canvas-2D map debugger, and a node self-check that asserts the +whole acceptance contract. `node web/js/citygen/selfcheck.js` prints **ALL GREEN (1082/1082)**. +Five seeds render as recognisable towns (screenshots in `docs/shots/laneA/`). + +## Deliverables (all present) + +| # | file | what | +|---|---|---| +| 1 | [web/js/citygen/plan.js](../web/js/citygen/plan.js) | `generatePlan(citySeed)`, `chunkIndex(plan)`, `CHUNK`, `chunkKey` | +| 2 | [web/js/citygen/names.js](../web/js/citygen/names.js) + [wordlists.js](../web/js/citygen/wordlists.js) | seeded shop+town names, 50+ patterns, short signboard forms | +| 3 | [web/js/core/registry.js](../web/js/core/registry.js) | `SHOP_TYPES` (all 9), district weights, enums, pure helpers | +| 4 | [web/map.html](../web/map.html) | standalone Canvas-2D plan viewer (pan/zoom/hover, layer toggles, seed box, regen, export JSON, chunk grid) | +| 5 | [web/js/citygen/selfcheck.js](../web/js/citygen/selfcheck.js) | `node web/js/citygen/selfcheck.js` — full acceptance harness | +| + | [web/package.json](../web/package.json) | `{"type":"module"}` so `node` runs the self-check as ESM (see *Treaty notes*) | +| + | `docs/shots/laneA/seed-*.png` | 5 seeds screenshotted (20261990, 1, 42, 777, 8675309) | + +## What the generator produces (matches the CITY_SPEC design brief) + +- **Main-street spine** — 7 stations S→N through the origin, x-jitter ±30m, 28m corridor, `kind:'main'`. + Continuous narrow-frontage (6–9m) retail both sides. +- **Cross streets** at 4 stations; the two central ones are wider "second high streets", the outer + two are grittier `backstreets`. All `kind:'side'`, ±8° jitter. +- **Market square** west of the origin — a tidy 5×8 grid of `stall` lots + the `dept` anchor + fronting the spine. +- **Arcade** — a `kind:'arcade'` (width 5) pedestrian lane cutting east through a mid-spine block, + lined both sides with tiny 3–5m record-heavy shops. +- **Warehouse fringe** — sparse big lots beyond one spine end (N or S, seeded), mostly `infill` + with the odd pawn shop. +- **Residential collar** — a loose ring road of `house` lots with **2–4 corner milk bars** embedded. +- **Laneways** (`kind:'lane'`) behind the central blocks, with `yard` lots for back-door flavour. + +Sample (seed 20261990 → "Boolarra Heads"): 27 nodes, 22 edges, 35 blocks, 711 lots, 523 shops, 152 chunks. + +## Self-check coverage (`node web/js/citygen/selfcheck.js`) + +Determinism (two runs byte-identical) · <100ms (actually <1ms) · every edge→real nodes · every block→real +district · every lot→real block + **valid frontEdge** + positive size · every shop→real lot + known type + +**facade skin exists on disk** + sane hours + named · one-shop-per-lot · **no overlapping lots within a +block** (rotated-rect OBB / SAT test) · **chunkIndex covers every lot** & buckets reference real ids · +JSON round-trip lossless · design-brief presence (spine, arcade, market, stalls, dept anchor, 2–4 milkbars) · +all registry + used facades exist in `web/assets/gen/`. Run over 6 seeds → **1082/1082**. + +## House-law compliance + +- **Zero `Math.random` and zero THREE imports in `js/citygen/*` and `registry.js`** (grep-clean). + All randomness flows through `web/js/core/prng.js`. (map.html uses `Math.random` only to pick a + *random seed to view* — the generation it then runs is fully seeded; the map is pure Canvas 2D, + no THREE.) +- JSON-serializable, deterministic, <100ms — verified. +- Registry is flat data every lane imports; facade pools are real files in `web/assets/gen/`. + +## Treaty / cross-lane notes for Fable + +1. **`web/package.json` added.** Needed so `node web/js/citygen/selfcheck.js` runs the ES modules + (browsers use ` + + diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..8833820 --- /dev/null +++ b/web/package.json @@ -0,0 +1,6 @@ +{ + "name": "procity-web", + "private": true, + "type": "module", + "description": "Marks web/js/** as ES modules so plain `node web/js/citygen/selfcheck.js` runs. Browsers use