Lane C R20 (v4.0-beta): publish OSM-class -> archetype mapping (ledger #2, C's half)

The density widening's C half: real towns fetch general retail, not just secondhand.
Published the OSM shop-class -> registry-archetype mapping in LANE_C_PUB.md §6 (new
v4.0-beta amendment; frozen venue contract §0-§5 untouched). C->E handshake: E builds to it.

- No new archetypes. General retail wears existing recipes: food/grocer/newsagent/chemist
  -> milkbar; clothes/hardware/big-retail -> dept; produce/florist -> stall.
- Secondhand stays the hero (charity->opshop, books->book, music->record, video->video,
  pawn->pawn, toys->toy); never subsampled. Unknown/unlisted -> opshop (R18-proven).
- Subtle per John: texture not takeover. Copy-paste JSON map + tasteful fetch list (skip
  vehicle/funeral/industrial/pure-services) + guardrail for E to subsample if retail drowns
  the secondhand strip (count in norm.dropped).
- Mechanic: plan_osm keeps registry types, so E bakes a registry type per the map into each
  cache's shop.type -> no C code change, budgets unchanged.

Pre-validated before E builds to it: milkbar/dept/stall/opshop all build valid at a real
katoomba lot (8.5x14, 0 carves, <=143 draws); dept reads as a clean dressed-retail floor
(shelves+racks+counter, escalator does not dominate the 7.9x11.7 hall) -> clothes/hardware
-> dept confirmed. Full five-town door-soak (ledger #6) follows E's re-emitted caches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-16 18:28:50 +10:00
parent 955ec3497b
commit c7ca39b4f7
2 changed files with 121 additions and 7 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 19) · owner: PROCITY-C · reviewer: Fable
Last updated: 2026-07-16 (round 20) · owner: PROCITY-C · reviewer: Fable
---
## Update 2026-07-16 (round 20, v4.0-beta FIVE TOWNS) — the class→archetype mapping (ledger #2, C's half)
R20 §Lane C (I lead — E builds to it, half-day rule): **published the OSM shop-class → interior archetype
mapping** in [LANE_C_PUB.md](docs/LANES/LANE_C_PUB.md) **§6** (new v4.0-beta amendment; the frozen venue
contract §0§5 untouched). This is the density widening — real towns fetch **general retail**, not just the
thriftgod secondhand classes, so the main street holds its real bakery/cafe/chemist/clothes shops.
**Design (John's directive: SUBTLE — texture, not takeover):**
- **No new archetypes.** General retail wears **existing** recipes: food/grocer/newsagent/chemist → `milkbar`
(the canonical AU counter shop); clothes/hardware/big-retail → `dept`; produce/florist → `stall`.
- **Secondhand stays the hero** — charity/antiques→opshop, books→book, music→record, video/games→video,
pawn→pawn, toys→toy; never subsampled.
- **Unknown/unlisted → `opshop`** (R18-proven safe). Included a copy-paste JSON map for E's `build_towns.py`
+ a tasteful fetch list (skip vehicle/funeral/industrial/pure-services like hairdresser/bank).
- **Guardrail for E:** if a town's general retail would visually drown the secondhand strip, seed-subsample
the texture classes toward ~23× the secondhand count and count the drops in `norm.dropped`.
**Mechanic note:** `plan_osm` keeps only registry types (unknowns flatten to opshop), so E bakes a **registry
type** per the map into each cache's `shop.type` — no C code change, all targets are existing recipes/registry
entries, budgets unchanged. **C→E handshake: §6 is live.**
**Pre-validated the mapping (measurement over folklore, before E builds to it):** milkbar/dept/stall/opshop all
build valid at the katoomba lot (8.5×14) — 0 carves, ≤143 draws, pathOK. Rendered `dept` (my one flagged case
— the escalator centrepiece): reads as a clean **dressed-retail floor** (cube shelves of goods + clothes rack +
counter + "GROUND FLOOR/HABERDASHERY" signage) in the 7.9×11.7 hall, escalator does *not* dominate — so
`clothes`/`hardware` → `dept` is confirmed, not a concern.
**Pending (ledger #6, after E re-emits the 5 widened caches):** the five-town sampled door-soak — every town,
sampled doors at the new density, all types resolve, no carve, budgets; one table, five rows. I'll watch that
`dept` reads right on small real lots (the escalator centrepiece). Docs-only this commit; door-soak follows E.
---

View File

@ -1,9 +1,10 @@
# LANE C — venue interface contract (v3.0-FROZEN: the district) → Lane D + Lane F
# LANE C — interiors contract (venues + real-town class mapping) → Lanes A/D/E/F
> **v3.0-FROZEN** · 2026-07-16 · durable contract for Lane D + Lane F. Describes the *shipped* state;
> changes require a version bump (CITY_SPEC amendment law). Verified R13 (build) + R14 (release audit).
> **v3.1 amendment (2026-07-16):** §3 becomes the `stage.backline[]` contract (ledger #5 — the amp
> unification); C dropped its primitive ampStacks. Everything else in this doc is unchanged and stands.
> **v3.0-FROZEN** · 2026-07-16 · durable contract for Lane D + Lane F. §0§5 describe the *shipped*
> venue state; changes require a version bump (CITY_SPEC amendment law). Verified R13 (build) + R14 (audit).
> **v3.1 amendment:** §3 became the `stage.backline[]` contract (ledger #5 — the amp unification).
> **v4.0-beta amendment (2026-07-16):** **§6 added — the real-town shop-class → archetype mapping**
> (ledger #2, the density widening; C→E handshake). The frozen venue contract (§0§5) is unchanged.
*The district ships **three** venue archetypes behind `?gigs=1``pub`, `band_room`, `rsl`. Lane A
converts a chosen shop to a venue kind in place (`shop.type = kind`); C keys the interior recipe off
@ -136,4 +137,84 @@ bar in the corner — the PA louder than the room. `rsl` = carpet-and-flock club
(hall/wide), a proper raised stage at one end, bistro tables round the edge, members' bar, the biggest crowd
cap. Both reuse the `pub` venue machinery (`theme.js venueSpec` + `layout.js` placeStage/placeWatchPoints);
only the dressing + `venueSpec` differ. Stage/PA keep GLB slots for Lane E (primitive fallback holds); the
primitive ampStacks are the backline fallback (see §3).
backline amp is D's, planted at `stage.backline[0]` (see §3).
---
## 6. Real-town shop-class → interior archetype mapping (v4.0-beta, ledger #2) → Lane E
**Directive (John, kickoff — SUBTLE: texture, not takeover).** The secondhand shops stay the **heroes** of
the town (they *are* the game). The widening adds general retail as *texture* — the everyday main-street
staples a real Australian town has — mapped onto **existing** archetypes (**no new archetypes this round**).
The player should feel the town's more alive, not that the game changed.
**How it's applied (E owns the emission).** `plan_osm` keeps only **registry types** (`SHOP_TYPES` — unknowns
flatten to `opshop`). So E maps each fetched OSM `shop=*` / `amenity=*` value to a **registry type** below and
bakes it into the cache's `shop.type`. Every target is an existing type, so C's recipes, A's registry, and the
budgets are all unchanged. Unknown/unlisted classes degrade safely to `opshop` (R18-proven: 18 real OSM types
all built valid).
**Heroes — secondhand (unchanged; NEVER subsampled):**
| OSM class | → type |
|---|---|
| `charity`, `second_hand`, `antiques`, `vintage` | `opshop` |
| `books`, `bookshop` | `book` |
| `music` | `record` |
| `video`, `games` | `video` |
| `pawnbroker` | `pawn` |
| `toys` | `toy` |
**Widened — everyday main-street texture (general retail):**
| OSM class(es) | → type | wears it as |
|---|---|---|
| `bakery`, `cafe`†, `confectionery`, `pastry`, `chocolate`, `deli`/`delicatessen`, `butcher`, `cheese`, `coffee`, `tea` | `milkbar` | the food counter |
| `convenience`, `kiosk`, `general`, `dairy` | `milkbar` | the corner store |
| `newsagent`, `stationery` | `milkbar` | papers + magazines |
| `chemist`, `pharmacy`, `cosmetics`, `perfumery` | `milkbar` | dispensary counter |
| `clothes`, `fashion`, `boutique`, `shoes`, `bag`, `jewelry`/`jewellery` | `dept` | the dressed retail floor |
| `department_store`, `variety_store`, `supermarket` | `dept` | big general retail |
| `hardware`, `doityourself`, `trade`, `electronics`, `mobile_phone`, `furniture`, `houseware`/`homeware` | `dept` | shelved goods |
| `greengrocer`, `florist`, `farm`, `garden_centre` | `stall` | produce/plants on trestles |
`cafe`/`fast_food` are `amenity=*`, not `shop=*` — fetch them from the amenity tag; everything else is `shop=*`.
**Fallback:** any fetched class not listed → `opshop`.
**Copy-paste map for E (`build_towns.py`):**
```json
{
"charity":"opshop","second_hand":"opshop","antiques":"opshop","vintage":"opshop",
"books":"book","bookshop":"book","music":"record","video":"video","games":"video",
"pawnbroker":"pawn","toys":"toy",
"bakery":"milkbar","cafe":"milkbar","confectionery":"milkbar","pastry":"milkbar","chocolate":"milkbar",
"deli":"milkbar","delicatessen":"milkbar","butcher":"milkbar","cheese":"milkbar","coffee":"milkbar","tea":"milkbar",
"convenience":"milkbar","kiosk":"milkbar","general":"milkbar","dairy":"milkbar",
"newsagent":"milkbar","stationery":"milkbar",
"chemist":"milkbar","pharmacy":"milkbar","cosmetics":"milkbar","perfumery":"milkbar",
"clothes":"dept","fashion":"dept","boutique":"dept","shoes":"dept","bag":"dept","jewelry":"dept","jewellery":"dept",
"department_store":"dept","variety_store":"dept","supermarket":"dept",
"hardware":"dept","doityourself":"dept","trade":"dept","electronics":"dept","mobile_phone":"dept",
"furniture":"dept","houseware":"dept","homeware":"dept",
"greengrocer":"stall","florist":"stall","farm":"stall","garden_centre":"stall"
}
```
Default (not in the map) → `opshop`.
**Subtlety guardrails (E):**
- Fetch only these tasteful staples — **not** every OSM `shop=*`. Skip vehicle/tyres/fuel, funeral, storage,
industrial, and pure services the player never browses (`hairdresser`, `beauty`, `travel_agency`, `bank`,
`laundry`, `estate_agent`).
- **Never** subsample the secondhand heroes.
- If a town's general-retail count would visually **drown** the secondhand strip, seed-subsample the *texture*
classes (the milkbar/dept/stall targets) toward **~23× the secondhand count**, and count the drops in
`norm.dropped` like every other drop.
**Why these targets:** `milkbar` (counter + fridge + magazine rack + glass case) is the canonical Australian
counter shop — it wears cafe/bakery/deli/newsagent/chemist naturally; `dept` (cube shelves + clothes racks +
glass cases) wears clothes + hardware + big retail; `stall` (trestles + crates) wears produce + florist. Three
general-retail looks + the six secondhand heroes + the three venues = variety with no new archetypes.
**Pre-verified (seed 20261990, real-town lot 8.5×14):** milkbar/dept/stall/opshop all build valid (0 carves,
≤143 draws); `dept` reads as a clean **dressed-retail floor** (cube shelves + clothes racks + counter, the
escalator does *not* dominate the ~7.9×11.7 room), so `clothes`/`hardware` → `dept` is confirmed. C re-checks
the full result in the five-town door-soak (ledger #6) once E's caches land. (FYI: C's `theme.js canonicalType`/ALIAS already recognizes several
of these — `deli`/`corner_store`→milkbar etc. — for any direct `buildInterior(rawClass)`; the authoritative
mapping for the caches is this table.)