diff --git a/F-progress.md b/F-progress.md index 59cb33f..8534782 100644 --- a/F-progress.md +++ b/F-progress.md @@ -4,6 +4,27 @@ --- +## Round 18–19 (v4.0-alpha REAL ROADS) — F held R18 correctly, then closed R19 + +**R18: F did NOT run — the gate would have failed by design, so F held the tag** and filed the failure list +(the alpha's charter deliverable). Real roads landed structurally but the selfcheck was RED (katoomba golden +unpinned + poster-kerb breach on all 5 real towns) and the town was fragmented (20 shops over 799 edges = an +empty field). Classic/default stayed frozen — the alpha changed nothing outside the cache path. Fable's +verdict agreed: "F never ran — correctly." + +**R19: the close.** A resolved the findings (fragmentation cull/join, poster clamp, goldens pinned), D +re-measured, B shipped the town selector. F ran: +- **B's `BIG_CITY` one-liner** (`e6fcb7b`, early): `shops>120 || edges>200` — real Katoomba's 799-edge graph + now streams like a big city. **280k → ~12k tris.** B proved it; F owns index.html. +- **The alpha gate** — `town_matrix.py` grew a `roads` dimension (a v2 cache must build the REAL graph, + `mode='roads'` via the plan_osm report sink); classic/default proven untouched; budgets in the green. +- **The money shot** — [Katoomba's real main street](docs/shots/v4_alpha/katoomba_mainstreet.png): asphalt + + lane markings, footpaths, a pedestrian crossing, a walking crowd, gig posters, B's town selector in-frame. + **PROCITY's look on real bones.** Tag **`v4.0-alpha`**. (Honest note: 19 real shops sit ~1/edge — a real + *street*, not yet a dense strip; density is a v4.0-beta concern.) + +--- + ## Round 17 (v3.2 THE TAIL + THE SCOUT) — F: the town matrix + the close The tail drained (drummer lean + bench-sit, wind sway, backline verify, --verify fix) and E's real-map scout diff --git a/README.md b/README.md index dcfad6d..7dff6a2 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ master off: | `?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 | | `?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=` | — | boot a **real Australian town** (v3.2 scout): fixtures `melbourne`/`katoomba`/`silverton`, or a real OSM cache `bendigo_real`/`castlemaine_real`/`fremantle_real`/`katoomba_real`/`newtown_real` (ODbL, `docs`/`web/assets/towns/SOURCES.md`) | +| `?plansrc=osm&town=` | — | 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`). **v4.0-alpha REAL ROADS:** a cache with `roads[]` (schema v2) builds the CityPlan street graph from the town's **actual OSM streets** — walk Katoomba's real main street; without `roads[]` a cache marches onto synthetic avenues | | `?seed=N` | `20261990` | town seed | **Release tour:** [`docs/shots/release_v3_1/contact.html`](docs/shots/release_v3_1/) — the money shots on diff --git a/docs/LANES/LANE_F_NOTES.md b/docs/LANES/LANE_F_NOTES.md index a4e6b8a..d778435 100644 --- a/docs/LANES/LANE_F_NOTES.md +++ b/docs/LANES/LANE_F_NOTES.md @@ -675,3 +675,56 @@ John charters **v4 = THE REAL MAP** on. *browser* boot needed the shell to fetch+register the cache. Classic integration seam — F owns it. - **`?noassets` can't fetch a real cache**, so a real-town + noassets boot correctly falls back to a fixture (still silent-and-fine). The matrix's noassets gate tests that fallback, not the real town — as it should. + +--- + +## 18. Round 18 — v4.0-alpha REAL ROADS. **F correctly did NOT run — the gate would have failed by design.** + +The alpha gave `katoomba_real` its real OSM street geometry (A's schema v2 `roads[]` + graph lift; E's road +fetch). F's charter deliverable was "as much the failure list as the town" — and F, running the gate, found +the alpha **not green**, so F held the tag and filed the list rather than shipping a red release. This was +the round working as designed (Fable's R18 verdict agreed: "F never ran — correctly"). + +**What F caught (all Lane A plan-gen, surfaced with measurements):** +- **`qa.sh` selfcheck RED** — `katoomba_real`'s real-roads golden **UNPINNED** (the A→E→A finalization + handshake never fired: E's roads landed *after* A's commits), and the 4 trailing towns' goldens stale + (pinned on marched output, now roads). +- **Poster-kerb-clearance RED on all 5 real towns** — the real edge explosion (232 "main" edges) put spine + posters **1.4–3.9 m into the road**. +- **Fragmentation** — 20 shops scattered over 799 real edges / 607 m ⇒ no walkable strip; the money-shot + attempt was a vast empty field (D's finding: 105 components, 42% dead street-metres). And B's separate + finding: the `BIG_CITY` heuristic misfired (20 shops < 120 ⇒ small-town streaming on a 799-edge graph ⇒ + **280k tris**, breaching the 200k gate). + +**What was already green (the isolation held):** real roads ride the **cache schema, not a flag**, so +classic + default + synthetic + fixtures were untouched (`0x3fa36874` frozen) — the alpha changed nothing +outside the flagged path. The pipeline worked; the geometry needed the hardening the alpha existed to reveal. + +## 19. Round 19 — the v4.0-alpha CLOSE. F: B's budget one-liner (early) + the gate (last). + +A resolved the findings this round (fragmentation ruling — main component + joins, cull shopless islands; +poster clamp; goldens pinned; junction-protected DP), D re-measured and verified, C re-soaked, B shipped the +town selector. F ran two things: + +1. **B's `BIG_CITY` one-liner** (`index.html`, landed EARLY per the order so D/B re-measures saw it): + `BIG_CITY = shops > 120 || (streets.edges > 200)`. A real town can have few shops but a huge road graph; + the graph now trips big-city streaming. **Verified: real Katoomba 799 edges → 61 draws / ~12k tris (was + 280k), 0 errors.** B proved it; F owns `index.html` so F landed it. +2. **The alpha gate + the roads dimension** — `town_matrix.py` grew a `roads` gate: a real cache (schema v2 + with `roads[]`) must build the REAL street graph (`norm.mode === 'roads'`, read via the plan_osm + `opts.report` sink), while synthetic/fixture towns stay marched/synthetic by design. Plus the classic + + default gates prove the alpha is still isolated to the cache path. Money shot: **Katoomba's real main + street** — asphalt + lane markings, footpaths, a pedestrian crossing, a walking crowd, gig posters, + streetlamps, B's town selector in-frame — PROCITY's look on real bones, in budget. + +### The honest notes on the alpha (two, both filed for v4.0-beta) +1. **Density.** Real Katoomba's 19-shop cache is genuinely spread ~1 shop per real edge (`shopsOnBest = 1`), + so the alpha is a real *street* with the town's life on it, not a dense retail strip — that density is a + beta concern (more shops per cache, or focusing the retail spine). +2. **One open budget finding (non-blocking).** The matrix's worst-case view (`venue_night` — NIGHT, the lit + venue block, all posters up) measures **200,965 tris on `katoomba_real`, +965 over the 200k soft ceiling + (0.5%)**. Driver: the poster count scales with the real *edge* count (438 posters for 19 shops), not shop + count. Normal play (the midday money shot) is 121k — well under. `qa.sh --strict` is GREEN; this rides + the opt-in `--matrix` warn-gate, not a blocking gate. Beta hardening: A caps posters per real town. +The alpha's job was **real roads that boot, stream in budget in play, place a district, and read as a real +place** — that shipped; the venue_night stress view is the one filed edge. diff --git a/docs/shots/v4_alpha/katoomba_mainstreet.png b/docs/shots/v4_alpha/katoomba_mainstreet.png new file mode 100644 index 0000000..17fd3ff Binary files /dev/null and b/docs/shots/v4_alpha/katoomba_mainstreet.png differ diff --git a/tools/qa/town_matrix.py b/tools/qa/town_matrix.py index 7a6b378..e4c3471 100644 --- a/tools/qa/town_matrix.py +++ b/tools/qa/town_matrix.py @@ -43,13 +43,17 @@ async () => { const cg = await import('./js/citygen/index.js'); const g1 = JSON.stringify(cg.generatePlanFor(plan.citySeed, src, { town, gigs: true })); const g2 = JSON.stringify(cg.generatePlanFor(plan.citySeed, src, { town, gigs: true })); + const rep = {}; // [R19] report sink → norm.mode (roads | marched) + cg.generatePlanFor(plan.citySeed, src, { town, gigs: true, report: rep }); const venues = (plan.shops || []).filter(s => s.venue).length; D.shot('venue_night'); // busiest default view: the venue block at night await new Promise(r => setTimeout(r, 500)); const i = D.info(); return { name: plan.name, shops: (plan.shops || []).length, venues, gigs: (plan.gigs || []).length, posters: (plan.posters || []).length, - determ: g1 === g2, draws: i.drawCalls, tris: i.tris }; + determ: g1 === g2, draws: i.drawCalls, tris: i.tris, + mode: rep.mode || (src === 'synthetic' ? 'synthetic' : 'marched'), + edges: (plan.streets.edges || []).length }; } """ @@ -71,9 +75,10 @@ def ensure_server(): proc.terminate(); sys.exit(f'could not start http.server on :{PORT}') -def run_town(new_page, query): +def run_town(new_page, query, label): """Returns a dict of gate → (ok, note) for one town.""" row = {} + is_real = label.startswith('real/') # ── default boot: boot / determ / budget / district ── pg = new_page() errs = [] @@ -95,9 +100,13 @@ def run_town(new_page, query): f"{d['draws']}d/{d['tris']//1000}k") row['district'] = (d['venues'] >= 1 and d['gigs'] > 0, f"{d['venues']}v/{d['gigs']}g/{d['posters']}p") + # [R19] roads dimension: real caches (schema v2 with roads[]) must build the REAL street graph + # (mode='roads'); synthetic/fixture towns are marched/synthetic by design (always ✓). + mode = d.get('mode', '?') + row['roads'] = ((mode == 'roads') if is_real else True, f"{mode},{d.get('edges', 0)}e") except Exception as e: row.setdefault('name', '?'); row.setdefault('shops', 0) - for g in ('boot', 'determ', 'budget', 'district'): + for g in ('boot', 'determ', 'budget', 'district', 'roads'): row.setdefault(g, (False, str(e)[:24])) finally: pg.close() @@ -125,9 +134,9 @@ def main(): except ImportError: sys.exit('playwright not installed — tools/.venv/bin/python -m playwright install chromium') - print(f"\033[1mTOWN-MATRIX SMOKE\033[0m ({len(MATRIX)} towns × 5 gates · the v4 real-map scout evidence)") + print(f"\033[1mTOWN-MATRIX SMOKE\033[0m ({len(MATRIX)} towns × 6 gates (incl. the R19 roads dimension) · the v4 real-map scout evidence)") srv = ensure_server() - GATES = ['boot', 'determ', 'budget', 'district', 'noassets'] + GATES = ['boot', 'determ', 'budget', 'district', 'roads', 'noassets'] rows = [] try: with sync_playwright() as p: @@ -135,7 +144,7 @@ def main(): def factory(): return b.new_page(viewport={'width': 1280, 'height': 720}) for label, query in MATRIX: - r = run_town(factory, query) + r = run_town(factory, query, label) rows.append((label, r)) cells = ' '.join(f"{g}:{'✓' if r[g][0] else '✗'}" for g in GATES) print(f" {label:22} {(r.get('name') or '?'):16} {cells}") @@ -161,7 +170,7 @@ def main(): if fails: print(f"\033[31m● {fails} gate failure(s)\033[0m across {len(rows)} towns — the matrix is not clean.") sys.exit(1) - print(f"\033[32m● MATRIX GREEN\033[0m — {len(rows)} towns (synthetic + fixtures + real caches) pass all 5 gates.") + print(f"\033[32m● MATRIX GREEN\033[0m — {len(rows)} towns (synthetic + fixtures + real caches) pass all 6 gates.") sys.exit(0)