1. validate_atlas (the G2a format gate). pipeline/validate_atlas.py, wired into validate_manifest so it
runs in qa gate 3. Judges Lane G's tier-1 atlases from the COMMITTED FILES ALONE -- no dealgod DB, no
network. No atlases yet => clean pass, so it's in place before G's lands. Enforces: provenance
{license, attribution, generator, snapshot} (charter law #3 + determinism); NO private-individual item
fields (law #3); 1 atlas/shop hard cap 2 (C §7.1); <=1024², 2048² only for a 60+ item shop (C §7.2);
declared atlas_px == the atlas's REAL pixels + every listed atlas exists; schema/UV/bands/dup-ids
(C §7.3). The licence string is PRINTED, not pattern-matched -- clearing photos for public release is
a human call, so the gate surfaces it. Dependency-free PNG/WebP header parser. Tested against a
10-case matrix (real 2048² WebP + 1024² PNG): good passes clean, all 9 violations caught.
2. toowoomba RETIRED (my call, counted). Tried the re-bbox FIRST: 3.0km CBD-wide -> 1.6km on the Ruthven
St heart. It fixed the named metric (median NN 395.7 -> 89.4m raw, 'passes') but made the real thing
WORSE: hub density 3/12 -> 2/12 within 160m, the pack's worst (D's alive-darwin is 7/12). Its shops
are PAIRS strung along a road, not a high street; densest 300m cluster is 3 shops (< MIN_TOWN_SHOPS),
so no tighter box exists. Shipping it would have gamed the number while leaving a town nobody shops in
(D: 0 finds / 1417 checks). Config entry kept commented with the rationale. Pack: 21 real + 1 godverse
= 22 rostered, 1180 shops, all 8 states/territories (QLD keeps westend). selfcheck ALL GREEN 152015.
-> Lane A, before you freeze the spacing warn (#5): (a) your validator sees the CACHE (raw lat/lon) but
D's numbers are SEATED (post-lift) -- darwin is 27m seated vs 68.3m RAW, so a threshold picked off D's
table would FALSE-WARN darwin; calibrate on the raw spread (daylesford 11.6 ... braddon 119.2,
ballarat 254.6 -- a ~200m line has daylight). (b) median NN alone is GAMEABLE: my re-bbox improved it
4.4x while the town got worse -- the hub fraction is the discriminator, and my raw hub metric
reproduces D's darwin exactly (7/12), so it's directly encodable (alive ~38-75%, dead <=20%).
(c) ballarat is a SECOND spread town D's two-town comparison missed (NN 254.6m, hub 4/20 = 20%) -- it
will trip your warn, correctly. Not retired: the ledger named toowoomba only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 lines
4.7 KiB
Markdown
81 lines
4.7 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 · 1180 shops · 295 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.
|
||
|
||
| state | towns |
|
||
|---|---|
|
||
| NSW (6) | katoomba · newtown · glebe · marrickville · newcastle (Hamilton strip) · bowral |
|
||
| VIC (7) | fitzroy · brunswick · geelong · bendigo · ballarat · castlemaine · daylesford |
|
||
| WA (2) | fremantle · northbridge |
|
||
| QLD (1) | westend |
|
||
| TAS (2) | hobart · launceston |
|
||
| SA (1) | adelaide |
|
||
| ACT (1) | braddon |
|
||
| NT (1) | darwin |
|
||
|
||
**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.
|
||
|
||
## 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).
|