Compare commits

...

6 Commits

Author SHA1 Message Date
m3ultra
201a2bb868 Lane F R21 (v4.0-beta close): the beta gate — tram dimension, the re-measure, the beta shot
All five lanes in (A's venue cluster bias, B's selector-from-index, C's density door-soak, D's relocation
verify PASSES, E's 22-town pack non-gating); F gated and tagged.

- town_matrix.py: a `tram` dimension — B's R20 shop-adjacency ruling verified EXACTLY (newtown runs 16 stops
  after B's phantom-stop fix, castlemaine 10; katoomba/fremantle/bendigo FENCED at 3/2/1 shops fronted, all
  below the 5-shop floor). 10 towns x 7 gates: boot/determ/district/roads/tram/noassets green on all ten.
- index.html: expose window.PROCITY.tram — B built `routeInfo` FOR F's smoke but nothing published it; F owns
  the shell, so F wired the seam.
- RECORDED (ledger #6b — the instruction was "record the new number"): the venue_night re-measure. A's cap
  WORKED (posters 438->111) but E's density widening ate it — katoomba 200,965 (+965, R19) -> 221,935
  (+21,935, +11%); bendigo 201k (+0.5%); fremantle/newtown/castlemaine in budget. Draws fine everywhere
  (151/300 — half budget); tris-only, at the worst night stress view. Filed as R22's first item, where the
  tri-diet backlog (instrument LOD, tram tri diet) already lives. katoomba is the outlier: 966 edges, 72 shops.
- Ruling (ledger #6d): the town selector stays ALWAYS-IN-HUD, not ?dbg-gated — THE REAL MAP's product IS the
  towns. Corollary (F's own gap): money shots hide the HUD; the R19 alpha shot had the selector in-frame
  because F's harness screenshotted the full viewport.
- Beta money shot: Fremantle's real street at golden hour — a corridor of shopfronts, footpaths, a crossing,
  gum trees, and a genuinely busy crowd (the density widening, visible). 126d/167k tris, HUD hidden.
- docs: LANE_F_NOTES §20 (the honest why-R20-had-no-tag record) + §21, README beta paragraph, F-progress.

qa.sh --strict GREEN; selfcheck 154141/154141 (A's re-pinned goldens hold).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:37:04 +10:00
m3ultra
01c925816e Lane D R21 (v4.0-beta close): relocation verify — A's venue cluster bias PASSES (ledger #4)
Verified A's venue cluster-adjacency bias (110c828), assigned from my R20 relocation
finding. selfcheck ALL GREEN 154141/154141 against A's re-pinned goldens.

ACCEPTANCE PASSES ON ALL FIVE (no venue with <3 shops in its 160m radius):
katoomba min 9 | newtown min 5 | bendigo min 5 | castlemaine min 4 | fremantle min 3.
Castlemaine's floor did NOT need an exemption.

MY HEADLINE FINDING IS CLOSED: katoomba's pub — "a gig with no passing crowd", 1 shop
at 1007m — now sits at 466m with 9 shops. Newtown is the dramatic fix: all three venues
were 2.2-2.4km out with 0-1 shops; its rsl now sits 29m from the hub with 11.

THE CROWD FOLLOWED (katoomba pub, same density/seed/21:00): passing crowd 34->66 (2x),
patron checks 226->442 (2x), inside frames 1042->1424, roster 2->3, 0 NaN.

TWO READINGS THAT NEED CARE:
- fremantle is the weakest pass: pub/rsl clear the >=3 bar but moved FURTHER from the
  primary hub (969->1352m, 561->1292m) — A's bias optimises local cluster adjacency and
  they found a secondary cluster. Letter satisfied, crowd healthy (pub roster 6, inside
  2741), so not a miss — just named. A's call if they want it tighter.
- venue-win % DROPPING is not a regression (newtown rsl 100%->21%). It was only 100%
  because the venue was alone; post-bias it has neighbours competing for finds while
  total crowd rose. Isolation flatters that metric — ignore it post-bias.

D->F: relocation verify GREEN, no gate concern for v4.0-beta.
FYI F: selfcheck scans every towns/*.json on disk incl. E's UNTRACKED pack WIP — I saw
it transiently RED (newcastle_real, no open-late shop) then green minutes later. If you
gate while E is mid-fetch you may catch a false red; check if a failure is a pack town.
Still filed for v4.x: GIG_RANGE 34m radius vs single-chunk lookup (8.7% chunk-blind).
Flagged as unowned: R20's main-street relocation half (hero strip vs densest cluster).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:09:38 +10:00
m3ultra
8a383e494e Lane E R21 (v4.0): the town pack — 22 towns, 1192 shops (DATA-ONLY, non-gating)
Ledger #5 pull-forward. Nothing here touches a golden until A absorbs in R22; F tags v4.0-beta with
or without it. selfcheck ALL GREEN 154141/154141, synthetic 0x3fa36874 unmoved, all 22 byte-identical
on re-run.

- Curated 18 candidates on secondhand density first (heroes are the game), a walkable 2-3.4km centre,
  and a national spread; 17 survived -> 22 towns, 1192 shops, 298 heroes, all 8 states/territories.
  fitzroy is the mecca (40 heroes/160 shops, 2x katoomba); thin tail toowoomba/darwin (3 heroes) left
  in as honest data -- A/Fable may drop them in R22.
- FINDING: the 3x-hero cap is a CURATION FILTER, not just a density knob. Wollongong had ~62 real
  shops but 1 hero -> capped to 4 -> dropped by the >=6 floor. A town without a secondhand strip
  cannot inflate into a retail strip; John's SUBTLE directive does quality control for free.
- Newcastle: my centre was wrong, not the town (CBD held 2 heroes; the strip is Hamilton/Beaumont St).
  Re-centred: 2 -> 9 heroes, 8 -> 36 shops.
- BUG (mine, shipped R18, caught here): fetch_roads_raw had no query-comparison while fetch_raw did,
  so re-centring refetched shops but silently reused the OLD CBD roads -> Hamilton shops seated against
  a graph 2.5km away -> the town marched out with ZERO shops (surfacing as 32 bogus 'open-late
  invariant' failures; ten other no-video towns passing is what proved it wasn't the open-late rule).
  Fixed: the roads path now compares its query too -- the bbox lives in the query, so a re-centre must
  invalidate BOTH snapshots. Newcastle rebuilt: 34 shops seated, openLate=1.
- Discipline: bounded bboxes, raw snapshots committed (shops+roads), C's §6 mapping, SUBTLE guardrails
  (heroes never subsampled, texture 3x, 2392 drops counted), ODbL. Overpass rate-limits hard at pack
  scale (batch 1 died on a fatal 504 after 25 retries) -- courtesy sleep 4s, two polite batches.

-> Lane A (R22): 34 goldens to pin (17 new towns x base+gig); sizes 12->160 shops load-test your
   capacity/overflow fences. -> Lane B: index.json now lists 22 towns (your selector already reads it).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:06:46 +10:00
m3ultra
c134584b88 Lane C R21 (v4.0-beta): the five-town density door-soak (ledger #3)
Wave 2 — ran after A's venue cluster-adjacency bias landed (110c828), so the soak reads the
relocated world + A's re-pinned goldens. The carried R20 #6.

Five towns at their new densities, ~25 deterministically sampled doors/town (sample takes one
of EVERY type present, then stride-fills, so the texture classes' first real appearance is
always covered):

  town              shops  sampled  venues  types  worst draws   verdict
  katoomba_real      72      25       3      10       157         PASS
  newtown_real       67      25       3      11       155         PASS
  fremantle_real     79      25       3      11       153         PASS
  bendigo_real       35      25       3      10       154         PASS
  castlemaine_real   23      23(all)  3       8       156         PASS

123 doors: 0 throws / 0 carves / 0 path-fails / 0 over-budget, worst 157 draws (<=350).
typesInTown == typesSampled in every town (all archetypes entered, incl. all 3 venue kinds).
All five towns landed 3 venues -> A's cluster bias + district placement hold at density.

§6 mapping verified live: katoomba cache = 20 heroes + 60 texture (exactly E's 3x cap, heroes
untouched). Texture's first real appearance renders right -- "Blue Mountains Chocolate Company"
(real OSM shop=chocolate) wears milkbar as a believable confectionery counter shop. Texture,
not takeover. Cache->plan deltas are A's counted drops, not an interior concern.

C->F: density verdict GREEN. Docs-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:05:17 +10:00
m3ultra
110c82833b Lane A round 21: venue cluster-adjacency bias — D's relocation finding (ledger #1)
D found katoomba's pub 1,000m from the retail cluster — a gig with no passing crowd. Measuring all
five towns first showed it was SYSTEMIC: 11 of 15 venues sat with <3 shops within 160m (newtown's were
0/0/1 — every venue stranded). After the bias: 0 of 15. Katoomba's pub 1 → 9. Castlemaine cleared without
needing the floor exception the brief anticipated.

- pickVenues builds a CLUSTER-ADJACENT field first (>= CLUSTER_MIN 3 shops within CLUSTER_R 160m), then the
  kind flavors (pub corner / band_room fringe / rsl off-spine) bias WITHIN that field rather than overriding
  it (per the brief: biases, not absolutes) — a fringe band_room in the cluster beats one a kilometre from
  anyone. A town with no cluster at all falls back to the pool.
- SYNTHETIC FROZEN BY CONSTRUCTION, not by luck. The brief assumed a blanket filter would be a no-op because
  'the synthetic town is one dense cluster anyway'. Measurement says otherwise: 4 synthetic candidates PER
  SEED sit under the threshold (min cluster 0-1), so a blanket filter WOULD have moved the frozen golden.
  Gated on plan.source === 'osm' (undefined on synthetic) — impossible rather than unlikely. The marched
  fixtures are 'osm' but genuinely dense (min cluster 3/11/13) ⇒ verified no-op.
- Only the GIG goldens moved (venue selection is gig-layer; base town goldens untouched): katoomba
  0xbf586b77, newtown 0xacdb3eee, fremantle 0xcf3426fc, bendigo 0x646b2c23, castlemaine 0xf9713a69.
  classic 0x3fa36874 / gig 0xb1d48ea1 / marched fixtures FROZEN. selfcheck ALL GREEN 66419/66419;
  scaffold + consistency GREEN; cross-process deterministic.
- FYI: E's v4.0 pack (glebe/marrickville/newcastle) already boots clean through my loader (validates + full
  suites pass), listed UNPINNED — I pin the pack in R22; it does not gate the beta tag.

Handshake → C + D: cluster bias landed, goldens re-pinned, start your verifies (before/after table in
LANE_A_NOTES §R21).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:37:45 +10:00
m3ultra
4b0144989b Lane B round 21 (v4.0-beta): town selector reads E's towns index (ledger #2, the missed R20 #5)
Closes the gap Fable caught (hud.js:11 still hardcoded REAL_TOWNS). The real-town list now comes from E's
web/assets/towns/index.json (procity-towns-index/1), so it grows with the town pack instead of being edited
in hud.js. Verified fresh Chromium. Nothing else touched -- tram/ground work is done and verified.

Fail-soft by construction: createHUD is synchronous, so the picker is built immediately from the fallback
literal and UPGRADED IN PLACE when the index resolves -- if the index never arrives, a working list is
already on screen.
- index present -> real names/states/shop counts: "Katoomba, NSW · 80 shops", "Fremantle, WA · 80 shops",
  "Newtown, NSW · 72 shops", "Bendigo, VIC · 36 shops", "Castlemaine, VIC · 24 shops" (roads:false -> "· marched").
- ?noassets -> the fetch is SKIPPED entirely (asset law; the shell doesn't load town caches there either).
  Measured: 0 index fetches, fallback list, 0 errors.
- anything wrong with the index -> the fallback simply stands. Exercised the exact chain: 404, network error,
  malformed JSON, towns:[], towns-not-an-array, junk entries (no key) -> none throws, none rebuilds from junk;
  only a good index rebuilds.

REAL_TOWNS_FALLBACK is retained ONLY as that fallback (comment says so), no longer the source of truth.
Verified live: booting katoomba_real shows "Katoomba, NSW · 80 shops" pre-selected; fits (193px of 230px max);
0 page errors; navigation unchanged (onchange is set once on the <select>, so rebuilding options never clears it).

-> F: unchanged from R19 -- NO shell seam (selector is entirely hud.js, already built by createHUD) and it
   lives inside #pc-hud so setVisible(false) hides it for the beta money shot. The gating call is still yours.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:35:47 +10:00
71 changed files with 3122077 additions and 46 deletions

View File

@ -3,7 +3,40 @@
*Status: **v1 complete & verified**. Standalone interiors library + test page. Every shop door opens
into a unique, seeded, themed interior, generated on demand in ~4ms, byte-identical every revisit.*
Last updated: 2026-07-16 (round 20) · owner: PROCITY-C · reviewer: Fable
Last updated: 2026-07-16 (round 21) · owner: PROCITY-C · reviewer: Fable
---
## Update 2026-07-16 (round 21, v4.0-beta close) — the five-town density door-soak (ledger #3)
R21 §Lane C (wave 2 — ran **after A's venue cluster-adjacency bias** landed, `110c828`, so the soak reads the
relocated world + A's re-pinned goldens). The carried R20 #6: **every one of the five beta towns at its new
density**, deterministically sampled ~25 doors/town — the sample takes **one of every type present** then
stride-fills, so the texture classes' first real appearance (milkbar/dept/stall on real shops) is always covered.
| town | shops (in plan) | sampled | venues | types (all sampled) | throws | carves | path-fails | over-budget | worst draws |
|---|---|---|---|---|---|---|---|---|---|
| `katoomba_real` | 72 | 25 | 3 | 10 | 0 | 0 | 0 | 0 | **157** |
| `newtown_real` | 67 | 25 | 3 | 11 | 0 | 0 | 0 | 0 | 155 |
| `fremantle_real` | 79 | 25 | 3 | 11 | 0 | 0 | 0 | 0 | 153 |
| `bendigo_real` | 35 | 25 | 3 | 10 | 0 | 0 | 0 | 0 | 154 |
| `castlemaine_real` | 23 | 23 (all) | 3 | 8 | 0 | 0 | 0 | 0 | 156 |
**123 doors · 0 throws · 0 carves · 0 path-fails · 0 over-budget · worst 157 draws (≤350).** In every town
`typesInTown === typesSampled` — every archetype present was entered, including all three venue kinds
(pub/band_room/rsl) and the texture classes. **All five towns landed 3 venues** → A's cluster bias + district
placement hold at density.
**§6 mapping verified live (John's SUBTLE directive, working by construction):** katoomba's cache is **20
heroes + 60 texture** — exactly E's 3× cap, heroes untouched. In-plan (after A's counted drops): 17 heroes
(opshop 10 · book 4 · record 2 · video 1) + 52 texture (milkbar 29 · dept 18 · stall 5) + 3 venues = 72.
The texture classes' **first real appearance** renders right: **"Blue Mountains Chocolate Company"** — a real
Katoomba `shop=chocolate` — now wears `milkbar` (70s geo wallpaper, cube shelves of price-tagged goods, counter,
wall rack): a believable confectionery counter shop. The widening reads as texture, not takeover.
*(Cache→plan deltas — e.g. katoomba 80→72 — are A's overflow/fragmentation drops, counted by cause in A's R20
accounting; not an interior concern, and every surviving door builds clean.)* **C→F: density verdict GREEN.**
Docs-only. C otherwise on-call; my §6 mapping + this soak close both C items for the beta.
---

View File

@ -4,6 +4,28 @@
---
## Round 2021 (v4.0-beta THE FIVE TOWNS) — F never ran R20; closed R21
**R20: F never ran** (no gate, no tag) — the honest record is in LANE_F_NOTES §20. Unlike R18 (where F ran
and *held* on evidence), the slot simply didn't execute; the round also left C's door-soak, B's selector
index, and D's relocation finding open. R21 closed all four.
**R21: the beta gate.** Waves [A,B,E] → [C,D] → [F]. All five lanes in; F gated:
- **Matrix 10 towns × 7 gates** — boot/determ/district/roads/**tram**/noassets green on all ten; selfcheck
154141/154141; `qa.sh --strict` GREEN.
- **Tram dimension (new)** — B's R20 ruling verified exactly: Newtown runs 16 stops (was 149 — B's phantom
fix), Castlemaine 10; Katoomba/Fremantle/Bendigo **fenced** at 3/2/1 shops fronted. Needed a new seam:
the shell now exposes `window.PROCITY.tram` (B built `routeInfo` for F's smoke; nothing published it).
- **⚠ venue_night re-measure — recorded, premise falsified.** A's cap worked (posters 438→111) but the
density widening ate it: katoomba **200,965 (+965) → 221,935 (+21,935, +11%)**; bendigo 201k. Draws fine
(151/300). Filed as R22's first item (the tri-diet backlog already lives there).
- **Selector ruling** — always in the HUD (the towns *are* the product), + the corollary that F's harness
must hide the HUD for beauty shots (the R19 alpha shot's selector-in-frame was F's own gap).
- **Beta money shot** — [Fremantle's real street at golden hour](docs/shots/v4_beta/fremantle_mainstreet.png):
a corridor of shopfronts, footpaths, a crossing, and a genuinely busy crowd. Tag **`v4.0-beta`**.
---
## Round 1819 (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

View File

@ -74,7 +74,17 @@ 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=<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`). **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 |
| `?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-beta — the five towns, at density
Five real Australian towns (**Katoomba, Newtown, Fremantle, Bendigo, Castlemaine — 292 shops**) boot on
their **actual OSM street graphs**, at real retail density: secondhand heroes keep their footfall while the
street around them gets ~4× busier (texture, never a takeover). Venues bias toward the retail cluster, the
tram runs only where it fronts a real high street (Newtown/Castlemaine — elsewhere it was "a highway bus",
so it's fenced), and the in-HUD **town selector** reads the towns index, so you can just pick one. Every
town: deterministic, districted, silent under `?noassets`, `?classic=1` still byte-identical to v2.
See [`docs/shots/v4_beta/`](docs/shots/v4_beta/) and the charter, [`docs/V4_REAL_MAP.md`](docs/V4_REAL_MAP.md).
| `?seed=N` | `20261990` | town seed |
**Release tour:** [`docs/shots/release_v3_1/contact.html`](docs/shots/release_v3_1/) — the money shots on

View File

@ -1,11 +1,35 @@
# LANE A — CITYGEN · progress (PROCITY-A)
*Status: **all deliverables landed; self-check all-green (51866/51866); rounds 220 closed** (see below).
v4.0-beta: spine-poster cap scaled by shop count (katoomba 438→31, closes F's venue_night edge) + E's
density widening absorbed (5 towns at 36× shops, all place 3 venues, drops 5.5% counted by cause); all 10
real-town goldens (base + gig) pinned. classic/gig/marched-fixtures frozen.*
*Status: **all deliverables landed; self-check all-green (66419/66419); rounds 221 closed** (see below).
R21: venue cluster-adjacency bias — D's relocation finding resolved (venues under 3 shops/160 m: 11 of 15
→ 0); gig goldens re-pinned; synthetic frozen by construction. R20: poster cap (katoomba 438→31) + E's
density widening absorbed (5 towns at 36× shops). classic/gig/marched-fixtures frozen.*
*Date: 2026-07-16 · owner: PROCITY-A (Opus 4.8)*
## Round 21 (2026-07-16) — v4.0-beta: the venue cluster-adjacency bias (ledger #1, the round's spine)
D filed it: katoomba's pub sat 1,000 m from the retail cluster — a gig with no passing crowd. Measuring all
five towns first showed it was **systemic: 11 of 15 venues** had <3 shops within 160 m (newtown's were
0/0/1). After the bias: **0 of 15**. Katoomba's pub went **1 → 9**; castlemaine cleared without needing the
floor exception Fable anticipated.
- `pickVenues` now builds a **cluster-adjacent field** (≥`CLUSTER_MIN` 3 shops within `CLUSTER_R` 160 m),
then the kind flavors (pub corner / band_room fringe / rsl off-spine) bias **within** it rather than
overriding it (per the brief: biases, not absolutes). No cluster at all → falls back to the pool.
- **Synthetic frozen BY CONSTRUCTION**, not by luck. The brief assumed a blanket filter was a no-op because
"the synthetic town is one dense cluster anyway" — measurement says otherwise: **4 synthetic candidates
per seed** sit under the threshold (min cluster 01), so a blanket filter *would* have moved the frozen
golden. Gated on `plan.source === 'osm'` (undefined on synthetic). Marched fixtures are 'osm' but genuinely
dense (min 3/11/13) ⇒ verified no-op.
- **Only the GIG goldens moved** (venue selection is gig-layer): katoomba `0xbf586b77`, newtown `0xacdb3eee`,
fremantle `0xcf3426fc`, bendigo `0x646b2c23`, castlemaine `0xf9713a69`. Base goldens untouched.
classic/gig/marched fixtures frozen. selfcheck ALL GREEN **66419/66419**; scaffold + consistency GREEN;
cross-process deterministic.
- FYI: E's v4.0 pack (`glebe`, `marrickville`, `newcastle`) already boots clean through my loader (validates
+ full suites pass), listed UNPINNED — **I pin the pack in R22**; it does not gate the beta tag.
Handshake fired → C + D: cluster bias landed, goldens re-pinned, start your verifies.
## Round 20 (2026-07-16) — v4.0-beta THE FIVE TOWNS: the poster cap (density absorb pends E)
Two Lane-A deliverables; the first (independent) landed this commit, the second waits on E's widened caches.

View File

@ -2,6 +2,45 @@
Durable answers to questions other lanes raised against Lane A. Full status in `A-progress.md`.
## Round 21 (2026-07-16) — the venue cluster bias (D's relocation finding) + goldens re-pinned
### → C + D: **cluster bias landed, goldens re-pinned — start your verifies** (the handshake)
**Only the GIG goldens moved** (venue selection is gig-layer; the base town goldens are untouched):
katoomba `0xbf586b77`, newtown `0xacdb3eee`, fremantle `0xcf3426fc`, bendigo `0x646b2c23`,
castlemaine `0xf9713a69`. Base unchanged (katoomba `0x420f677d`, …). selfcheck **ALL GREEN 66419/66419**;
classic `0x3fa36874` / gig `0xb1d48ea1` / marched fixtures **frozen**.
### → D: your relocation finding is resolved — and it was systemic
You found katoomba's pub at 1 shop within 160 m. Measuring all five, **11 of 15 venues** sat under the
threshold (newtown's were 0/0/1 — every venue stranded). After the bias, **0 of 15**:
| town | before (shops within 160 m) | after |
|---|---|---|
| katoomba | pub **1**, rsl 10, band_room 7 | band_room 10, rsl 12, **pub 9** |
| newtown | band_room 0, pub 0, rsl 1 | band_room 7, rsl 11, pub 5 |
| fremantle | pub 1, rsl 2, band_room 2 | band_room 8, pub 3, rsl 3 |
| bendigo | pub 1, rsl 0, band_room 0 | rsl 10, band_room 10, pub 5 |
| castlemaine | band_room 6, rsl 4, pub 1 | pub 5, band_room 6, rsl 4 |
Castlemaine cleared without needing the floor exception Fable flagged. Your venue-win % and the "gig with
no passing crowd" observation should both improve — the pub is now in the retail heart on every town.
### How it works (and why synthetic is frozen BY CONSTRUCTION, not by luck)
`pickVenues` builds a **cluster-adjacent field** first (candidates with ≥ `CLUSTER_MIN` 3 shops within
`CLUSTER_R` 160 m), then the kind flavors (pub corner / band_room fringe / rsl off-spine) bias **within**
that field rather than overriding it — a fringe band_room in the cluster beats a fringe band_room a
kilometre from anyone. A town with no cluster falls back to the whole pool.
**Gated on `plan.source === 'osm'`** — real-data towns only. Fable's brief assumed a blanket filter would
be a no-op because "the synthetic town is one dense cluster anyway". **It isn't:** I measured **4 synthetic
candidates per seed** sitting under the threshold (min cluster 01), so a blanket filter *would* have moved
the frozen synthetic golden. The `source` gate makes it impossible instead of unlikely. The marched fixtures
are 'osm' too but genuinely dense (min cluster 3/11/13) ⇒ verified no-op.
### FYI: E's v4.0 town pack is already booting clean
`glebe_real`, `marrickville_real`, `newcastle_real` landed and my loader auto-validates + boots them through
the full structural + gig suites — **all pass**, listed UNPINNED (a non-fatal warn). That's per the brief:
**I pin the pack in R22**, and it must not gate the beta tag. Early signal: the pack needs no new hardening.
## Round 20 (2026-07-16) — v4.0-beta: the poster cap (density absorb pending E's widened caches)
### → F: **poster cap landed — re-measure `venue_night`** (your +965-tri edge should close)

View File

@ -1,5 +1,41 @@
# LANE B — NOTES (measured)
## Round 21 (Fable's ROUND21 → Lane B) — selector from E's towns index (ledger #2, the missed R20 #5)
Closed the R20 gap Fable caught (`hud.js:11` still hardcoded `REAL_TOWNS`). The real-town list now comes
from **E's `web/assets/towns/index.json`** (`procity-towns-index/1`), so it grows with the town pack instead
of being edited in `hud.js`. Verified fresh Chromium. Nothing else touched — the tram/ground work is done.
### How it works (fail-soft by construction)
`createHUD` is synchronous, so the picker is **built immediately from the fallback literal** and then
**upgraded in place** when the index resolves. That ordering *is* the fail-soft: if the index never arrives,
the working list is already on screen.
- **Index present** → real names, states and shop counts: `Katoomba, NSW · 80 shops`, `Fremantle, WA · 80
shops`, `Newtown, NSW · 72 shops`, `Bendigo, VIC · 36 shops`, `Castlemaine, VIC · 24 shops`. (`roads:false`
towns would read `· marched`; none today.)
- **`?noassets`** → the fetch is **skipped entirely** (asset law — the shell doesn't load town caches there
either, so reading the index would be pointless as well as illegal). Measured: **0 index fetches**,
fallback list, 0 errors.
- **Anything wrong with the index** → the fallback simply stands. Exercised the exact chain against every
nasty case; **none throws, none rebuilds from junk**:
| index case | result |
|---|---|
| 404 / missing · network error · malformed JSON | fallback stands ✅ |
| `towns: []` · `towns` not an array · junk entries (no `key`) | fallback stands ✅ |
| good index | rebuilds from index ✅ |
`REAL_TOWNS_FALLBACK` is retained **only** as that fallback (comment says so) — it is no longer the source
of truth. Verified live: booting `katoomba_real` shows `Katoomba, NSW · 80 shops` pre-selected; the picker
fits (193 px of its 230 px max); 0 page errors; navigation unchanged (`onchange` is set once on the
`<select>`, so rebuilding the options never clears it).
**→ Lane F:** unchanged from R19 — **no shell seam**, the selector is entirely `hud.js` (already built by
`createHUD`), and it lives inside `#pc-hud` so `setVisible(false)` hides it for the beta money shot. Your
R19 gating call (always-in-HUD vs `?dbg`) is still yours; one line either way.
---
## Round 20 (Fable's ROUND20 → Lane B) — the tram ruling + ground polish (ledger #3/#4, v4.0-beta)
### 1. The tram ruling (ledger #3) — route by SHOP ADJACENCY, fence per-town

View File

@ -6,6 +6,66 @@ _rotOnly/head-bone normalize/upgradeStreetPeople). Measurements on the M3 Ultra
---
## ROUND 21 — v4.0-beta CLOSE: relocation verify (ledger #4)
*PROCITY-D, 2026-07-16. Verifying A's venue cluster-adjacency bias (`110c828`), which Fable assigned from
my R20 relocation finding. `selfcheck` **ALL GREEN 154141/154141** against A's re-pinned goldens.*
### Verdict: A's bias PASSES acceptance on all five — my finding is closed
Acceptance was "no venue sits with <3 shops in its 160 m radius." Shops within 160 m @ distance-to-retail-hub,
before (R20) → after (R21):
| town | min shops in 160 m | before → after |
|---|---|---|
| katoomba_real | **9** PASS | **pub 1→9 @1007→466 m** · rsl 10→12 @161→148 m · band_room 7→10 @181→161 m |
| newtown_real | **5** PASS | **rsl 1→11 @2228→29 m** · band_room 0→7 @2433→124 m · pub 0→5 @2190→714 m |
| bendigo_real | **5** PASS | rsl 0→10 @451→86 m · band_room 0→10 @1157→96 m · pub 1→5 @504→316 m |
| castlemaine_real | **4** PASS | pub 1→5 @223→182 m · band_room 6→6 @0 m · rsl 4→4 @155 m |
| fremantle_real | **3** PASS* | band_room 2→8 @612→309 m · *pub 1→3 @969→**1352 m*** · *rsl 2→3 @561→**1292 m*** |
**My R20 headline is fixed**: katoomba's pub — "a gig with no passing crowd", 1 shop at 1007 m — now sits at
**466 m with 9 shops**. Newtown is the dramatic one: all three venues were **2.22.4 km out with 01 shops**;
the rsl now sits **29 m from the hub with 11**. Castlemaine's floor did NOT need an exemption (min 4).
### The crowd followed — katoomba's pub, same density/seed/21:00
| | R20 (pre-bias) | **R21 (post-bias)** |
|---|---|---|
| passing crowd (maxActive) | 34 | **66** (2×) |
| patron checks | 226 | **442** (2×) |
| inside frames | 1042 | **1424** |
| tonightRoster | 2 | **3** |
| NaN | 0 | **0** |
The "gig with no passing crowd" observation is retired. (null % stays ~96 % at 21:00 — retail is shut at night
**by design**; that's my own R20 correction, not a leak.)
### Two readings that need care (so nobody mis-reads my own numbers)
- ***fremantle is the weakest pass** (\*): its pub/rsl clear the ≥3 bar but moved **further** from the primary
hub (969→1352 m, 561→1292 m) — A's bias optimises **local cluster adjacency**, and fremantle's venues found
a *secondary* cluster. It satisfies the letter of acceptance and the crowd is healthy in practice (pub:
roster **6**, inside **2741**, maxActive **72**), so I'm **not** calling it a miss — just naming it, since
"3 shops at 1.3 km" is a thinner high street than katoomba's "9 shops at 466 m". A's call if they want it tighter.
- **venue-win % DROPPING is not a regression.** newtown's rsl went 100 %→**21 %**, fremantle's pub 100 %→62 %.
That metric asks "when a check finds a shop, is it the venue?" — it was only ever 100 % because the venue
was *alone*. Post-bias the venue has real neighbours competing for finds, while total crowd went **up**
(newtown rsl: roster 3, inside 1873, maxActive 55). Isolation flatters that number; ignore it post-bias.
### Handshakes
- **D → F (gate):** relocation verify **GREEN**. All five towns pass A's acceptance, the pub finding is closed,
0 NaN at every venue, rosters populate. No D-side gate concern for `v4.0-beta`.
- **FYI F:** `selfcheck` scans **every** `web/assets/towns/*.json` on disk, including E's *untracked* pack WIP.
I saw it transiently RED mid-round (`newcastle_real`: no open-late shop) purely from E's in-flight files, then
green again minutes later at 154141 checks. If you gate while E is mid-fetch you may catch a false red —
E's pack is non-gating, so check whether a failure is a pack town before believing it.
- **Still filed for v4.x (agreed, not a mid-beta change):** `GIG_RANGE` is a 34 m radius but `_nearestOpenShop`
searches only the ped's own 64 m chunk → 8.7 % of in-range peds are chunk-blind. Fix = chunk + 8 neighbours.
- **Unowned from R20:** the *main-street* relocation half (heroes 019 % of the densest cluster; castlemaine's
main street has zero secondhand shops). E's R20 SUBTLE guardrails (texture capped at 3× heroes) address the
ratio town-wide; whether the **hero strip is again the densest cluster** is unverified. Not in my R21 ledger —
flagging it so it doesn't get lost at the epoch close.
---
## ROUND 20 — v4.0-beta THE FIVE TOWNS: citizens at density (ledger #7)
*PROCITY-D, 2026-07-16. Part 1 of 2: the **pre-density baseline** — the gig crowd's behaviour on all five

View File

@ -1,5 +1,55 @@
# LANE E — cross-lane notes
## Round 21 — the v4.0 town pack (pull-forward, DATA-ONLY) ⟨v4.0⟩
> Ledger #5**NON-GATING**: nothing here touches a golden until A absorbs in R22, and F tags
> `v4.0-beta` with or without it. **The pack: 22 towns · 1192 shops · 298 heroes · all 8 states/
> territories.** selfcheck **ALL GREEN 154141/154141**, synthetic `0x3fa36874` unmoved, all 22
> byte-identical on re-run. → **Lane A (R22): 34 goldens await your pin** (17 new towns × base+gig).
**Curation.** Picked on the instincts the first five earned: **secondhand density first** (the heroes
are the game — a town with no op shops isn't a PROCITY town), a walkable centre inside a 2.03.4 km
bbox (the mega-strip law), and a national spread. 18 candidates proposed, 17 survived.
| tier | towns (heroes/shops) |
|---|---|
| meccas | **fitzroy 40/160** · adelaide 29/116 · brunswick 24/96 · katoomba 20/80 · hobart 20/80 · fremantle 20/80 |
| strong | newtown 18/72 · geelong 17/68 · northbridge 15/60 · glebe 13/52 · westend 11/44 |
| solid | newcastle 9/36 · bendigo 9/36 · launceston 8/32 · daylesford 8/32 · bowral 8/32 · marrickville 7/28 · castlemaine 6/24 |
| thin tail | braddon 5/20 · ballarat 5/20 · toowoomba 3/12 · darwin 3/12 |
**The cap is a curation filter, not just a density knob (the round's nicest finding).** Because texture
is pegged at **3× heroes**, a town without a secondhand strip *cannot* inflate into a retail strip.
**Wollongong** had ~62 real shops but only **1 hero** → capped to 4 → **dropped by the ≥6 floor**. It
curated itself out. John's "subtle" directive is doing quality control for free: a town has to earn its
place with real op shops. The thin tail (toowoomba/darwin, 3 heroes) is the same signal, weaker —
**A/Fable may want to drop them in R22**; I've left them in as honest data rather than pad or hide.
**Newcastle: my centre was wrong, not the town.** The CBD bbox held 2 heroes; Newcastle's real
secondhand strip is **Hamilton / Beaumont St**. Re-centred → **2 → 9 heroes, 8 → 36 shops**.
### 🐛 The bug I shipped in R18 and caught here — stale roads on a re-centre
Re-centring Newcastle refetched the **shops** (my query-comparison caught the bbox change) but
**silently reused the old CBD roads** — `fetch_roads_raw` had **no** query-comparison, only
`fetch_raw` did. Result: Hamilton shops seated against a road graph **2.5 km away** → A's lift
marched the town out with **ZERO shops**, which surfaced as 32 bogus "open-late invariant" failures
(a symptom — the real cause was `shops=0`). Ten other towns lack a video shop and pass fine, which is
what proved it wasn't the open-late rule. **Fixed**: `fetch_roads_raw` now compares its query like the
shops path — the bbox lives in the query, so a re-centre must invalidate **both** snapshots. Newcastle
rebuilt: 34 shops seated, openLate=1. *Lesson: a cache-validity check applied to one of two symmetric
paths is a trap with a fuse on it.*
**Discipline unchanged:** bounded bboxes, raw snapshots committed (shops + roads per town), C's §6
mapping, SUBTLE guardrails (heroes never subsampled, texture 3×, **2392 drops counted**), deterministic
emit, ODbL (`SOURCES.md` + per-cache fields). Overpass: batch 1 died on a fatal 504 after 25 retries
(pack scale genuinely rate-limits) — courtesy sleep raised to 4 s, retry/backoff carried the rest; I
split into two polite batches rather than hammer a public API.
**→ Lane A (R22 absorb):** 17 new towns to pin (34 goldens). Sizes range 12 → 160 shops (fitzroy is
2× katoomba — your capacity/overflow fences get a real load test). **→ Lane B:** `index.json` now has
22 towns; your selector reads it already (thanks — R20 #5 closed). Also: thanks for the selfcheck
`index.json` skip, A — my R20 seam flag landed clean.
## Round 20 — v4.0-beta THE FIVE TOWNS: the density widening ⟨v4-beta⟩
> Ledger #2, E's half — built to **C's LANE_C_PUB §6 table** under **John's SUBTLE directive**

View File

@ -728,3 +728,66 @@ town selector. F ran two things:
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.
---
## 20. Round 20 — v4.0-beta THE FIVE TOWNS (density). **F never ran — the honest record.**
R20 widened the towns (E: katoomba 20→80, five towns to 292 shops, "subtle" enforced by construction),
proved the directive from the crowd side (D's A/B: heroes kept footfall 17→19 while the street got 3.8×
busier), capped posters 438→31 (A), and ruled the tram by shop adjacency (B: the alpha tram fronted **zero
shops on 4 of 5 real towns** — "it really was a highway bus"). Excellent round.
**F did not run, and there was no tag.** Unlike R18 — where F ran the gate and *held* on evidence — R20's F
slot simply never executed. The round also left C's density door-soak undone, B's selector still hardcoding
`hud.js:11` instead of E's index, and D's relocation finding (katoomba's pub 1,000 m from the retail cluster
— a gig with no passing crowd) without an owner. R21 closed all four.
## 21. Round 21 — the v4.0-beta CLOSE. F: the beta gate + the tag (ledger #6).
Waves ran [A, B, E] → [C, D] → [F]. A biased `pickVenues` toward retail-cluster adjacency (D's finding) and
re-pinned once; B derived the selector from E's `index.json`; C soaked the five towns' doors at density; D
verified the relocation (**A's bias PASSES**); E pulled 22 towns / 1192 shops forward as non-gating data.
### The matrix — 10 towns × 7 gates (`--matrix`)
`boot · determ · district · roads · tram · noassets` **green on all ten**. Two budget flags (below).
Selfcheck **154141/154141**, `qa.sh --strict` GREEN.
### Tram (#6c) — B's R20 ruling verified exactly
| town | verdict |
|---|---|
| newtown_real | **runs, 16 stops** (B's phantom-stop fix: was 149) |
| castlemaine_real | runs, 10 stops |
| katoomba / fremantle / bendigo | **fenced** — 3 / 2 / 1 shops fronted, all < the 5-shop floor |
New seam: the shell now exposes `window.PROCITY.tram` — B built `routeInfo` *for F's smoke* but nothing
published it. F owns index.html, so F wired it. The matrix reads `{fenced, stops, shopsFronted}`.
### ⚠ The venue_night re-measure (#6b) — RECORDED, and the premise came out false
The brief expected A's poster cap to close F's R19 `+965`-tri edge. **It did not — it widened:**
| | R19 | R21 |
|---|---|---|
| katoomba_real venue_night | 200,965 (+965, **+0.5%**) | **221,935 (+21,935, +11%)** |
| bendigo_real venue_night | — | 201k (**+0.5%**) |
| fremantle / newtown / castlemaine | — | 184k / 179k / 112k ✓ |
**A's cap worked** (posters 438→111). The cause is the *density widening*: katoomba 19→72 shops + D's 3.8×
busier street more than ate the savings. **Draws are fine everywhere** (151/300 — half budget); this is
tris-only, at the worst night stress view. Not a blocking gate (it rides the opt-in `--matrix` warn), and
the brief's instruction was "record the new number" — recorded. **Filed as R22's first item**, where the
tri-diet backlog (instrument LOD · tram tri diet) already lives. katoomba is the outlier: a 966-edge graph
carrying 72 shops.
### Ruling (#6d) — selector gating: **always in the HUD**, not `?dbg`-gated
THE REAL MAP's product *is* the towns; gating their discovery behind a debug flag would hide the epoch's
headline feature. It's unobtrusive, shows friendly names, and lives in the HUD overlay. **Corollary (F's own
gap):** money shots must hide the HUD — the R19 alpha shot had the selector in-frame because F's harness
screenshotted the full viewport. The beta shot hides it.
### The beta money shot (#6e)
[`docs/shots/v4_beta/fremantle_mainstreet.png`](../shots/v4_beta/fremantle_mainstreet.png) — Fremantle's real
street at golden hour: buildings lining both sides down the corridor, footpaths, a crossing, gum trees,
streetlamps, and a genuinely busy crowd (the density widening, visible). 126 draws / 167k tris, HUD hidden.
Posed by projecting the densest **spatial** shop cluster (10 shops within 60 m) onto its front edge and
standing on the road — per-edge shop counts are ~1 on a real graph, so "densest edge" is the wrong pose
heuristic for real towns.

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 KiB

View File

@ -24,16 +24,46 @@ TOWNS_DIR = os.path.join(ROOT, "web", "assets", "towns")
RAW_DIR = os.path.join(TOWNS_DIR, "_raw")
OVERPASS = "https://overpass-api.de/api/interpreter"
UA = "PROCITY-townscout/0.1 (real-map scout; OpenStreetMap ODbL data)"
COURTESY_SLEEP = 4 # pause between Overpass calls — the standing auth covers the fetches,
# courtesy covers the cadence (R21 pack scale: ~2 calls × ~20 towns)
# Compact real AU towns: center (lat,lon) + query box span (km). `katoomba_real` is the fixture
# comparison (vs the hand-made `katoomba` in osm_fixture.js). Spans kept tight so each is ONE town.
TOWNS = {
# ── the beta five (v4.0-alpha/beta — A has these absorbed + pinned) ─────────────────────────
"katoomba_real": {"town": "Katoomba", "state": "NSW", "center": (-33.7145, 150.3120), "span_km": 3.0},
"newtown_real": {"town": "Newtown", "state": "NSW", "center": (-33.8985, 151.1790), "span_km": 2.6},
"fremantle_real": {"town": "Fremantle", "state": "WA", "center": (-32.0555, 115.7480), "span_km": 2.6},
"bendigo_real": {"town": "Bendigo", "state": "VIC", "center": (-36.7580, 144.2810), "span_km": 3.4},
"castlemaine_real": {"town": "Castlemaine", "state": "VIC", "center": (-37.0640, 144.2170), "span_km": 3.0},
# ── the v4.0 curated pack (ROUND21 ledger #5 — DATA-ONLY; A absorbs + pins in R22) ──────────
# Curated on the instincts the first five earned: pick for real SECONDHAND density (the heroes
# are the game — a town with no op shops isn't a PROCITY town), a walkable centre that fits a
# ~23 km bbox (the mega-strip law), and a national spread. Any town that misses the ≥6-shop
# floor or the 5 km span is dropped by the builder and counted — the pack is what survives.
"glebe_real": {"town": "Glebe", "state": "NSW", "center": (-33.8790, 151.1870), "span_km": 2.2},
"marrickville_real": {"town": "Marrickville", "state": "NSW", "center": (-33.9110, 151.1550), "span_km": 2.4},
# Newcastle: centred on the Hamilton / Beaumont St strip, NOT the CBD — the CBD bbox held only 2
# heroes; Hamilton is where Newcastle's actual secondhand shops are (my first centre missed it).
"newcastle_real": {"town": "Newcastle", "state": "NSW", "center": (-32.9235, 151.7440), "span_km": 2.4},
"wollongong_real": {"town": "Wollongong", "state": "NSW", "center": (-34.4250, 150.8940), "span_km": 2.8},
"bowral_real": {"town": "Bowral", "state": "NSW", "center": (-34.4780, 150.4180), "span_km": 2.2},
"fitzroy_real": {"town": "Fitzroy", "state": "VIC", "center": (-37.7990, 144.9790), "span_km": 2.2},
"brunswick_real": {"town": "Brunswick", "state": "VIC", "center": (-37.7700, 144.9600), "span_km": 2.6},
"ballarat_real": {"town": "Ballarat", "state": "VIC", "center": (-37.5620, 143.8500), "span_km": 3.0},
"daylesford_real": {"town": "Daylesford", "state": "VIC", "center": (-37.3430, 144.1430), "span_km": 2.0},
"geelong_real": {"town": "Geelong", "state": "VIC", "center": (-38.1490, 144.3600), "span_km": 3.0},
"westend_real": {"town": "West End", "state": "QLD", "center": (-27.4830, 153.0100), "span_km": 2.2},
"toowoomba_real": {"town": "Toowoomba", "state": "QLD", "center": (-27.5600, 151.9540), "span_km": 3.0},
"northbridge_real": {"town": "Northbridge", "state": "WA", "center": (-31.9490, 115.8570), "span_km": 2.4},
"adelaide_real": {"town": "Adelaide", "state": "SA", "center": (-34.9240, 138.6050), "span_km": 2.8},
"hobart_real": {"town": "Hobart", "state": "TAS", "center": (-42.8820, 147.3270), "span_km": 2.8},
"launceston_real": {"town": "Launceston", "state": "TAS", "center": (-41.4380, 147.1370), "span_km": 2.6},
"braddon_real": {"town": "Braddon", "state": "ACT", "center": (-35.2740, 149.1330), "span_km": 2.4},
"darwin_real": {"town": "Darwin", "state": "NT", "center": (-12.4630, 130.8420), "span_km": 2.6},
}
# the beta five are already pinned by A; `--pack` builds only the new curated candidates
BETA_FIVE = ("katoomba_real", "newtown_real", "fremantle_real", "bendigo_real", "castlemaine_real")
# ── the class list (v4.0-beta, ROUND20 ledger #2 — C's LANE_C_PUB §6 table, John's SUBTLE directive) ──
# HEROES = the secondhand shops (they ARE the game) — never subsampled. TEXTURE = the everyday
@ -174,25 +204,32 @@ def fetch_raw(key, bb, refetch):
fetched = datetime.date.today().isoformat()
json.dump({"fetchedAt": fetched, "endpoint": OVERPASS, "query": q, "bbox": bb, "elements": els},
open(path, "w"), indent=1)
time.sleep(2) # be a good Overpass citizen between towns
time.sleep(COURTESY_SLEEP) # be a good Overpass citizen between towns
return els, fetched
def fetch_roads_raw(key, bb, refetch):
"""Return the raw OSM highway ways (with geometry) for the town bbox, cached in-repo like the shops."""
"""Raw OSM highway ways (with geometry) for the town bbox, cached in-repo like the shops — and,
like the shops, auto-refetched when the QUERY changes. That symmetry matters: the bbox lives in
the query, so re-centring a town must invalidate BOTH snapshots. (R21: it didn't. Re-centring
Newcastle refetched the shops but silently reused the old CBD roads Hamilton shops seated
against a road graph 2.5 km away, and the town marched out with ZERO shops.)"""
os.makedirs(RAW_DIR, exist_ok=True)
path = os.path.join(RAW_DIR, key + ".roads.overpass.json")
if os.path.exists(path) and not refetch:
return json.load(open(path))["elements"]
q = (f'[out:json][timeout:120];'
f'way["highway"~"^({ROAD_HW})$"]'
f'({bb["minLat"]:.5f},{bb["minLon"]:.5f},{bb["maxLat"]:.5f},{bb["maxLon"]:.5f});'
f'out geom;')
if os.path.exists(path) and not refetch:
w = json.load(open(path))
if w.get("query") == q:
return w["elements"]
print(f" [{key}] roads bbox/query changed → new raw snapshot")
print(f" [{key}] fetching Overpass roads (highway ways, bounded)")
ways = overpass_post(q)
json.dump({"fetchedAt": datetime.date.today().isoformat(), "endpoint": OVERPASS, "query": q,
"bbox": bb, "elements": ways}, open(path, "w"), indent=1)
time.sleep(2)
time.sleep(COURTESY_SLEEP)
return ways
@ -295,7 +332,8 @@ def main():
args = [a for a in sys.argv[1:] if not a.startswith("-")]
refetch = "--refetch" in sys.argv
no_roads = "--no-roads" in sys.argv # build a v1 cache (marched fallback), no road fetch
keys = args or list(TOWNS)
pack = "--pack" in sys.argv # only the NEW curated candidates (the beta five are
keys = args or ([k for k in TOWNS if k not in BETA_FIVE] if pack else list(TOWNS)) # pinned by A)
os.makedirs(TOWNS_DIR, exist_ok=True)
kept, dropped = [], []
for key in keys:

View File

@ -22,6 +22,10 @@ ROOT = pathlib.Path(__file__).resolve().parent.parent.parent
PORT = 8130
HOST = f'http://127.0.0.1:{PORT}'
STREET_DRAWS_MAX, STREET_TRIS_MAX = 300, 200_000
# [R21 ledger #6c] B's R20 tram ruling: on a REAL-ROADS town the tram only runs if its best main chain
# fronts ≥5 shops — otherwise it's "a highway bus" and gets fenced. These two run; the other three are fenced.
TRAM_RUN = {'newtown_real', 'castlemaine_real'}
TRAM_STOPS_SANE = (2, 40) # B fixed the phantom-stop bug en route (Newtown: 149 → 16)
# the matrix: (row-label, boot-query). Synthetic hero seeds + 3 fixtures + E's 5 real AU caches.
MATRIX = (
@ -49,11 +53,13 @@ async () => {
D.shot('venue_night'); // busiest default view: the venue block at night
await new Promise(r => setTimeout(r, 500));
const i = D.info();
const tr = P.tram ? { fenced: !!(P.tram.routeInfo || {}).fenced, stops: P.tram.stops | 0,
shopsFronted: (P.tram.routeInfo || {}).shopsFronted } : null; // [R21] B's fence verdict
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,
mode: rep.mode || (src === 'synthetic' ? 'synthetic' : 'marched'),
edges: (plan.streets.edges || []).length };
edges: (plan.streets.edges || []).length, tram: tr };
}
"""
@ -104,9 +110,20 @@ def run_town(new_page, query, label):
# (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")
# [R21 #6c] tram: B's R20 ruling — a real-roads town runs the tram only if its best main chain fronts
# ≥5 shops; otherwise it's FENCED (empty tram group, 0 stops, no errors). Synthetic/fixtures always run.
t, key = d.get('tram'), (label.split('/', 1)[1] if '/' in label else label)
if is_real and key in TRAM_RUN:
row['tram'] = (bool(t) and not t['fenced'] and TRAM_STOPS_SANE[0] <= t['stops'] <= TRAM_STOPS_SANE[1],
f"run {t['stops']}st" if t else 'absent')
elif is_real:
row['tram'] = (bool(t) and t['fenced'] and t['stops'] == 0,
f"fenced/{t.get('shopsFronted', '?')}sh" if t else 'absent')
else:
row['tram'] = (bool(t) and not t['fenced'], f"run {t['stops']}st" if t else 'absent')
except Exception as e:
row.setdefault('name', '?'); row.setdefault('shops', 0)
for g in ('boot', 'determ', 'budget', 'district', 'roads'):
for g in ('boot', 'determ', 'budget', 'district', 'roads', 'tram'):
row.setdefault(g, (False, str(e)[:24]))
finally:
pg.close()
@ -134,9 +151,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 × 6 gates (incl. the R19 roads dimension) · the v4 real-map scout evidence)")
print(f"\033[1mTOWN-MATRIX SMOKE\033[0m ({len(MATRIX)} towns × 7 gates (roads + tram dimensions) · the v4 real-map scout evidence)")
srv = ensure_server()
GATES = ['boot', 'determ', 'budget', 'district', 'roads', 'noassets']
GATES = ['boot', 'determ', 'budget', 'district', 'roads', 'tram', 'noassets']
rows = []
try:
with sync_playwright() as p:
@ -170,7 +187,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 6 gates.")
print(f"\033[32m● MATRIX GREEN\033[0m — {len(rows)} towns (synthetic + fixtures + real caches) pass all 7 gates.")
sys.exit(0)

View File

@ -17,15 +17,22 @@ the "© OpenStreetMap contributors (ODbL)" credit visible.
## Provenance table
Shop counts are post-widening (v4.0-beta); `index.json` is the machine-readable roster.
**`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`.
| cache | town | source | licence | fetched | shops (heroes+texture) | raw response |
|---|---|---|---|---|---|---|
| `katoomba_real.json` | Katoomba, NSW | OSM Overpass (bounded) | ODbL 1.0 | 2026-07-16 | 80 (20+60) | `_raw/katoomba_real.overpass.json` |
| `newtown_real.json` | Newtown, Sydney NSW | OSM Overpass (bounded) | ODbL 1.0 | 2026-07-16 | 72 (18+54) | `_raw/newtown_real.overpass.json` |
| `fremantle_real.json` | Fremantle, WA | OSM Overpass (bounded) | ODbL 1.0 | 2026-07-16 | 80 (20+60) | `_raw/fremantle_real.overpass.json` |
| `bendigo_real.json` | Bendigo, VIC | OSM Overpass (bounded) | ODbL 1.0 | 2026-07-16 | 36 (9+27) | `_raw/bendigo_real.overpass.json` |
| `castlemaine_real.json` | Castlemaine, VIC | OSM Overpass (bounded) | ODbL 1.0 | 2026-07-16 | 24 (6+18) | `_raw/castlemaine_real.overpass.json` |
**The v4.0 pack (R21): 22 towns · 1192 shops · 298 heroes**, 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 (2) | westend · toowoomba |
| TAS (2) | hobart · launceston |
| SA (1) | adelaide |
| ACT (1) | braddon |
| NT (1) | darwin |
## The density widening (v4.0-beta, ROUND20 ledger #2)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,997 @@
{
"fetchedAt": "2026-07-16",
"endpoint": "https://overpass-api.de/api/interpreter",
"query": "[out:json][timeout:180];(nwr[\"shop\"~\"^(antiques|bag|bakery|books|bookshop|boutique|butcher|charity|cheese|chemist|chocolate|clothes|coffee|confectionery|convenience|cosmetics|dairy|deli|delicatessen|department_store|doityourself|electronics|farm|fashion|florist|furniture|games|garden_centre|general|greengrocer|hardware|homeware|houseware|jewellery|jewelry|kiosk|mobile_phone|music|newsagent|pastry|pawnbroker|perfumery|pharmacy|second_hand|shoes|stationery|supermarket|tea|toys|trade|variety_store|video|video_games|vintage)$\"][\"name\"](-34.48791,150.40598,-34.46809,150.43002);nwr[\"amenity\"~\"^(cafe)$\"][\"name\"](-34.48791,150.40598,-34.46809,150.43002););out center;",
"bbox": {
"minLat": -34.48790990990991,
"minLon": 150.4059784233629,
"maxLat": -34.468090090090094,
"maxLon": 150.4300215766371
},
"elements": [
{
"type": "node",
"id": 2266548319,
"lat": -34.4788824,
"lon": 150.4176876,
"tags": {
"name": "Gumnut Pattiserie",
"opening_hours": "Mo-Su 08:00-16:00",
"shop": "bakery"
}
},
{
"type": "node",
"id": 3894052381,
"lat": -34.4793047,
"lon": 150.4165542,
"tags": {
"brand": "Rivers",
"brand:wikidata": "Q106224813",
"check_date": "2022-07-24",
"level": "0",
"name": "Rivers",
"shop": "clothes"
}
},
{
"type": "node",
"id": 6059394998,
"lat": -34.4804575,
"lon": 150.4184493,
"tags": {
"addr:housenumber": "23",
"addr:postcode": "2576",
"addr:state": "NSW",
"addr:street": "Boolwey Street",
"addr:suburb": "Bowral",
"amenity": "cafe",
"name": "Primary Espresso",
"opening_hours:signed": "no",
"outdoor_seating": "yes"
}
},
{
"type": "node",
"id": 6429549858,
"lat": -34.480173,
"lon": 150.4180428,
"tags": {
"name": "A Touch of Tea",
"opening_hours": "Mo 10:00-17:00; Tu-Fr 09:30-17:00; Sa, Su 10:00-16:00",
"phone": "+61 2 4862 2225",
"shop": "tea",
"website": "https://www.atouchoftea.com.au/"
}
},
{
"type": "node",
"id": 8124047197,
"lat": -34.4799168,
"lon": 150.4175131,
"tags": {
"addr:housenumber": "329-331",
"addr:postcode": "2576",
"addr:state": "NSW",
"addr:street": "Bong Bong Street",
"addr:suburb": "Bowral",
"amenity": "cafe",
"cuisine": "coffee_shop",
"name": "Elephant Boy Cafe",
"outdoor_seating": "no",
"phone": "+61 2 4855 2921"
}
},
{
"type": "node",
"id": 8401209657,
"lat": -34.4817024,
"lon": 150.4167739,
"tags": {
"amenity": "cafe",
"name": "Plantation Cafe"
}
},
{
"type": "node",
"id": 8401238122,
"lat": -34.4817011,
"lon": 150.4165116,
"tags": {
"name": "Dirty Janes",
"shop": "antiques"
}
},
{
"type": "node",
"id": 8401265331,
"lat": -34.4806505,
"lon": 150.4173157,
"tags": {
"name": "Few & Far",
"shop": "furniture"
}
},
{
"type": "node",
"id": 11092600813,
"lat": -34.4765067,
"lon": 150.4186032,
"tags": {
"amenity": "cafe",
"name": "The Mill Cafe"
}
},
{
"type": "node",
"id": 11092600816,
"lat": -34.4765694,
"lon": 150.4195185,
"tags": {
"amenity": "cafe",
"diet:vegetarian": "yes",
"name": "Veggie Nook"
}
},
{
"type": "node",
"id": 11092600817,
"lat": -34.4765481,
"lon": 150.4193988,
"tags": {
"name": "Father Chris Riley Op Shop",
"shop": "second_hand"
}
},
{
"type": "node",
"id": 11092617604,
"lat": -34.4774915,
"lon": 150.4183821,
"tags": {
"amenity": "cafe",
"name": "RAW & WILD Market & Cafe"
}
},
{
"type": "node",
"id": 11092652175,
"lat": -34.4787876,
"lon": 150.4188276,
"tags": {
"amenity": "cafe",
"name": "Kookabar Cafe"
}
},
{
"type": "node",
"id": 11092652176,
"lat": -34.4787705,
"lon": 150.4186714,
"tags": {
"name": "Blooms of Bowral",
"shop": "florist"
}
},
{
"type": "node",
"id": 11092691609,
"lat": -34.4777358,
"lon": 150.4196083,
"tags": {
"amenity": "cafe",
"cuisine": "bubble_tea",
"name": "Dream Tea"
}
},
{
"type": "node",
"id": 11092691651,
"lat": -34.4785378,
"lon": 150.4171278,
"tags": {
"brand": "Witchery",
"brand:wikidata": "Q8027909",
"name": "Witchery",
"opening_hours": "Mo-Sa 09:00-17:30; Su 10:00-16:00",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092691652,
"lat": -34.4784091,
"lon": 150.4172286,
"tags": {
"name": "CBD",
"shop": "chemist"
}
},
{
"type": "node",
"id": 11092691715,
"lat": -34.4782042,
"lon": 150.4181805,
"tags": {
"name": "Claytons Pharmacy",
"shop": "chemist"
}
},
{
"type": "node",
"id": 11092691716,
"lat": -34.4782732,
"lon": 150.41817,
"tags": {
"name": "Country Accent",
"shop": "houseware"
}
},
{
"type": "node",
"id": 11092691717,
"lat": -34.4783967,
"lon": 150.4181235,
"tags": {
"name": "Micmac Boutique",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092691718,
"lat": -34.4784631,
"lon": 150.4181123,
"tags": {
"name": "Barbara's Storehouse",
"shop": "houseware"
}
},
{
"type": "node",
"id": 11092691719,
"lat": -34.4785137,
"lon": 150.4181046,
"tags": {
"name": "Red Cross Shop",
"shop": "charity"
}
},
{
"type": "node",
"id": 11092691721,
"lat": -34.4786762,
"lon": 150.4180732,
"tags": {
"name": "Nina Leons Shoe Boutique",
"shop": "shoes"
}
},
{
"type": "node",
"id": 11092691722,
"lat": -34.4786953,
"lon": 150.4182012,
"tags": {
"amenity": "cafe",
"name": "Janek's Cafe"
}
},
{
"type": "node",
"id": 11092691723,
"lat": -34.4787149,
"lon": 150.4183989,
"tags": {
"amenity": "cafe",
"name": "U Jelly Cafe"
}
},
{
"type": "node",
"id": 11092759409,
"lat": -34.4796304,
"lon": 150.4183449,
"tags": {
"name": "Maugers Meats",
"shop": "butcher"
}
},
{
"type": "node",
"id": 11092759411,
"lat": -34.4798395,
"lon": 150.418641,
"tags": {
"addr:suburb": "Bowral",
"amenity": "cafe",
"name": "Oliver Brown"
}
},
{
"type": "node",
"id": 11092759419,
"lat": -34.4796621,
"lon": 150.4178675,
"tags": {
"amenity": "cafe",
"name": "Bendooley Estate Larder"
}
},
{
"type": "node",
"id": 11092759422,
"lat": -34.4794614,
"lon": 150.4182684,
"tags": {
"amenity": "cafe",
"name": "The Hungry Monkey"
}
},
{
"type": "node",
"id": 11092759423,
"lat": -34.4794174,
"lon": 150.4185675,
"tags": {
"name": "Gypsy Road",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092759425,
"lat": -34.4794085,
"lon": 150.4180119,
"tags": {
"name": "Cheese etc.",
"shop": "cheese"
}
},
{
"type": "node",
"id": 11092759426,
"lat": -34.4792776,
"lon": 150.4179489,
"tags": {
"name": "Fella Hamilton",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092759427,
"lat": -34.4791992,
"lon": 150.4180708,
"tags": {
"amenity": "cafe",
"name": "4 Brothers Cafe"
}
},
{
"type": "node",
"id": 11092759428,
"lat": -34.4790383,
"lon": 150.4180036,
"tags": {
"name": "Capital Chemist",
"shop": "chemist"
}
},
{
"type": "node",
"id": 11092759429,
"lat": -34.478956,
"lon": 150.418012,
"tags": {
"brand": "Peter Alexander",
"brand:wikidata": "Q118383240",
"name": "Peter Alexander",
"opening_hours": "Mo-Fr 09:00-17:30; Sa 09:00-17:00; Su 10:00-17:00",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092759430,
"lat": -34.4798147,
"lon": 150.4178444,
"tags": {
"brand": "Bed Bath N' Table",
"brand:wikidata": "Q118551276",
"name": "Bed Bath N' Table",
"shop": "houseware"
}
},
{
"type": "node",
"id": 11092759431,
"lat": -34.4799401,
"lon": 150.4178181,
"tags": {
"name": "Cookshop Plus",
"shop": "houseware"
}
},
{
"type": "node",
"id": 11092759432,
"lat": -34.4801333,
"lon": 150.4178137,
"tags": {
"name": "The Countryman",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092759436,
"lat": -34.4801785,
"lon": 150.4181519,
"tags": {
"name": "The Creative Kid",
"shop": "toys"
}
},
{
"type": "node",
"id": 11092779693,
"lat": -34.4788957,
"lon": 150.4169921,
"tags": {
"brand": "Country Road",
"brand:wikidata": "Q2998907",
"name": "Country Road",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092779694,
"lat": -34.4788636,
"lon": 150.4175335,
"tags": {
"name": "Sonoma Bakery",
"shop": "bakery"
}
},
{
"type": "node",
"id": 11092779696,
"lat": -34.4791429,
"lon": 150.4176411,
"tags": {
"name": "GAZMAN Bowral",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092779697,
"lat": -34.4792069,
"lon": 150.4176258,
"tags": {
"brand": "Cotton On",
"brand:wikidata": "Q5175717",
"name": "Cotton On",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092779698,
"lat": -34.479356,
"lon": 150.4175864,
"tags": {
"name": "The Bookshop Bowral",
"shop": "books"
}
},
{
"type": "node",
"id": 11092779699,
"lat": -34.4794283,
"lon": 150.4175668,
"tags": {
"brand": "Newspower",
"brand:wikidata": "Q120670137",
"name": "Newspower",
"shop": "newsagent"
}
},
{
"type": "node",
"id": 11092799326,
"lat": -34.4796067,
"lon": 150.4159517,
"tags": {
"name": "The Modern Furniture Store",
"shop": "furniture"
}
},
{
"type": "node",
"id": 11092829251,
"lat": -34.4802472,
"lon": 150.4167419,
"tags": {
"brand": "Bing Lee",
"brand:wikidata": "Q4914136",
"name": "Bing Lee",
"shop": "electronics"
}
},
{
"type": "node",
"id": 11092829257,
"lat": -34.4803341,
"lon": 150.4173679,
"tags": {
"name": "Black Pepper",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829258,
"lat": -34.4805497,
"lon": 150.4173502,
"tags": {
"name": "Eastern Living For Home & Giving",
"shop": "furniture"
}
},
{
"type": "node",
"id": 11092829259,
"lat": -34.4807264,
"lon": 150.4173034,
"tags": {
"brand": "Millers",
"brand:wikidata": "Q120644857",
"clothes": "women",
"name": "Millers",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829262,
"lat": -34.4808506,
"lon": 150.4172832,
"tags": {
"clothes": "children",
"name": "Big Little Ones",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829271,
"lat": -34.4815025,
"lon": 150.41698,
"tags": {
"clothes": "women",
"name": "Sandy Short Style",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829272,
"lat": -34.4817328,
"lon": 150.4165819,
"tags": {
"amenity": "cafe",
"name": "Salters at Dirty Janes"
}
},
{
"type": "node",
"id": 11092829276,
"lat": -34.4803757,
"lon": 150.4177143,
"tags": {
"brand": "Rodd & Gunn",
"brand:wikidata": "Q85797658",
"clothes": "men",
"name": "Rodd & Gunn",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829277,
"lat": -34.480468,
"lon": 150.4176974,
"tags": {
"clothes": "oversize",
"name": "Taking Shape",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829278,
"lat": -34.4805736,
"lon": 150.4176578,
"tags": {
"clothes": "women",
"name": "Nu Mode Boutique",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829279,
"lat": -34.4806219,
"lon": 150.417643,
"tags": {
"clothes": "oversize",
"name": "Swish",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829280,
"lat": -34.4806825,
"lon": 150.4176319,
"tags": {
"amenity": "cafe",
"name": "Allumer Coffee & Eatery"
}
},
{
"type": "node",
"id": 11092829281,
"lat": -34.480781,
"lon": 150.4176118,
"tags": {
"clothes": "men",
"name": "Valentino's for Men",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092829283,
"lat": -34.4804466,
"lon": 150.4183837,
"tags": {
"name": "Hem Store",
"shop": "clothes"
}
},
{
"type": "node",
"id": 11092868574,
"lat": -34.4822464,
"lon": 150.417451,
"tags": {
"branch": "Op Shop",
"brand": "The Salvation Army",
"brand:wikidata": "Q188307",
"name": "The Salvation Army",
"shop": "charity"
}
},
{
"type": "node",
"id": 11092868575,
"lat": -34.4828025,
"lon": 150.4176862,
"tags": {
"name": "RUSH Roasting Co",
"shop": "coffee"
}
},
{
"type": "node",
"id": 11092869107,
"lat": -34.4817501,
"lon": 150.4170822,
"tags": {
"amenity": "cafe",
"indoor_seating": "yes",
"name": "The Press Shop",
"outdoor_seating": "yes",
"outdoor_seating:comfort": "chair"
}
},
{
"type": "node",
"id": 11092869109,
"lat": -34.4819598,
"lon": 150.4170417,
"tags": {
"name": "Coast to Country Custom Furniture",
"shop": "furniture"
}
},
{
"type": "node",
"id": 11092869129,
"lat": -34.4814826,
"lon": 150.4150875,
"tags": {
"name": "Save the Children Op Shop",
"shop": "second_hand"
}
},
{
"type": "node",
"id": 11092869158,
"lat": -34.4827728,
"lon": 150.414023,
"tags": {
"name": "Hot Canary Gourmet Meats",
"shop": "butcher"
}
},
{
"type": "node",
"id": 11093033749,
"lat": -34.4837853,
"lon": 150.4139074,
"tags": {
"brand": "Harris Market Farms",
"brand:wikidata": "Q5664888",
"name": "Harris Farm Markets",
"shop": "supermarket"
}
},
{
"type": "node",
"id": 11093045808,
"lat": -34.4833228,
"lon": 150.4150482,
"tags": {
"name": "Highlands Oriental Grocer",
"shop": "convenience"
}
},
{
"type": "node",
"id": 11093045810,
"lat": -34.4830149,
"lon": 150.4153113,
"tags": {
"name": "The Organic Store",
"organic": "only",
"shop": "supermarket"
}
},
{
"type": "way",
"id": 35832271,
"center": {
"lat": -34.479945,
"lon": 150.4194816
},
"nodes": [
418944976,
5680614660,
4388496990,
4388496984,
4388496992,
5680614659,
5680614658,
5680614657,
5680614656,
418944977,
418944978,
418944979,
5680614661,
418944976
],
"tags": {
"addr:housenumber": "33",
"addr:street": "Bendooley Street",
"brand": "Coles",
"brand:wikidata": "Q1108172",
"brand:wikipedia": "en:Coles Supermarkets",
"building": "yes",
"name": "Coles",
"shop": "supermarket",
"website": "https://www.coles.com.au/",
"wheelchair": "yes"
}
},
{
"type": "way",
"id": 36203288,
"center": {
"lat": -34.4821018,
"lon": 150.4157839
},
"nodes": [
422632893,
422632896,
11092869124,
422632898,
422632900,
422632902,
4388494825,
4388494828,
422632906,
422632893
],
"tags": {
"addr:housenumber": "9-15",
"addr:postcode": "2576",
"addr:state": "NSW",
"addr:street": "Banyette Street",
"addr:suburb": "Bowral",
"brand": "ALDI",
"brand:wikidata": "Q41171672",
"brand:wikipedia": "en:Aldi",
"building": "yes",
"check_date:opening_hours": "2023-05-05",
"full_name": "ALDI Bowral",
"name": "ALDI",
"opening_hours": "Mo-Su 08:30-19:00",
"shop": "supermarket",
"website": "https://store.aldi.com.au/nsw/bowral/9-15-banyette-street",
"wheelchair": "yes"
}
},
{
"type": "way",
"id": 441086078,
"center": {
"lat": -34.4812682,
"lon": 150.4179674
},
"nodes": [
4388494273,
5681146624,
4388494272,
4388494494,
5683435029,
5683435028,
4388494275,
4388494509,
4388494492,
4388494284,
4388494502,
4388494278,
5680614654,
5680614655,
4388494281,
4388494273
],
"tags": {
"addr:housenumber": "380",
"addr:postcode": "2576",
"addr:state": "NSW",
"addr:street": "Bong Bong Street",
"addr:suburb": "Bowral",
"brand": "Woolworths",
"brand:wikidata": "Q3249145",
"brand:wikipedia": "en:Woolworths Supermarkets",
"building": "retail",
"name": "Woolworths",
"opening_hours": "Mo-Su 07:00-22:00",
"operator": "Woolworths Group",
"operator:wikidata": "Q607272",
"shop": "supermarket",
"source:addr": "LPI Base Map June 2018",
"website": "https://www.woolworths.com.au/"
}
},
{
"type": "way",
"id": 441086128,
"center": {
"lat": -34.481161,
"lon": 150.4155058
},
"nodes": [
4388490741,
4388490737,
4388490746,
4388490739,
4388490741
],
"tags": {
"brand": "EG Australia",
"brand:wikidata": "Q5023980",
"brand:wikipedia": "en:Caltex Woolworths",
"building": "yes",
"name": "EG Australia",
"shop": "convenience"
}
},
{
"type": "way",
"id": 596317973,
"center": {
"lat": -34.4826845,
"lon": 150.4174704
},
"nodes": [
5681147074,
5681147073,
5681147072,
5681147071,
5681147070,
5681147069,
5681147068,
5681147067,
5681147075,
5681147074
],
"tags": {
"brand": "Reddy Express",
"brand:wikidata": "Q5144653",
"building": "yes",
"building:levels": "1",
"name": "Reddy Express",
"shop": "convenience",
"source:building": "LPI Imagery June 2018",
"website": "www.reddyexpress.com.au"
}
},
{
"type": "way",
"id": 596394804,
"center": {
"lat": -34.4773261,
"lon": 150.4184999
},
"nodes": [
5681563452,
5681563449,
5681563444,
5681563448,
5681563451,
5681563452
],
"tags": {
"addr:housenumber": "246-248",
"addr:street": "Bong Bong Street",
"brand": "Vinnies",
"brand:wikidata": "Q120646672",
"building": "yes",
"name": "Vinnies",
"opening_hours": "Mo-Fr 09:00-15:30; Sa 09:00-12:00",
"shop": "charity",
"source:addr": "LPI Base Map June 2018",
"source:building": "LPI Imagery June 2018"
}
},
{
"type": "way",
"id": 596689907,
"center": {
"lat": -34.4798956,
"lon": 150.4169774
},
"nodes": [
5683584059,
5683584056,
5683584055,
5681563688,
5683584051,
5683584053,
11092799316,
5683584060,
5683584059
],
"tags": {
"addr:postcode": "2576",
"addr:state": "NSW",
"addr:street": "Boolwey Street",
"addr:suburb": "Bowral",
"brand": "Kmart",
"brand:wikidata": "Q6421682",
"brand:wikipedia": "en:Kmart Australia",
"building": "yes",
"name": "K Hub",
"shop": "department_store",
"source:geometry": "LPI Base Map June 2018"
}
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,623 @@
{
"fetchedAt": "2026-07-16",
"endpoint": "https://overpass-api.de/api/interpreter",
"query": "[out:json][timeout:180];(nwr[\"shop\"~\"^(antiques|bag|bakery|books|bookshop|boutique|butcher|charity|cheese|chemist|chocolate|clothes|coffee|confectionery|convenience|cosmetics|dairy|deli|delicatessen|department_store|doityourself|electronics|farm|fashion|florist|furniture|games|garden_centre|general|greengrocer|hardware|homeware|houseware|jewellery|jewelry|kiosk|mobile_phone|music|newsagent|pastry|pawnbroker|perfumery|pharmacy|second_hand|shoes|stationery|supermarket|tea|toys|trade|variety_store|video|video_games|vintage)$\"][\"name\"](-12.47471,130.83001,-12.45129,130.85399);nwr[\"amenity\"~\"^(cafe)$\"][\"name\"](-12.47471,130.83001,-12.45129,130.85399););out center;",
"bbox": {
"minLat": -12.474711711711711,
"minLon": 130.83000564827645,
"maxLat": -12.451288288288287,
"maxLon": 130.85399435172357
},
"elements": [
{
"type": "node",
"id": 1768235556,
"lat": -12.4641113,
"lon": 130.8429234,
"tags": {
"check_date:opening_hours": "2025-10-18",
"name": "Life n Style Darwin",
"opening_hours:signed": "no",
"shop": "houseware",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 2478924751,
"lat": -12.4637037,
"lon": 130.8395775,
"tags": {
"brand": "Coles",
"brand:wikidata": "Q1108172",
"brand:wikipedia": "en:Coles Supermarkets",
"name": "Coles",
"operator": "Coles Group",
"operator:wikidata": "Q131937428",
"shop": "supermarket",
"website": "https://www.coles.com.au/"
}
},
{
"type": "node",
"id": 3230870934,
"lat": -12.4633733,
"lon": 130.8399384,
"tags": {
"addr:country": "AU",
"addr:state": "NT",
"amenity": "cafe",
"brand": "The Coffee Club",
"brand:wikidata": "Q7726599",
"brand:wikipedia": "en:The Coffee Club",
"cuisine": "coffee_shop",
"name": "The Coffee Club",
"takeaway": "yes",
"website": "https://www.coffeeclub.com.au/"
}
},
{
"type": "node",
"id": 3230979991,
"lat": -12.4633514,
"lon": 130.8421418,
"tags": {
"name": "Just Looking",
"opening_hours": "Mo-Fr 09:30-17:00; Sa 09:00-15:00; Su 10:30-14:00",
"shop": "clothes",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3230979994,
"lat": -12.4639637,
"lon": 130.84276,
"tags": {
"check_date:opening_hours": "2025-10-18",
"name": "Hoskings Jewellers",
"opening_hours:signed": "no",
"phone": "+61 8 8981 8895",
"shop": "jewelry",
"website": "https://hoskings.com.au/",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3230979997,
"lat": -12.463738,
"lon": 130.8422598,
"tags": {
"brand": "Just Jeans",
"brand:wikidata": "Q6316068",
"brand:wikipedia": "en:Just Group",
"check_date:opening_hours": "2025-10-18",
"clothes": "denim",
"name": "Just Jeans",
"opening_hours:signed": "no",
"shop": "clothes",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3230980001,
"lat": -12.4646064,
"lon": 130.8431144,
"tags": {
"addr:housenumber": "19",
"addr:street": "Smith Street Mall",
"addr:unit": "SHOP M13/S1",
"brand": "R.M.Williams",
"brand:wikidata": "Q65042966",
"name": "R.M.Williams",
"opening_hours": "Mo-Fr 09:00-17:00; Sa 09:00-16:00; Su 10:00-15:00",
"shop": "shoes"
}
},
{
"type": "node",
"id": 3230980007,
"lat": -12.4634366,
"lon": 130.8422329,
"tags": {
"brand": "Cotton On",
"brand:wikidata": "Q5175717",
"brand:wikipedia": "en:Cotton On Group",
"check_date:opening_hours": "2025-10-18",
"name": "Cotton On",
"opening_hours:signed": "no",
"shop": "clothes",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3230980010,
"lat": -12.4637346,
"lon": 130.8425718,
"tags": {
"name": "Off Ya Tree",
"opening_hours": "Mo-Fr 09:00-18:00; Sa 09:00-17:00; Su 10:00-15:00",
"shop": "clothes",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3231017952,
"lat": -12.4642257,
"lon": 130.8430444,
"tags": {
"check_date:opening_hours": "2025-10-18",
"name": "Mr Convenient",
"opening_hours:signed": "no",
"shop": "convenience",
"wheelchair": "no"
}
},
{
"type": "node",
"id": 3231017957,
"lat": -12.4643515,
"lon": 130.8428874,
"tags": {
"name": "Infidelity",
"shop": "clothes"
}
},
{
"type": "node",
"id": 3231022466,
"lat": -12.4642601,
"lon": 130.8430709,
"tags": {
"name": "The Bookshop",
"opening_hours": "Mo-Fr 09:00-17:00; Sa 09:00-15:00; Su 10:00-14:00",
"phone": "+61 8 8941 3489",
"shop": "books",
"website": "https://www.bookshopdarwin.com.au/",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3759068231,
"lat": -12.4605581,
"lon": 130.8405146,
"tags": {
"brand": "Woolworths",
"brand:wikidata": "Q3249145",
"brand:wikipedia": "en:Woolworths Supermarkets",
"check_date:opening_hours": "2025-06-18",
"name": "Woolworths",
"opening_hours": "06:00-22:00",
"operator": "Woolworths Group",
"operator:wikidata": "Q607272",
"shop": "supermarket",
"source": "company website",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 3796152681,
"lat": -12.4636413,
"lon": 130.8402074,
"tags": {
"amenity": "cafe",
"brand": "Boost Juice",
"brand:wikidata": "Q4943789",
"cuisine": "juice",
"name": "Boost Juice",
"phone": "+61 8 8981 5555",
"source": "http://mitchellcentre.com.au/centre-directory.html",
"takeaway": "yes",
"website": "https://www.boostjuice.com.au/"
}
},
{
"type": "node",
"id": 3796152682,
"lat": -12.4637489,
"lon": 130.8398288,
"tags": {
"name": "Bright Eyes",
"shop": "clothes",
"source": "http://mitchellcentre.com.au/centre-directory.html",
"website": "https://www.brighteyes.com.au/"
}
},
{
"type": "node",
"id": 3796152687,
"lat": -12.4640134,
"lon": 130.8401154,
"tags": {
"brand": "Optus",
"brand:wikidata": "Q865038",
"brand:wikipedia": "en:Optus",
"name": "Optus",
"shop": "mobile_phone",
"source": "http://mitchellcentre.com.au/centre-directory.html"
}
},
{
"type": "node",
"id": 3796152690,
"lat": -12.4638132,
"lon": 130.8403882,
"tags": {
"brand": "Telstra",
"brand:wikidata": "Q721162",
"brand:wikipedia": "en:Telstra",
"name": "Telstra",
"shop": "mobile_phone",
"source": "http://mitchellcentre.com.au/centre-directory.html"
}
},
{
"type": "node",
"id": 3796202328,
"lat": -12.4637271,
"lon": 130.8401991,
"tags": {
"contact:facebook": "https://www.facebook.com/attitudeX/",
"name": "Attitude X",
"shop": "clothes",
"source": "http://mitchellcentre.com.au/centre-directory.html"
}
},
{
"type": "node",
"id": 3796202355,
"lat": -12.4637649,
"lon": 130.8402521,
"tags": {
"brand": "Strandbags",
"brand:wikidata": "Q111946652",
"name": "Strandbags",
"shop": "bag",
"source": "http://mitchellcentre.com.au/centre-directory.html",
"website": "https://www.strandbags.com.au/"
}
},
{
"type": "node",
"id": 4223293611,
"lat": -12.461599,
"lon": 130.8419672,
"tags": {
"addr:housenumber": "35",
"addr:street": "Cavenagh Street",
"addr:unit": "1",
"amenity": "cafe",
"cuisine": "bakery;cake;coffee;meat_pies",
"name": "Kurt's Cakes",
"phone": "+61 8 8941 5033"
}
},
{
"type": "node",
"id": 4959162299,
"lat": -12.4574764,
"lon": 130.8355439,
"tags": {
"addr:housenumber": "109",
"addr:street": "Smith Street",
"amenity": "cafe",
"name": "Cafe 21 Smith",
"opening_hours": "Mo-Fr 07:00-16:00; Sa,Su 07:00-13:00",
"phone": "+61 8 7917 8703",
"website": "https://www.cafe21.com.au/index.php?route=information/information&information_id=8"
}
},
{
"type": "node",
"id": 4959816482,
"lat": -12.4567297,
"lon": 130.8359701,
"tags": {
"addr:housenumber": "2",
"addr:postcode": "0800",
"addr:state": "NT",
"addr:street": "Harriet Place",
"addr:unit": "1",
"amenity": "cafe",
"cuisine": "coffee_shop",
"name": "Kopi Stop",
"phone": "+61 8 8941 2414"
}
},
{
"type": "node",
"id": 5555831147,
"lat": -12.4638312,
"lon": 130.8432441,
"tags": {
"addr:housenumber": "32",
"addr:street": "Smith Street Mall",
"addr:unit": "8A Star Village",
"name": "CoinBear Collectables",
"shop": "antiques"
}
},
{
"type": "node",
"id": 5623298221,
"lat": -12.4650961,
"lon": 130.8428893,
"tags": {
"addr:housenumber": "Shop 4-5",
"addr:street": "Smith Street Mall",
"amenity": "cafe",
"description": "A 100% not-for-profit organisation committed to selling ethically sourced and sustainable products that directly support local Indigenous communities.",
"name": "Aboriginal Bush Traders",
"name:en": "Aboriginal Bush Traders",
"outdoor_seating": "yes",
"phone": "+61 8 8931 6650",
"shop": "art",
"website": "https://aboriginalbushtraders.com/"
}
},
{
"type": "node",
"id": 5742355123,
"lat": -12.4670209,
"lon": 130.846334,
"tags": {
"addr:country": "AU",
"addr:state": "NT",
"amenity": "cafe",
"brand": "The Coffee Club",
"brand:wikidata": "Q7726599",
"brand:wikipedia": "en:The Coffee Club",
"cuisine": "coffee_shop",
"internet_access": "wlan",
"level": "0",
"name": "The Coffee Club",
"takeaway": "yes",
"website": "https://www.coffeeclub.com.au/"
}
},
{
"type": "node",
"id": 5742771761,
"lat": -12.4643302,
"lon": 130.8431412,
"tags": {
"addr:housenumber": "28",
"addr:street": "Smith Street Mall",
"air_conditioning": "yes",
"amenity": "cafe",
"check_date:opening_hours": "2025-10-18",
"cuisine": "coffee;breakfast;waffle;lunch;sandwich",
"name": "Caf\u00e9 Twenty One",
"opening_hours:signed": "no",
"phone": "+61 8 7917 8703",
"smoking": "no",
"website": "https://www.cafe21.com.au/",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 5744907175,
"lat": -12.4621411,
"lon": 130.8423045,
"tags": {
"addr:housenumber": "37",
"addr:street": "Knuckey Street",
"air_conditioning": "yes",
"amenity": "cafe",
"changing_table": "yes",
"email": "gertrude@moorishcafe.com.au",
"indoor_seating": "yes",
"name": "Moorish Cafe",
"opening_hours": "Tu-Fr 11:00-14:30,18:00-22:00; Sa 11:00-22:00",
"outdoor_seating": "no",
"payment:credit_cards": "yes",
"payment:debit_cards": "yes",
"phone": "+61 8 8981 0010",
"website": "https://www.moorishcafe.com.au/"
}
},
{
"type": "node",
"id": 7081158586,
"lat": -12.4618269,
"lon": 130.8416055,
"tags": {
"amenity": "cafe",
"cuisine": "bagel",
"diet:vegan": "yes",
"name": "Mad Snake"
}
},
{
"type": "node",
"id": 9553841165,
"lat": -12.4631496,
"lon": 130.8420973,
"tags": {
"air_conditioning": "yes",
"amenity": "cafe",
"cuisine": "coffee_shop",
"name": "The Rabbit Hole",
"opening_hours": "Mo-Fr 07:00-15:00; Sa,Su 08:00-14:00",
"smoking": "no",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 10958632095,
"lat": -12.4643252,
"lon": 130.8426431,
"tags": {
"amenity": "cafe",
"name": "Pokelicious"
}
},
{
"type": "node",
"id": 10958836833,
"lat": -12.4644685,
"lon": 130.8423883,
"tags": {
"amenity": "cafe",
"cuisine": "juice",
"name": "Fruillati"
}
},
{
"type": "node",
"id": 11895994369,
"lat": -12.4608319,
"lon": 130.8416269,
"tags": {
"addr:housenumber": "48",
"addr:postcode": "0800",
"addr:street": "Cavenagh Street",
"amenity": "pharmacy",
"branch": "GPO",
"brand": "Chemist Warehouse",
"brand:wikidata": "Q48782120",
"healthcare": "pharmacy",
"name": "Chemist Warehouse",
"name:en": "Chemist Warehouse Darwin GPO",
"opening_hours": "Mo-Fr 08:00-20:00; Sa-Su 08:30-17:00",
"phone": "+61 8 8981 9202",
"shop": "chemist",
"website": "https://www.chemistwarehouse.com.au/"
}
},
{
"type": "node",
"id": 11896000469,
"lat": -12.4610643,
"lon": 130.8418065,
"tags": {
"addr:housenumber": "48",
"addr:postcode": "0800",
"addr:street": "Cavenagh Street",
"addr:unit": "5",
"brand": "Vinnies",
"brand:wikidata": "Q120646672",
"name": "Vinnies",
"opening_hours": "Mo-Fr 09:00-17:00; Sa 09:00-16:00; Su closed",
"phone": "+61 8 8941 2849",
"shop": "charity",
"website": "https://www.vinnies.org.au/nt/shops/vinnies-darwin-city"
}
},
{
"type": "node",
"id": 11896004570,
"lat": -12.461172,
"lon": 130.8419583,
"tags": {
"addr:housenumber": "48",
"addr:postcode": "0800",
"addr:street": "Cavenagh Street",
"addr:unit": "9",
"amenity": "cafe",
"check_date:opening_hours": "2025-06-18",
"name": "Alberto's",
"opening_hours": "Mo-Fr 07:00-15:00; Sa 08:00-14:00",
"phone": "+61 426 241 971"
}
},
{
"type": "node",
"id": 11910908823,
"lat": -12.4681147,
"lon": 130.846395,
"tags": {
"addr:housenumber": "7",
"addr:street": "Kitchener Drive",
"addr:unit": "E4",
"name": "Surf Dive 'n Ski - Darwin Waterfront",
"opening_hours": "Mo-Fr 09:00-17:30; Sa 09:00-17:00; Su 10:00-17:00",
"phone": "+61 8 8941 0425",
"shop": "clothes",
"website": "https://sds.com.au/"
}
},
{
"type": "node",
"id": 12069251200,
"lat": -12.4629941,
"lon": 130.8413635,
"tags": {
"name": "Bobar Darwin",
"opening_hours": "Mo-Fr 11:00-18:00; Sa 11:00-17:30; Su 12:00-15:30",
"phone": "+61 2 7978 8669",
"shop": "tea",
"wheelchair": "no"
}
},
{
"type": "node",
"id": 12608531707,
"lat": -12.4607079,
"lon": 130.8405799,
"tags": {
"air_conditioning": "yes",
"amenity": "cafe",
"changing_table": "no",
"check_date:opening_hours": "2025-02-22",
"indoor_seating": "yes",
"name": "Passengers Cafe",
"opening_hours:signed": "no",
"outdoor_seating": "no",
"smoking": "no",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 12608563677,
"lat": -12.4608522,
"lon": 130.8403856,
"tags": {
"name": "Blooms",
"opening_hours": "Mo-Fr 08:00-19:00; Sa,Su 08:00-14:00",
"shop": "chemist",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 13390374346,
"lat": -12.4635109,
"lon": 130.8408988,
"tags": {
"addr:housenumber": "15",
"addr:street": "Knuckey Street",
"amenity": "cafe",
"indoor_seating": "no",
"name": "Bustard Town",
"outdoor_seating": "yes",
"website": "https://bustardtown.com/"
}
},
{
"type": "node",
"id": 13903181001,
"lat": -12.4639071,
"lon": 130.8429999,
"tags": {
"addr:housenumber": "2",
"addr:street": "Star Village",
"amenity": "cafe",
"check_date": "2026-06-02",
"check_date:opening_hours": "2026-06-02",
"cuisine": "breakfast;cake;coffee_shop",
"name": "Four Birds",
"opening_hours": "Mo-Fr 07:00-14:00; Sa 08:00-13:00"
}
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,596 @@
{
"fetchedAt": "2026-07-16",
"endpoint": "https://overpass-api.de/api/interpreter",
"query": "[out:json][timeout:180];(nwr[\"shop\"~\"^(antiques|bag|bakery|books|bookshop|boutique|butcher|charity|cheese|chemist|chocolate|clothes|coffee|confectionery|convenience|cosmetics|dairy|deli|delicatessen|department_store|doityourself|electronics|farm|fashion|florist|furniture|games|garden_centre|general|greengrocer|hardware|homeware|houseware|jewellery|jewelry|kiosk|mobile_phone|music|newsagent|pastry|pawnbroker|perfumery|pharmacy|second_hand|shoes|stationery|supermarket|tea|toys|trade|variety_store|video|video_games|vintage)$\"][\"name\"](-37.35201,144.13167,-37.33399,144.15433);nwr[\"amenity\"~\"^(cafe)$\"][\"name\"](-37.35201,144.13167,-37.33399,144.15433););out center;",
"bbox": {
"minLat": -37.35200900900901,
"minLon": 144.13166817643216,
"maxLat": -37.333990990991,
"maxLon": 144.15433182356784
},
"elements": [
{
"type": "node",
"id": 1013037027,
"lat": -37.3412366,
"lon": 144.1418112,
"tags": {
"amenity": "cafe",
"name": "Harvest Cafe"
}
},
{
"type": "node",
"id": 1240758570,
"lat": -37.3410037,
"lon": 144.1431033,
"tags": {
"addr:housenumber": "1",
"addr:street": "Burke Square",
"brand": "Mitre 10",
"brand:wikidata": "Q6882393",
"brand:wikipedia": "en:Mitre 10",
"name": "Crameri's Mitre 10",
"opening_hours": "Mo-Fr 07:30-17:30; Sa 08:30-15:30; Su 09:00-12:00",
"phone": "+61 3 5348 2316",
"shop": "doityourself",
"website": "https://www.mitre10.com.au/stores/vic/daylesford-crameri-s-mitre-10-853648"
}
},
{
"type": "node",
"id": 1240783219,
"lat": -37.3478628,
"lon": 144.1371111,
"tags": {
"amenity": "cafe",
"check_date": "2025-12-23",
"cuisine": "coffee_shop",
"name": "The Boathouse Cafe",
"website": "http://www.urbanspoon.com/r/346/1493625/restaurant/Victoria/The-Boathouse-Daylesford"
}
},
{
"type": "node",
"id": 1704817248,
"lat": -37.3426634,
"lon": 144.1422838,
"tags": {
"addr:housename": "That Bargain Place",
"addr:housenumber": "68",
"addr:street": "Vincent Street",
"contact:facebook": "https://www.facebook.com/ThatBargainPlaceDaylesford/",
"name": "That Bargain Place",
"shop": "variety_store"
}
},
{
"type": "node",
"id": 4403814794,
"lat": -37.342778,
"lon": 144.1426706,
"tags": {
"amenity": "cafe",
"name": "Larder",
"website": "https://www.larderdaylesford.com.au/"
}
},
{
"type": "node",
"id": 4658624090,
"lat": -37.3417167,
"lon": 144.1320928,
"tags": {
"addr:housenumber": "105",
"addr:street": "Central Springs Road",
"check_date": "2025-12-23",
"name": "The Amazing Mill Markets",
"opening_hours": "Mo-Su 10:00-18:00",
"shop": "antiques",
"tourism": "attraction",
"website": "https://www.millmarkets.com.au/daylesford/"
}
},
{
"type": "node",
"id": 5040169824,
"lat": -37.3434833,
"lon": 144.1491515,
"tags": {
"amenity": "cafe",
"cuisine": "austrian",
"diet:vegan": "yes",
"diet:vegetarian": "yes",
"name": "Wombat Hill House",
"opening_hours": "Fr-Tu 08:00-15:00",
"payment:credit_cards": "yes",
"payment:debit_cards": "yes",
"website": "https://wombathillhouse.com.au"
}
},
{
"type": "node",
"id": 5597847478,
"lat": -37.343045,
"lon": 144.142651,
"tags": {
"addr:housenumber": "73",
"addr:street": "Vincent Street",
"amenity": "cafe",
"name": "Himalaya",
"shop": "bakery",
"website": "https://himalayabakery.com/"
}
},
{
"type": "node",
"id": 6541247183,
"lat": -37.3406205,
"lon": 144.1511771,
"tags": {
"addr:housenumber": "28",
"addr:street": "Raglan Street",
"name": "Wombat Hill Florist",
"shop": "florist",
"website": "https://wombathillflorist.com.au/"
}
},
{
"type": "node",
"id": 7278926266,
"lat": -37.3420268,
"lon": 144.1424152,
"tags": {
"addr:housenumber": "46",
"addr:street": "Vincent Street",
"name": "Paradise Bookshop",
"opening_hours": "Mo-Su 11:00-17:00",
"shop": "books",
"website": "https://paradisebookshop.com.au/"
}
},
{
"type": "node",
"id": 9523030703,
"lat": -37.3400211,
"lon": 144.1451252,
"tags": {
"addr:housenumber": "1",
"addr:postcode": "3460",
"addr:state": "VIC",
"addr:street": "Howe Street",
"addr:suburb": "Daylesford",
"name": "Blake Family Grocers",
"opening_hours": "Mo-Su 08:00-19:00",
"phone": "+61 3 5318 1128",
"shop": "supermarket",
"website": "https://www.blakefamilygrocers.com.au/"
}
},
{
"type": "node",
"id": 10290719910,
"lat": -37.3482099,
"lon": 144.1377154,
"tags": {
"amenity": "cafe",
"cuisine": "coffee_shop;ice_cream;sandwich",
"name": "Walters"
}
},
{
"type": "node",
"id": 12416866197,
"lat": -37.3431995,
"lon": 144.1426217,
"tags": {
"addr:housenumber": "79",
"addr:street": "Vincent Street",
"name": "Creswick Natural Fibres",
"shop": "clothes",
"website": "https://creswickwool.com/pages/daylesford-store"
}
},
{
"type": "node",
"id": 12416866444,
"lat": -37.3420226,
"lon": 144.1428444,
"tags": {
"addr:housenumber": "33",
"addr:street": "Vincent Street",
"contact:facebook": "https://www.facebook.com/people/Mee-at-Daylesford/100039378596498/",
"name": "Mee at Daylesford",
"shop": "jewelry"
}
},
{
"type": "node",
"id": 12416866480,
"lat": -37.3420722,
"lon": 144.142835,
"tags": {
"addr:housenumber": "35",
"addr:street": "Vincent Street",
"name": "The Empress & Wolf",
"shop": "jewelry",
"website": "https://theempressandwolf.com/"
}
},
{
"type": "node",
"id": 12416866585,
"lat": -37.3433921,
"lon": 144.1425853,
"tags": {
"addr:housenumber": "87",
"addr:street": "Vincent Street",
"contact:facebook": "https://www.facebook.com/SweetDecadenceAtLocantro/",
"name": "Sweet Decadence at Locantro",
"shop": "chocolate"
}
},
{
"type": "node",
"id": 12416866829,
"lat": -37.3431372,
"lon": 144.1426335,
"tags": {
"addr:housenumber": "77",
"addr:street": "Vincent Street",
"contact:facebook": "https://www.facebook.com/Enkiorganics/",
"name": "Enki Apothecary & Distillery",
"shop": "cosmetics"
}
},
{
"type": "node",
"id": 12416866831,
"lat": -37.3421224,
"lon": 144.1428255,
"tags": {
"addr:housenumber": "37",
"addr:street": "Vincent Street",
"name": "The Daylesford Meat Co",
"shop": "butcher",
"website": "https://daylesfordmeatco.com.au/"
}
},
{
"type": "node",
"id": 12416866871,
"lat": -37.3418082,
"lon": 144.1428849,
"tags": {
"addr:housenumber": "27",
"addr:street": "Vincent Street",
"addr:unit": "1",
"name": "Manteau Noir",
"shop": "clothes",
"website": "https://manteaunoir.com.au/"
}
},
{
"type": "node",
"id": 12416866919,
"lat": -37.342985,
"lon": 144.1426623,
"tags": {
"addr:housenumber": "69-71",
"addr:street": "Vincent Street",
"contact:facebook": "https://www.facebook.com/daylesfordbakery/",
"name": "Daylesford Bakery",
"shop": "bakery"
}
},
{
"type": "node",
"id": 12416867014,
"lat": -37.3433466,
"lon": 144.1425939,
"tags": {
"addr:housenumber": "83-85",
"addr:street": "Vincent Street",
"name": "Harry and Me",
"shop": "clothes",
"website": "https://harryandme.com.au/"
}
},
{
"type": "node",
"id": 12416867098,
"lat": -37.3417293,
"lon": 144.1430296,
"tags": {
"addr:housenumber": "27",
"addr:street": "Vincent Street",
"addr:unit": "5",
"contact:instagram": "https://www.instagram.com/aroundthecorner_daylesford/",
"name": "Around the Corner",
"shop": "antiques"
}
},
{
"type": "node",
"id": 12420835148,
"lat": -37.3421321,
"lon": 144.1423943,
"tags": {
"addr:housenumber": "50",
"addr:street": "Vincent Street",
"name": "The Magic Pudding Homewares",
"shop": "houseware"
}
},
{
"type": "node",
"id": 12420836576,
"lat": -37.3416484,
"lon": 144.1424901,
"tags": {
"addr:housenumber": "28",
"addr:street": "Vincent Street",
"name": "Frances Pilley",
"shop": "cosmetics",
"website": "https://www.francespilley.com.au/"
}
},
{
"type": "node",
"id": 12420836577,
"lat": -37.3416115,
"lon": 144.1422392,
"tags": {
"addr:housenumber": "22",
"addr:street": "Albert Street",
"contact:facebook": "https://www.facebook.com/people/Albert-Street-Butchery-Daylesford/100057539834248/",
"name": "Albert Street Butchery",
"shop": "butcher"
}
},
{
"type": "node",
"id": 12420836612,
"lat": -37.3404231,
"lon": 144.1452113,
"tags": {
"addr:housenumber": "10-12",
"addr:street": "Howe Street",
"name": "Buster McGee",
"shop": "clothes",
"website": "https://bustermcgee.com.au/"
}
},
{
"type": "node",
"id": 12420836699,
"lat": -37.3424976,
"lon": 144.1423191,
"tags": {
"addr:housenumber": "60",
"addr:street": "Vincent Street",
"name": "Pastry King",
"shop": "bakery"
}
},
{
"type": "node",
"id": 12420836714,
"lat": -37.3407194,
"lon": 144.1516473,
"tags": {
"addr:housenumber": "22",
"addr:street": "Raglan Street",
"amenity": "cafe",
"name": "The Daylesford Hot Chocolate Company",
"website": "https://www.daylesfordhotchocolate.com/"
}
},
{
"type": "node",
"id": 12420836716,
"lat": -37.3410013,
"lon": 144.1440776,
"tags": {
"addr:housenumber": "28",
"addr:street": "Howe Street",
"name": "Vinnies",
"opening_hours": "Mo-Sa 09:00-17:00; Su 10:00-17:00",
"phone": "+61 3 5348 3862",
"shop": "charity",
"website": "https://www.vinnies.org.au/vic/shops/vinnies-daylesford"
}
},
{
"type": "node",
"id": 12420836864,
"lat": -37.3416903,
"lon": 144.1424818,
"tags": {
"addr:housenumber": "30",
"addr:street": "Vincent Street",
"name": "Alpaca Passion",
"shop": "clothes",
"website": "https://www.alpacapassion.com.au/"
}
},
{
"type": "node",
"id": 12420836982,
"lat": -37.342088,
"lon": 144.1424031,
"tags": {
"addr:housenumber": "48",
"addr:street": "Vincent Street",
"name": "The Sew Good Company",
"shop": "clothes",
"website": "https://thesewgoodcompany.org/"
}
},
{
"type": "node",
"id": 12420837016,
"lat": -37.3417585,
"lon": 144.1424683,
"tags": {
"addr:housenumber": "32-34",
"addr:street": "Vincent Street",
"name": "Brick Lane Bazaar",
"shop": "second_hand",
"website": "https://bricklanebazaar.com/"
}
},
{
"type": "node",
"id": 13396672125,
"lat": -37.3418814,
"lon": 144.131898,
"tags": {
"amenity": "cafe",
"name": "The Maze",
"opening_hours": "Mo-Fr 10:00-16:00; Sa-Su 10:00-15:00",
"outdoor_seating": "yes",
"website": "https://www.millmarkets.com.au/cafes/"
}
},
{
"type": "node",
"id": 13588943580,
"lat": -37.3407844,
"lon": 144.1445263,
"tags": {
"addr:housenumber": "22-24",
"addr:street": "Howe Street",
"addr:unit": "1-2",
"name": "Salvos",
"opening_hours": "Mo-Sa 09:00-17:00",
"phone": "+61 3 5348 2720",
"shop": "charity",
"website": "https://www.salvosstores.com.au/stores/vic/3460-daylesford-806"
}
},
{
"type": "node",
"id": 13588943581,
"lat": -37.3409459,
"lon": 144.1441921,
"tags": {
"addr:housenumber": "22-24",
"addr:street": "Howe Street",
"addr:unit": "7",
"name": "Uniting Op Shop",
"opening_hours": "Tu-Su 09:30-17:00; Mo closed",
"phone": "+61 3 9051 2763",
"shop": "charity",
"website": "https://www.unitingvictas.org.au/locations/op-shop-daylesford/"
}
},
{
"type": "node",
"id": 13588956511,
"lat": -37.3419604,
"lon": 144.1424283,
"tags": {
"addr:housenumber": "44",
"addr:street": "Vincent Street",
"contact:facebook": "https://www.facebook.com/dcjdaylesford/",
"name": "Double C Jeanery",
"shop": "clothes"
}
},
{
"type": "node",
"id": 13589251803,
"lat": -37.3417169,
"lon": 144.1429022,
"tags": {
"addr:housenumber": "27",
"addr:street": "Vincent Street",
"addr:unit": "3",
"name": "Artedeco",
"shop": "antiques",
"website": "https://www.artedeco.com.au/"
}
},
{
"type": "node",
"id": 13589288436,
"lat": -37.341318,
"lon": 144.1424316,
"tags": {
"addr:housenumber": "26",
"addr:street": "Vincent Street",
"name": "The Farmer's Wife",
"shop": "clothes",
"website": "https://thefarmerswifestore.com.au/"
}
},
{
"type": "way",
"id": 108219615,
"center": {
"lat": -37.3396039,
"lon": 144.1467323
},
"nodes": [
1241976087,
1241976088,
1241976090,
1241976091,
1241976079,
1241976078,
1241976096,
1241976097,
1241976098,
1241976087
],
"tags": {
"brand": "Reddy Express",
"brand:wikidata": "Q5144653",
"building": "yes",
"name": "Reddy Express",
"shop": "convenience",
"website": "www.reddyexpress.com.au"
}
},
{
"type": "way",
"id": 108219853,
"center": {
"lat": -37.3422119,
"lon": 144.1416651
},
"nodes": [
1241978597,
1241978598,
13589291160,
1241978599,
1241978602,
1241978603,
1241978604,
2176313230,
1241978594,
13589291158,
13589291159,
1241978589,
1241978596,
1241978597
],
"tags": {
"addr:housenumber": "32",
"addr:street": "Albert Street",
"brand": "Coles Local",
"brand:wikidata": "Q104850818",
"brand:wikipedia": "en:Coles Supermarkets",
"building": "yes",
"name": "Coles Local",
"opening_hours": "Mo-Su 07:00-21:00",
"operator": "Coles Group",
"operator:wikidata": "Q131937428",
"phone": "+61 3 5325 7200",
"shop": "supermarket",
"website": "https://www.coles.com.au/"
}
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,841 @@
{
"fetchedAt": "2026-07-16",
"endpoint": "https://overpass-api.de/api/interpreter",
"query": "[out:json][timeout:180];(nwr[\"shop\"~\"^(antiques|bag|bakery|books|bookshop|boutique|butcher|charity|cheese|chemist|chocolate|clothes|coffee|confectionery|convenience|cosmetics|dairy|deli|delicatessen|department_store|doityourself|electronics|farm|fashion|florist|furniture|games|garden_centre|general|greengrocer|hardware|homeware|houseware|jewellery|jewelry|kiosk|mobile_phone|music|newsagent|pastry|pawnbroker|perfumery|pharmacy|second_hand|shoes|stationery|supermarket|tea|toys|trade|variety_store|video|video_games|vintage)$\"][\"name\"](-32.93431,151.73112,-32.91269,151.75688);nwr[\"amenity\"~\"^(cafe)$\"][\"name\"](-32.93431,151.73112,-32.91269,151.75688););out center;",
"bbox": {
"minLat": -32.93431081081081,
"minLon": 151.73112074181012,
"maxLat": -32.91268918918919,
"maxLon": 151.75687925818988
},
"elements": [
{
"type": "node",
"id": 367127925,
"lat": -32.9173937,
"lon": 151.7314109,
"tags": {
"brand": "IGA",
"brand:wikidata": "Q5970945",
"brand:wikipedia": "en:IGA Supermarkets Australia)",
"name": "IGA",
"shop": "supermarket",
"wheelchair": "yes"
}
},
{
"type": "node",
"id": 1612632841,
"lat": -32.9172505,
"lon": 151.7491889,
"tags": {
"amenity": "cafe",
"name": "Suspension Espresso",
"website": "https://www.slingtown.com"
}
},
{
"type": "node",
"id": 2999805547,
"lat": -32.9188202,
"lon": 151.7480964,
"tags": {
"amenity": "cafe",
"cuisine": "coffee_shop",
"name": "Roladoor Cafe",
"opening_hours:signed": "no"
}
},
{
"type": "node",
"id": 2999805549,
"lat": -32.9175975,
"lon": 151.7501325,
"tags": {
"amenity": "cafe",
"name": "Peaberrys Coffee Roasters",
"website": "https://www.peaberrys.com.au/"
}
},
{
"type": "node",
"id": 2999805552,
"lat": -32.9243297,
"lon": 151.7470182,
"tags": {
"amenity": "cafe",
"name": "Mockingbird Cafe"
}
},
{
"type": "node",
"id": 2999805558,
"lat": -32.9243567,
"lon": 151.7467553,
"tags": {
"amenity": "cafe",
"name": "Blue Door Cafe"
}
},
{
"type": "node",
"id": 2999805559,
"lat": -32.9239333,
"lon": 151.7470158,
"tags": {
"addr:housenumber": "129",
"addr:street": "Beaumont Street",
"amenity": "cafe",
"brand": "Gloria Jean's",
"brand:wikidata": "Q2666365",
"cuisine": "coffee_shop",
"name": "Gloria Jean's",
"official_name": "Gloria Jean's Coffees",
"takeaway": "yes"
}
},
{
"type": "node",
"id": 3128619076,
"lat": -32.9220235,
"lon": 151.7471464,
"tags": {
"amenity": "pharmacy",
"brand": "Priceline Pharmacy",
"brand:wikidata": "Q7242652",
"healthcare": "pharmacy",
"name": "Priceline Pharmacy",
"shop": "chemist"
}
},
{
"type": "node",
"id": 3377399796,
"lat": -32.9171649,
"lon": 151.7322129,
"tags": {
"name": "Like-nu Appliances",
"shop": "electronics"
}
},
{
"type": "node",
"id": 3379211532,
"lat": -32.914319,
"lon": 151.7568551,
"tags": {
"name": "Viatek",
"shop": "electronics"
}
},
{
"type": "node",
"id": 3725992754,
"lat": -32.9141506,
"lon": 151.7328501,
"tags": {
"name": "Newy Workwear",
"shop": "clothes"
}
},
{
"type": "node",
"id": 3727810194,
"lat": -32.9189192,
"lon": 151.7474545,
"tags": {
"name": "Home of Stone",
"shop": "hardware"
}
},
{
"type": "node",
"id": 3727810198,
"lat": -32.9194716,
"lon": 151.7479665,
"tags": {
"name": "Samaritans",
"shop": "clothes"
}
},
{
"type": "node",
"id": 3842345611,
"lat": -32.9156254,
"lon": 151.7463359,
"tags": {
"name": "Broadley Signs",
"shop": "hardware"
}
},
{
"type": "node",
"id": 5172145221,
"lat": -32.9161294,
"lon": 151.7325481,
"tags": {
"name": "Newcastle Home Timber And Hardware",
"shop": "hardware"
}
},
{
"type": "node",
"id": 5298432698,
"lat": -32.9246914,
"lon": 151.7375446,
"tags": {
"addr:housenumber": "226",
"addr:street": "Denison Street",
"name": "Belflora",
"shop": "florist"
}
},
{
"type": "node",
"id": 5298467054,
"lat": -32.9241201,
"lon": 151.7395237,
"tags": {
"addr:housenumber": "54-56",
"addr:street": "Belford Street",
"amenity": "cafe",
"check_date": "2025-05-23",
"cuisine": "sandwich;coffee_shop;french;breakfast;cake",
"internet_access": "no",
"name": "The Little French Cafe",
"opening_hours": "Mo-Fr 07:00-14:00; Sa 08:00-12:00",
"outdoor_seating": "no",
"payment:cash": "yes",
"payment:credit_cards": "yes",
"payment:debit_cards": "yes",
"phone": "+61 455 196 070",
"smoking": "no",
"wheelchair": "limited"
}
},
{
"type": "node",
"id": 5601162021,
"lat": -32.9243212,
"lon": 151.7479496,
"tags": {
"name": "Jim's Dairy Delight Bar",
"shop": "confectionery"
}
},
{
"type": "node",
"id": 6869527385,
"lat": -32.9207022,
"lon": 151.7464265,
"tags": {
"addr:housenumber": "67",
"addr:street": "Cleary Street",
"amenity": "cafe",
"cuisine": "breakfast;coffee_shop",
"name": "Olive Branch Cafe"
}
},
{
"type": "node",
"id": 7580092892,
"lat": -32.9213178,
"lon": 151.7473098,
"tags": {
"addr:housenumber": "66",
"addr:postcode": "2303",
"addr:state": "NSW",
"addr:street": "Beaumont Street",
"addr:suburb": "Hamilton",
"air_conditioning": "yes",
"amenity": "cafe",
"bar": "yes",
"cuisine": "international;coffee_shop",
"delivery": "yes",
"description": "Newest foodie scene to hit Newcastle, breakfast, lunch, dinner and late night eats. Craft beers, bottomless coffee and awesome food!",
"diet:dairy_free": "yes",
"diet:gluten_free": "yes",
"diet:vegan": "yes",
"diet:vegetarian": "yes",
"email": "hello@sonofagundiner.com.au",
"internet_access": "wlan",
"internet_access:fee": "customers",
"name": "Son of a Gun",
"opening_hours": "24/7",
"outdoor_seating": "yes",
"payment:cash": "yes",
"payment:credit_cards": "yes",
"payment:debit_cards": "yes",
"payment:mastercard": "yes",
"payment:visa": "yes",
"phone": "+61 2 4049 1136",
"reservation": "yes",
"smoking": "no",
"takeaway": "yes",
"website": "https://www.sonofagundiner.com.au/"
}
},
{
"type": "node",
"id": 8453102948,
"lat": -32.9153262,
"lon": 151.7487223,
"tags": {
"amenity": "cafe",
"cuisine": "coffee_shop",
"name": "The Fast Lane"
}
},
{
"type": "node",
"id": 11264117470,
"lat": -32.9202347,
"lon": 151.7424602,
"tags": {
"addr:housenumber": "4",
"addr:postcode": "2303",
"addr:state": "NSW",
"addr:street": "Samdon Street",
"addr:suburb": "Hamilton",
"amenity": "cafe",
"name": "Second Fiddle Cafe",
"website": "https://www.secondfiddle.com.au"
}
},
{
"type": "node",
"id": 11332612308,
"lat": -32.9243007,
"lon": 151.7501634,
"tags": {
"brand": "OTR",
"brand:wikidata": "Q116394019",
"name": "OTR",
"shop": "convenience"
}
},
{
"type": "node",
"id": 12223202805,
"lat": -32.9214595,
"lon": 151.7475743,
"tags": {
"name": "Hamilton IGA",
"shop": "supermarket"
}
},
{
"type": "node",
"id": 12857192879,
"lat": -32.9233659,
"lon": 151.7471632,
"tags": {
"check_date": "2025-05-23",
"email": "info@qsbooks.com.au",
"name": "Q's Books",
"phone": "+61 2 4961 0222",
"second_hand": "yes",
"shop": "books",
"website": "https://qsbooks.com.au",
"wheelchair": "limited"
}
},
{
"type": "node",
"id": 12857192880,
"lat": -32.9223281,
"lon": 151.7471114,
"tags": {
"check_date": "2025-05-23",
"name": "Rice's Bookshop",
"phone": "+61 2 4929 2752",
"shop": "books",
"wheelchair": "limited"
}
},
{
"type": "node",
"id": 12857192881,
"lat": -32.9212777,
"lon": 151.7475952,
"tags": {
"check_date": "2025-05-23",
"name": "Australian Red Cross",
"opening_hours": "Mo-Fr 09:00-16:45; Sa 09:00-14:45; Su off",
"phone": "+61 2 4086 4712",
"second_hand": "yes",
"shop": "charity",
"wheelchair": "yes"
}
},
{
"type": "way",
"id": 307525838,
"center": {
"lat": -32.9209867,
"lon": 151.7472423
},
"nodes": [
3127081728,
3127082329,
3127082331,
11323345477,
11323345478,
3127082330,
3127081728
],
"tags": {
"amenity": "pharmacy",
"building": "commercial",
"healthcare": "pharmacy",
"name": "Discount Chemist",
"shop": "chemist"
}
},
{
"type": "way",
"id": 329987168,
"center": {
"lat": -32.9187688,
"lon": 151.7461999
},
"nodes": [
3369503335,
3369503331,
3369503332,
3369503325,
3369503324,
3369503318,
3369503320,
3369503330,
3369503329,
3369503339,
11367128008,
11367128007,
3369503335
],
"tags": {
"addr:housenumber": "11",
"addr:street": "Swan Street",
"brand": "ALDI",
"brand:wikidata": "Q41171672",
"brand:wikipedia": "en:Aldi",
"building": "retail",
"check_date:opening_hours": "2023-05-05",
"full_name": "ALDI Hamilton",
"landuse": "retail",
"name": "ALDI",
"opening_hours": "Mo-We,Fr-Su 08:30-20:00; Th 08:30-21:00",
"shop": "supermarket",
"website": "https://store.aldi.com.au/nsw/hamilton/11-swan-street",
"wheelchair": "yes"
}
},
{
"type": "way",
"id": 329988023,
"center": {
"lat": -32.9182007,
"lon": 151.7465886
},
"nodes": [
3369516642,
3369516641,
11384237318,
3369516635,
3369516636,
3369516642
],
"tags": {
"building": "commercial",
"name": "Empire Furniture Newcastle",
"shop": "furniture"
}
},
{
"type": "way",
"id": 330881040,
"center": {
"lat": -32.9171257,
"lon": 151.7320175
},
"nodes": [
3379178024,
3379178025,
11206155925,
11206155926,
3379178028,
3379178027,
3379178024
],
"tags": {
"amenity": "cafe",
"building": "commercial",
"name": "Crema Coffee House"
}
},
{
"type": "way",
"id": 334998496,
"center": {
"lat": -32.9256878,
"lon": 151.7569896
},
"nodes": [
3421299804,
11403848649,
3421299802,
11403848650,
3421299803,
3421299805,
8229426274,
3421299804
],
"tags": {
"branch": "Sofas",
"brand": "Plush",
"brand:wikidata": "Q111081152",
"building": "commercial",
"name": "Plush",
"shop": "furniture"
}
},
{
"type": "way",
"id": 336940406,
"center": {
"lat": -32.915699,
"lon": 151.732786
},
"nodes": [
3440293013,
3440292984,
3440292983,
3440292982,
3440293045,
3440293024,
3440293013
],
"tags": {
"building": "retail",
"contact:facebook": "https://www.facebook.com/AstroTileNewcastle/",
"name": "Astro Tile Newcastle",
"shop": "trade",
"trade": "tiles"
}
},
{
"type": "way",
"id": 370660542,
"center": {
"lat": -32.9250385,
"lon": 151.7339859
},
"nodes": [
3743565333,
3743565335,
3743565328,
3743565326,
3743560016,
3743560017,
3743565331,
3743565330,
3743565336,
3743565337,
3743565350,
3743565349,
3743565333
],
"tags": {
"brand": "Harvey Norman",
"brand:wikidata": "Q4040441",
"building": "yes",
"name": "Harvey Norman",
"shop": "electronics"
}
},
{
"type": "way",
"id": 370660545,
"center": {
"lat": -32.9250096,
"lon": 151.7347638
},
"nodes": [
3743569412,
3743560021,
3743560022,
3743565339,
3743565338,
3743569412
],
"tags": {
"brand": "Cash Converters",
"brand:wikidata": "Q5048645",
"building": "yes",
"name": "Cash Converters",
"shop": "pawnbroker"
}
},
{
"type": "way",
"id": 377809581,
"center": {
"lat": -32.9136842,
"lon": 151.7470167
},
"nodes": [
3812081538,
3812077953,
3812081537,
3812081541,
3812081539,
3812081540,
3812081538
],
"tags": {
"landuse": "retail",
"name": "Purnell Trophie & Giftware",
"shop": "variety_store"
}
},
{
"type": "way",
"id": 377809743,
"center": {
"lat": -32.914817,
"lon": 151.7477229
},
"nodes": [
3812076824,
3812076823,
3812076825,
3812076826,
3812076824
],
"tags": {
"building": "retail",
"email": "newcastle@tinks.com.au",
"landuse": "industrial",
"name": "Tink's - Newcastle (Newcastle Chainsaw & Mowers)",
"opening_hours": "Mo-Fr 08:00-17:00, Sa 08:00-14:00",
"operator": "Tink's Group",
"payment:afterpay": "yes",
"payment:apple_pay": "yes",
"payment:credit_cards": "yes",
"payment:debit_cards": "yes",
"payment:google_pay": "yes",
"payment:openpay": "yes",
"payment:zipmoney": "yes",
"phone": "+61 2 4961 1332",
"shop": "hardware",
"website": "https://www.tinks.com.au"
}
},
{
"type": "way",
"id": 377811131,
"center": {
"lat": -32.9169724,
"lon": 151.7491715
},
"nodes": [
3812092799,
3410550229,
3812092639,
3812092800,
3812092799
],
"tags": {
"landuse": "retail",
"name": "Mei Li Furniture & Collectables",
"shop": "antiques"
}
},
{
"type": "way",
"id": 377811132,
"center": {
"lat": -32.9168849,
"lon": 151.7491025
},
"nodes": [
3812095511,
3812095510,
3812095508,
3812095509,
3812095511
],
"tags": {
"landuse": "retail",
"name": "Yardsale",
"shop": "antiques"
}
},
{
"type": "way",
"id": 377811362,
"center": {
"lat": -32.9168403,
"lon": 151.7490657
},
"nodes": [
3812095510,
3812092638,
3812092798,
3812095508,
3812095510
],
"tags": {
"landuse": "retail",
"name": "Holahan Antiques",
"shop": "antiques"
}
},
{
"type": "way",
"id": 377811366,
"center": {
"lat": -32.9169139,
"lon": 151.7491261
},
"nodes": [
3812095509,
3812092799,
3812092800,
3812095511,
3812095509
],
"tags": {
"landuse": "retail",
"name": "Earths Garden Organics",
"shop": "convenience"
}
},
{
"type": "way",
"id": 377811647,
"center": {
"lat": -32.9175394,
"lon": 151.7493128
},
"nodes": [
3812097488,
3812135409,
3812135411,
3812097491,
3812097488
],
"tags": {
"building": "yes",
"name": "Regent Renovators",
"shop": "hardware"
}
},
{
"type": "way",
"id": 377812394,
"center": {
"lat": -32.9181308,
"lon": 151.7496607
},
"nodes": [
3812104221,
3727826406,
3727826407,
8195806812,
3812104224,
3812104225,
3812104223,
8195806809,
3812104221
],
"tags": {
"landuse": "commercial",
"name": "Reece",
"shop": "hardware"
}
},
{
"type": "way",
"id": 377814336,
"center": {
"lat": -32.9174539,
"lon": 151.748783
},
"nodes": [
3812127767,
3812127762,
3812127761,
3812127765,
3812127767
],
"tags": {
"building": "retail",
"name": "It\u2019s Just Because By Heather",
"shop": "variety_store"
}
},
{
"type": "way",
"id": 377817467,
"center": {
"lat": -32.9169012,
"lon": 151.74975
},
"nodes": [
3812170975,
3812129989,
3812170974,
3812170976,
3812170975
],
"tags": {
"landuse": "retail",
"name": "Islington Antiques",
"shop": "antiques"
}
},
{
"type": "way",
"id": 377817468,
"center": {
"lat": -32.9164537,
"lon": 151.7494586
},
"nodes": [
3812188098,
3812188097,
3812188099,
3812188100,
3812188098
],
"tags": {
"landuse": "retail",
"name": "Combined Collectables",
"shop": "antiques"
}
},
{
"type": "way",
"id": 377818801,
"center": {
"lat": -32.9162029,
"lon": 151.7492962
},
"nodes": [
3812188095,
7935349537,
3812188093,
3812188094,
3812188096,
3812188095
],
"tags": {
"landuse": "retail",
"name": "Saint Vincents de Paul",
"shop": "clothes"
}
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,20 @@
"license": "ODbL 1.0",
"attribution": "\u00a9 OpenStreetMap contributors",
"towns": [
{
"key": "adelaide_real",
"town": "Adelaide",
"state": "SA",
"shops": 116,
"roads": true
},
{
"key": "ballarat_real",
"town": "Ballarat",
"state": "VIC",
"shops": 20,
"roads": true
},
{
"key": "bendigo_real",
"town": "Bendigo",
@ -11,6 +25,27 @@
"shops": 36,
"roads": true
},
{
"key": "bowral_real",
"town": "Bowral",
"state": "NSW",
"shops": 32,
"roads": true
},
{
"key": "braddon_real",
"town": "Braddon",
"state": "ACT",
"shops": 20,
"roads": true
},
{
"key": "brunswick_real",
"town": "Brunswick",
"state": "VIC",
"shops": 96,
"roads": true
},
{
"key": "castlemaine_real",
"town": "Castlemaine",
@ -18,6 +53,27 @@
"shops": 24,
"roads": true
},
{
"key": "darwin_real",
"town": "Darwin",
"state": "NT",
"shops": 12,
"roads": true
},
{
"key": "daylesford_real",
"town": "Daylesford",
"state": "VIC",
"shops": 32,
"roads": true
},
{
"key": "fitzroy_real",
"town": "Fitzroy",
"state": "VIC",
"shops": 160,
"roads": true
},
{
"key": "fremantle_real",
"town": "Fremantle",
@ -25,6 +81,27 @@
"shops": 80,
"roads": true
},
{
"key": "geelong_real",
"town": "Geelong",
"state": "VIC",
"shops": 68,
"roads": true
},
{
"key": "glebe_real",
"town": "Glebe",
"state": "NSW",
"shops": 52,
"roads": true
},
{
"key": "hobart_real",
"town": "Hobart",
"state": "TAS",
"shops": 80,
"roads": true
},
{
"key": "katoomba_real",
"town": "Katoomba",
@ -32,12 +109,54 @@
"shops": 80,
"roads": true
},
{
"key": "launceston_real",
"town": "Launceston",
"state": "TAS",
"shops": 32,
"roads": true
},
{
"key": "marrickville_real",
"town": "Marrickville",
"state": "NSW",
"shops": 28,
"roads": true
},
{
"key": "newcastle_real",
"town": "Newcastle",
"state": "NSW",
"shops": 36,
"roads": true
},
{
"key": "newtown_real",
"town": "Newtown",
"state": "NSW",
"shops": 72,
"roads": true
},
{
"key": "northbridge_real",
"town": "Northbridge",
"state": "WA",
"shops": 60,
"roads": true
},
{
"key": "toowoomba_real",
"town": "Toowoomba",
"state": "QLD",
"shops": 12,
"roads": true
},
{
"key": "westend_real",
"town": "West End",
"state": "QLD",
"shops": 44,
"roads": true
}
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -448,6 +448,8 @@ window.PROCITY = { plan, scene, camera, renderer, chunks, lighting, player, skin
// decide there's no gig layer at all). `.state` is a live getter: quiet|doors|on|done
venuePresentation, // [Lane F R12] Lane B frontage + posters (null flags-off)
venueQueues, queueCountOf, // [Lane F R13] Lane D outdoor queue per venue + count accessor (F's smoke reads it)
tram, // [Lane F R21] Lane B's tram — `.routeInfo` carries the R20 shop-adjacency verdict
// ({fenced, reason, shopsFronted}) + `.stops`; B built it FOR F's smoke. Null flags-off.
// [Lane F R16 — THE FLIP] the flag-intent surface: what SHOULD be on this boot (the gates verify intent vs
// reality). Default boot = all four flipped flags true; ?classic=1 = all false + classic true; each `=0` opts out.
flags: { classic: CLASSIC, gigs: GIGS_ON, weather: flagOn('weather'), winmap: flagOn('winmap'), tram: flagOn('tram') },

View File

@ -44,6 +44,9 @@ const GIGS_PER_VENUE = [4, 6]; // per week — the rest are dark nights, whic
// Kind order as venues are added. A town of 4 gets a second pub at the far end of the spine —
// two pubs and a footy club is the most Australian town there is.
const VENUE_SEQUENCE = ['pub', 'band_room', 'rsl', 'pub'];
// ROUND21 (D's relocation finding): a venue 1 km from the retail cluster is a gig with no passing crowd
// (katoomba's pub had 1 shop within 160 m; the RSL had 13). Venue candidates prefer cluster adjacency.
const CLUSTER_R = 160, CLUSTER_MIN = 3;
// Cover law (ROUND13 §A2): ~half free town-wide; the RSL skews CHEAP (it's a club, the bistro pays the
// bills), the band room skews FREE (the door is a hat on a milk crate). `cover` stays an integer in
@ -92,6 +95,18 @@ function pickVenues(plan, citySeed) {
}
return best;
};
// ROUND21: how many OTHER shops sit within CLUSTER_R of this candidate — its retail-cluster adjacency.
// Real-data plans only: `plan.source === 'osm'` is undefined on the synthetic generator, so the bias
// below can never touch the frozen synthetic goldens BY CONSTRUCTION (not by luck — measured: 4
// synthetic candidates per seed sit under CLUSTER_MIN, so a blanket filter WOULD have moved them).
const realData = plan.source === 'osm';
const shopLots = realData ? plan.shops.map(lotOf).filter(Boolean) : [];
const clusterCount = s => {
const l = lotOf(s); if (!l) return 0;
let n = 0;
for (const o of shopLots) if (o !== l && Math.hypot(o.x - l.x, o.z - l.z) <= CLUSTER_R) n++;
return n;
};
const base = plan.shops.filter(s => {
if (s.openLate) return false; // must not displace the night landmark
@ -108,15 +123,24 @@ function pickVenues(plan, citySeed) {
const pool = base.filter(s => !taken.has(s.id));
if (!pool.length) break; // degenerate town — fewer venues, still valid
// ROUND21 ledger #1: prefer CLUSTER-ADJACENT candidates (the retail heart), then let the kind flavors
// bias WITHIN that set rather than override it — a fringe band_room in the cluster beats a fringe
// band_room a kilometre from anyone. A town with no cluster at all falls back to the whole pool.
let field = pool;
if (realData) {
const clustered = pool.filter(s => clusterCount(s) >= CLUSTER_MIN);
if (clustered.length) field = clustered;
}
let cand;
if (kind === 'band_room') {
cand = pool.filter(s => blockKindOf(s) === 'warehouse');
if (!cand.length) cand = pool.filter(s => !onMain(s)); // osm: no warehouse district
cand = field.filter(s => blockKindOf(s) === 'warehouse');
if (!cand.length) cand = field.filter(s => !onMain(s)); // osm: no warehouse district
} else if (kind === 'rsl') {
cand = pool.filter(s => !onMain(s) && blockKindOf(s) !== 'warehouse');
if (!cand.length) cand = pool.filter(s => !onMain(s));
cand = field.filter(s => !onMain(s) && blockKindOf(s) !== 'warehouse');
if (!cand.length) cand = field.filter(s => !onMain(s));
} else {
cand = pool.filter(onMain);
cand = field.filter(onMain);
// a SECOND pub belongs at the other end of the spine, not next door to the first
const firstPub = out.find(v => v.kind === 'pub');
if (firstPub) {
@ -133,10 +157,11 @@ function pickVenues(plan, citySeed) {
// the synthetic town every pub/rsl candidate already clears, so it stays a no-op there (golden frozen).
{
let clear = cand.filter(s => facadeClear(s) >= POSTER_CLEAR);
if (!clear.length) clear = pool.filter(s => !onMain(s) && facadeClear(s) >= POSTER_CLEAR);
if (!clear.length) clear = field.filter(s => !onMain(s) && facadeClear(s) >= POSTER_CLEAR); // stay in the cluster
if (clear.length) cand = clear;
}
if (!cand.length) cand = pool; // last resort: anything left
if (!cand.length) cand = field; // last resort: anything cluster-adjacent
if (!cand.length) cand = pool; // truly degenerate: anything left
const shortlist = farthestFirst(cand).slice(0, Math.min(5, cand.length));
const shop = pick(rng(citySeed, 'venuepick', i), shortlist);
if (!shop) break;

View File

@ -461,9 +461,11 @@ const REAL_TOWN_GOLDENS = {
// ROUND20: the GIG-layer golden per real town (district + capped posters) — the base golden above is
// gigs-off so it never captured the poster cap. Pinned here so the ROUND20 poster cap (and the density
// absorb to come) are regression-guarded byte-exact, not just by districtInvariants.
// ROUND21: re-pinned for the venue cluster-adjacency bias (D's relocation finding). Only the GIG goldens
// move — venue selection is gig-layer, so the base town goldens above are untouched.
const REAL_TOWN_GIG_GOLDENS = {
katoomba_real: 0x2115732a, newtown_real: 0x17ab31bb, fremantle_real: 0x82c27397,
bendigo_real: 0xf5ce58c4, castlemaine_real: 0x48272da9,
katoomba_real: 0xbf586b77, newtown_real: 0xacdb3eee, fremantle_real: 0xcf3426fc,
bendigo_real: 0x646b2c23, castlemaine_real: 0xf9713a69,
};
// `index.json` is E's towns INDEX (key/town/state/shops/roads for B's selector), not a town cache — skip it.
const townFiles = (existsSync(TOWNS_DIR) ? readdirSync(TOWNS_DIR) : []).filter(f => f.endsWith('.json') && f !== 'index.json');

View File

@ -6,9 +6,12 @@
import * as THREE from 'three';
import { osmTownKeys } from '../citygen/index.js'; // R19 town selector: enumerate OSM fixtures
// R19 (v4.0-alpha, beta pull-forward): the real-roads town caches under web/assets/towns/*.json. Hardcoded
// for the alpha — there is no towns manifest yet; beta derives this from an index file. New towns: add here.
const REAL_TOWNS = ['katoomba_real', 'newtown_real', 'fremantle_real', 'bendigo_real', 'castlemaine_real'];
// R21 (v4.0-beta, ledger #2): the real-roads towns come from E's index (web/assets/towns/index.json), so the
// list grows with the town pack instead of being edited here. This literal is now only the FAIL-SOFT fallback
// — used when the index is missing/unparseable, or under ?noassets (where the shell doesn't fetch town caches
// either, so reading the index would be both pointless and against the asset law). Zero errors either way.
const REAL_TOWNS_FALLBACK = ['katoomba_real', 'newtown_real', 'fremantle_real', 'bendigo_real', 'castlemaine_real'];
const TOWNS_INDEX = 'assets/towns/index.json';
const CSS = `
#pc-hud{position:fixed;inset:0;pointer-events:none;font:13px/1.4 -apple-system,Segoe UI,Roboto,sans-serif;color:#f4efe6;z-index:10}
@ -53,24 +56,46 @@ export function createHUD({ camera, renderer, plan, getDoorMeshes, onEnterShop }
$('pc-town').textContent = plan.name || '—';
$('pc-seed').textContent = plan.citySeed;
// ── town selector (R19, beta pull-forward) — synthetic + OSM fixtures + real-road caches. Navigates
// to the matching URL params, preserving everything else (seed, flags). Lives in the HUD overlay, so it
// hides with the HUD for money shots; usable when the pointer is free (Esc). No index.html seam. ──
// ── town selector (R19; R21 reads E's towns index) — synthetic + OSM fixtures + real-road towns.
// Navigates to the matching URL params, preserving everything else (seed, flags). Lives in the HUD
// overlay, so it hides with the HUD for money shots; usable when the pointer is free (Esc). No
// index.html seam. The real-town list is built SYNCHRONOUSLY from the fallback (so the picker always
// works, including under ?noassets and if the index 404s), then upgraded in place once E's index.json
// resolves — which also gives real names, states and shop counts. ──
(() => {
const sel = $('pc-town-select'); if (!sel) return;
const params = new URLSearchParams(location.search);
const cur = params.get('plansrc') === 'osm' ? (params.get('town') || '') : '';
const NOASSETS = params.get('noassets') != null && params.get('noassets') !== '0';
const cap = (k) => k.replace(/_real$/, '').replace(/(^|[\s_])\w/g, (c) => c.toUpperCase()).replace(/_/g, ' ');
const add = (key, label) => { const o = document.createElement('option'); o.value = key; o.textContent = label; if (key === cur) o.selected = true; sel.appendChild(o); };
add('', '▸ Synthetic — procedural');
for (const k of osmTownKeys().filter((k) => !k.endsWith('_real'))) add(k, `${cap(k)} · OSM fixture`);
for (const k of REAL_TOWNS) add(k, `${cap(k)} · real roads`);
if (cur && !Array.from(sel.options).some((o) => o.value === cur)) add(cur, `${cap(cur)} · (current)`); // unknown current town → still shown
sel.onchange = () => {
const opt = (key, label) => { const o = document.createElement('option'); o.value = key; o.textContent = label; if (key === cur) o.selected = true; return o; };
const build = (realTowns) => {
sel.textContent = '';
sel.appendChild(opt('', '▸ Synthetic — procedural'));
for (const k of osmTownKeys().filter((k) => !k.endsWith('_real'))) sel.appendChild(opt(k, `${cap(k)} · OSM fixture`));
for (const t of realTowns) sel.appendChild(opt(t.key, t.label));
if (cur && !Array.from(sel.options).some((o) => o.value === cur)) sel.appendChild(opt(cur, `${cap(cur)} · (current)`)); // unknown current town → still shown
};
build(REAL_TOWNS_FALLBACK.map((k) => ({ key: k, label: `${cap(k)} · real roads` })));
sel.onchange = () => { // set once; rebuilding the options below never clears it
const v = sel.value, p = new URLSearchParams(location.search);
if (!v) { p.delete('plansrc'); p.delete('town'); } else { p.set('plansrc', 'osm'); p.set('town', v); }
location.search = p.toString(); // reload into the chosen town
};
if (NOASSETS) return; // asset law: no fetch — the fallback list stands
fetch(TOWNS_INDEX, { cache: 'force-cache' })
.then((r) => (r.ok ? r.json() : null))
.then((j) => {
const towns = j && Array.isArray(j.towns) ? j.towns.filter((t) => t && t.key) : null;
if (!towns || !towns.length) return; // keep the fallback, silently
build(towns.map((t) => ({
key: t.key,
label: `${t.town || cap(t.key)}${t.state ? ', ' + t.state : ''}`
+ (t.shops != null ? ` · ${t.shops} shops` : '')
+ (t.roads === false ? ' · marched' : ''),
})));
})
.catch(() => {}); // index missing/blocked → fallback stands, zero errors
})();
const ray = new THREE.Raycaster();