THE STREET (ledger #3). redhill_real: Red Hill, Brisbane — 36 shops (9 heroes + 27 texture, -29 subsampled), 884 roads, median NN 73 m. **Musgrave Road is in roads[] (41 ways, primary + residential)** — that was the point: Monster Robot Party's real shop now has its real street. One bounded Overpass fetch under the standing authorization; raw snapshots in _raw/, ODbL, C's mapping. This is G's donor for godverse_town.py -> redhill_godverse. TWO HAZARDS HANDED TO G/A, both measured against the real geometry (notes R24 §1): (a) The shop is NOT in OSM — no shop=music node, no name match anywhere in the bbox (checked the raw snapshot, not the emitted cache). It cannot arrive via the fetch; G must inject id 3962749 from the census or the town ships without the shop the release is about. (b) THE SEATING HAZARD: A's lift seats on the NEAREST edge, and from G's geocode three streets are nearer than the addressed one — Zig Zag Street 38.6 m (residential), Craig Street 46.1 m, Musgrave Road 51.6 m. The shop would seat on Zig Zag St and the headline would quietly become false. Measured fix (G's call): the point on the real Musgrave centreline nearest G's geocode is -27.455169, 153.006902 — 0 m to Musgrave, next candidate 43 m. Snaps the street, does NOT verify the house number; I have no address data for where #147 sits along the road. THE HONEST GATE (ledger #4). F's catch was right and there were FOUR bugs: the glob used the published-contract name the runtime can never load (0 matches -> returned 0: it passed identically whether atlases were absent, misnamed, or perfect); the code read provenance top-level while my own docstring said nested (G nested it correctly — the gate would have failed G's real artifact); licence/license; and a stale ceiling. Rebuilt on the "runtime is the authority" ruling: globs stock_godverse/<id>/stock_<type>_index.json, type in {record,book,toy}. Vacuous-gate law implemented literally — 0 matches + stray files FAIL (listing them); 0 matches + empty dir prints "atlas-QA SKIP: no atlases present (0 files matched glob ...)"; plus an id equality (shop.godverse_id == dir) so it proves it touched its subject. Proved on four cases: empty -> loud SKIP, misnamed (F's exact bug) -> FAIL, unparseable -> FAIL, G's real atlas -> PASS (120 items, 2 atlases, licence printed). My own test found a fifth hole — the glob still matched the old stock_shop_* name, so the misnamed case failed only incidentally; added a STOCK_TYPES name check so it fails for the RIGHT reason. A gate that fails for the wrong reason will pass for the wrong reason later. BALLARAT — RETIRED, counted, and a DIFFERENT illness from Toowoomba (notes R24 §3). Toowoomba was dead everywhere. Ballarat is alive exactly where the game isn't: 103 POIs, densest 400 m disc = 47 of them (Toowoomba's was 3) — but that disc is cafes/clothes/bakeries while the op-shops sit 854 m, 1042 m and 1709 m out. Heroes and density don't coincide, so no bbox holds both. Real builds at every span: 1.0 km -> 8 shops/184 m/hub 4-8 but ZERO op-shops (a thrift town with no thrift shop); 2.0 km -> 12/186 m/3-12; 3.0 km as shipped -> 20/255 m/4-20. Every row worse than any shipped town. THE BINDING CONSTRAINT WAS MINE, NOT OSM'S: with 2 heroes the 3x texture cap keeps 6 of 47 texture POIs and the subsample is spatially blind, so survivors scatter at any span — part of the 255 m A's warn caught was my own cap's fingerprint. Seeding texture near heroes fixes the class but moves every town's golden -> filed as a v5.x proposal, not done in a release round. I OVERSTATED MY R23 ADVICE TO A: the hub fraction is NOT a standalone discriminator — glebe (shipped, healthy) reads 13% and redhill 14%; a hub threshold would false-flag both. Median NN is the robust primary; hub is only comparable at equal shop counts (toowoomba 2/12 vs darwin 7/12 was fair because both had 12). The raw-vs-seated calibration point stands. METHODOLOGY, recorded because it nearly shipped: I picked Ballarat's span from an offline simulation that predicted 68 m / hub 5-8, and had already written those numbers into a config comment as fact. The real build returned 184 m / 4-8 — same counts, different sample. Never trust a re-implementation of the pipeline's own selection; run the pipeline. -> A (batched pins): ADD REAL_TOWN_GOLDENS['redhill_real']=0x6046700f and REAL_TOWN_GIG_GOLDENS['redhill_real']=0x673785ee (the headline town currently only WARNS as UNPINNED — ungated until you pin it). REMOVE ballarat_real 0xf0a9e8a1 / 0xf097c331 — dead config by your own R23 note. -> F: tools/qa/tour_shots.py still shoots town=toowoomba_real, which I deleted in R23 — the v4 tour breaks on a missing town. Your file, your call. A retirement isn't done when the cache is deleted; it's done when the consumers are swept. -> C: built to the runtime + G's real artifact per the ruling; LANE_C_PUB §7 line 271 still names the contradictory stock_shop_<id>_index.json. I reconcile when your corrected contract lands. Determinism receipt: the retirement forced a full 21-town rebuild from cached raw (no refetches) and every existing cache came back byte-identical — only ballarat, redhill and index.json moved. Pack: 21 real towns · 1196 shops · 299 heroes (22 rostered with G's newtown_godverse). Selfcheck ALL GREEN 149,696, synthetic golden 0x3fa36874 unchanged. qa.sh --strict --matrix: 7 passed / 0 failed, MATRIX GREEN 10x7. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
102 lines
6.4 KiB
Markdown
102 lines
6.4 KiB
Markdown
# Town-cache data sources & licence (`web/assets/towns/`)
|
||
|
||
**Lane E owns this file** (ROUND17 ledger #6). Every real-town cache here is derived from
|
||
**OpenStreetMap** data and ships under OSM's licence. This notice + the `license`/`attribution`
|
||
fields on every `<key>.json` are the attribution that travels with the data.
|
||
|
||
## Licence — OpenStreetMap, ODbL 1.0
|
||
|
||
> © **OpenStreetMap contributors**. Data available under the **Open Database License (ODbL) 1.0**.
|
||
> <https://www.openstreetmap.org/copyright> · <https://opendatacommons.org/licenses/odbl/1-0/>
|
||
|
||
The caches are a **produced work** derived from OSM via the Overpass API (`overpass-api.de`), filtered
|
||
to on-theme `shop=*` points, deduped, suburb-filled, and type-mapped by `pipeline/build_towns.py`.
|
||
Attribution ships in-repo (this file) and in every cache (`"license":"ODbL 1.0"`,
|
||
`"attribution":"© OpenStreetMap contributors"`). If a rendered/public build surfaces this data, keep
|
||
the "© OpenStreetMap contributors (ODbL)" credit visible.
|
||
|
||
## Provenance table
|
||
|
||
**`index.json` is the machine-readable roster** (key/town/state/shops/roads) — read it rather than
|
||
hardcoding a list. Every cache carries the same terms; per-town numbers live in each cache's `counts`.
|
||
|
||
**The pack: 21 real towns · 1196 shops · 299 heroes** (+ Lane G's `newtown_godverse` = 22 rostered in
|
||
`index.json`), every one fetched from OSM Overpass with a bounded per-town bbox, ODbL 1.0, raw snapshots
|
||
in `_raw/` (shops + roads per town), fetched 2026-07-16 (`redhill_real` 2026-07-17).
|
||
|
||
| state | towns |
|
||
|---|---|
|
||
| NSW (6) | katoomba · newtown · glebe · marrickville · newcastle (Hamilton strip) · bowral |
|
||
| VIC (6) | fitzroy · brunswick · geelong · bendigo · castlemaine · daylesford |
|
||
| QLD (2) | westend · **redhill** (Monster Robot Party's real street — see below) |
|
||
| WA (2) | fremantle · northbridge |
|
||
| TAS (2) | hobart · launceston |
|
||
| SA (1) | adelaide |
|
||
| ACT (1) | braddon |
|
||
| NT (1) | darwin |
|
||
|
||
### `redhill_real` — the v5 crate's real street (R24, ledger #3)
|
||
|
||
**Red Hill, Brisbane QLD** · centre `-27.4553, 153.0064` · span 2.4 km · 36 shops (9 heroes + 27 texture,
|
||
−29 subsampled) · 884 roads · median NN 73 m, hub 5/36. Built because v5's 120 real records come from a
|
||
real shop — **Monster Robot Party, 147 Musgrave Rd** — and the shop had no street. **Musgrave Road is in
|
||
`roads[]` (41 ways, primary + residential)**, which was the point of the round. This cache is the DONOR
|
||
Lane G runs `godverse_town.py` against → `redhill_godverse`.
|
||
|
||
The shop itself is **not in OSM** (no `shop=music` node in the bbox), so G injects it from the census —
|
||
it cannot arrive via this fetch. See LANE_E_NOTES R24 for the seating hazard handed to G/A.
|
||
|
||
**Retired (R23, counted):** `toowoomba_real` — D's clustering audit measured it DEAD (0 patronage finds
|
||
in 1417 checks); a re-bbox onto the Ruthven St heart fixed the spacing metric (median NN 396 → 89 m) but
|
||
made the hub worse (2/12 within 160 m, the pack's worst), and its densest 300 m cluster is only 3 shops.
|
||
Cache + raw snapshots removed; the config entry stays commented with the rationale. See LANE_E_NOTES R23.
|
||
|
||
**Retired (R24, counted):** `ballarat_real` — A's spacing warn caught it at median NN 255 m. Unlike
|
||
Toowoomba, Ballarat is **not dead**: 103 POIs in the bbox, densest 400 m disc = 47 of them. It fails a
|
||
different way — **its live core and its heroes don't coincide.** The dense disc is cafés/clothes/bakeries;
|
||
the op-shops sit 854 m, 1042 m and 1709 m out, so no bbox holds both. Measured at every span (real builds):
|
||
1.0 km → 8 shops / NN 184 m / hub 4/8 but **zero op-shops** (a thrift town with no thrift shop); 2.0 km →
|
||
12 / 186 m / 3-12; 3.0 km (as shipped) → 20 / 255 m / 4-20. Every row is worse than any shipped town
|
||
(darwin 68 m, glebe 60 m, redhill 73 m). The binding constraint is ours, not OSM's: with 2 heroes the 3×
|
||
texture cap keeps 6 of 47 POIs and the subsample is **spatially blind**, so survivors scatter at any span.
|
||
Cache + raw snapshots removed; config entry commented with the rationale. See LANE_E_NOTES R24.
|
||
|
||
## The density widening (v4.0-beta, ROUND20 ledger #2)
|
||
|
||
The fetch covers the **secondhand heroes** plus the everyday main-street **texture** (bakery/cafe/deli/
|
||
newsagent/chemist/clothes/hardware/greengrocer/…), mapped to existing registry types per **C's
|
||
LANE_C_PUB §6** table. Tasteful staples only — no vehicle/fuel, funeral, storage, industrial, or pure
|
||
services. `cafe` rides `amenity=*`; everything else is `shop=*`. Per John's **subtle** directive the
|
||
heroes are **never** subsampled and texture is capped at **3× the hero count** (deterministic
|
||
`sha256(townKey:osmId)` rank); every drop is counted in each cache's `counts.textureDropped`.
|
||
|
||
## `index.json` — the towns roster
|
||
|
||
`{schema:"procity-towns-index/1", generated, license, attribution, towns:[{key, town, state, shops,
|
||
roads}]}`. Same ODbL terms as the caches. Consumers (B's selector) derive the town list from this
|
||
rather than hardcoding.
|
||
|
||
## Raw responses (`_raw/`)
|
||
|
||
The raw Overpass JSON is cached in-repo (wrapped with `fetchedAt`, `endpoint`, `query`, `bbox`):
|
||
`_raw/<key>.overpass.json` (shops) and `_raw/<key>.roads.overpass.json` (OSM highway ways, schema v2).
|
||
**Re-runs reuse the raw cache and never re-hit Overpass** — the fetch is outward-facing network
|
||
(John-authorized scout, once per town). `--refetch` forces a deliberate re-fetch. `selfcheck.js` reads
|
||
only top-level `*.json`, so `_raw/` is never loaded as a cache.
|
||
|
||
## Roads — schema v2 (ROUND18, v4.0-alpha REAL ROADS)
|
||
|
||
A v2 cache carries `roads[]` — the town's real OSM street geometry (`highway=*` ways), same ODbL licence
|
||
and attribution as the shops. **Fidelity cut** (charter risk #4): the raw fetch grabs every `ROAD_KIND`
|
||
tier, but the emitted `roads[]` is the **town street graph only** — drivable roads + pedestrian malls;
|
||
`service`/`track`/`footway`/`path`/`steps`/`cycleway` are excluded (in Katoomba, 1461 of 2506 ways —
|
||
bushwalking tracks, sidewalks, stairs, driveways). The excluded tier stays in the raw response if a
|
||
tier is wanted back. `katoomba_real` is v2 (the alpha); the other towns' roads land as data-only.
|
||
|
||
## Names — parody vs factual
|
||
|
||
Big **trademarked charity/franchise chains** are parodied in `build_towns.py` (Salvos→Slave-ohs,
|
||
Vinnies→Sinnies, Anglicare→Tanglecare, Cash Converters→Cashtheists, …) for the game's comic tone.
|
||
**Independent shops keep their real OSM name** — factual, publicly-mapped POI data under ODbL. No
|
||
private-individual data is carried (name/type/coordinate/suburb only).
|