Fable (integrator): round-39 instructions — v9 opens: THE ADDRESS LAYER + THE FOG (John's ruling), plus the op-shop dig gap and the magpie settle

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-08-03 20:13:43 +10:00
parent 6c6d6de87d
commit 07328b7e9f

View File

@ -0,0 +1,126 @@
# PROCITY — Round 39 instructions (from Fable, integrator)
Date: 2026-07-26 · **R38 closed green — v8 wave 1 shipped and the town is inhabited** (21 palettes,
36 backyards, the magpie, six panning ambient layers; budget held at **292/300, eight draws of
margin**, because the worst frame is a night frame and both new layers are zero at night).
**JOHN HAS RULED: do the street names.** *"yes do street names for sure and what else can we get on
with? just keep it going."* Round 39 opens **v9 — THE CITY IS THE GAME** with its two zero-draw
keystones, and keeps every other lane busy on work that needs no ruling.
Charters: [V9_THE_CITY_IS_THE_GAME.md](../V9_THE_CITY_IS_THE_GAME.md) (the hunt; read Fable's
verification header first) · [SALE_RED_TICKET_DAY.md](../SALE_RED_TICKET_DAY.md) (the round and the
Band Floor Law) · [V8_SOMEONE_LIVES_HERE.md](../V8_SOMEONE_LIVES_HERE.md) (in flight; wave 2 later).
## THE BINDING FACTS (verified by Fable — do not re-derive, do not contradict without numbers)
1. **17,835 of 19,132 road ways in the shipped caches carry a `name` — 93.2%.** Counted
independently. `plan_osm.js:363` builds each way as `rawWays.push({ kind: roadEdgeKind(rd.kind),
pl })` — it keeps the kind and the geometry and **discards `rd.name`**. Every real street in 23
Australian towns is in this repo and the game has never said one out loud.
2. **The names are recoverable without touching citygen's output.** Plan nodes ARE snapped
projected way points (`plan_osm.js:361-372`, `SNAP=3`), so plan edges lie ON the named ways:
median distance from a plan-edge midpoint to its nearest named way is **0.030.90 m** (worst
town katoomba), and **97.8% of corpus shops (1,192/1,219) resolve to a street name**.
3. **THE INTERIOR MARGIN IS SIX DRAWS, NOT 191.** `index.html:349` ships `useGLB: !NOASSETS`, so
the **default boot is the GLB path**, and `C-progress.md:841` records that sweep at **GLB-on
344** against the ≤350 cap. Any interior work in any epoch spends against **six**.
4. **Vertical movement is fiction.** `player.js:64` and `interior_mode.js:485` both write `y = EYE`
unconditionally every frame on every path — no gravity, no floor query, no storey state, no
floor height in any data structure. **Nothing this round proposes stairs.**
5. **Only record shops and market stalls have a diggable crate**`kind:'bin'` is minted at
`fittings.js:60`/`:75` (`recordBin`, `crate`) and used by exactly two recipes (`theme.js:38-39`
record, `:196` stall). The op shop's `crateStack` is labelled *"back-room dressing"* in its own
comment. **You cannot dig in an op shop**, in a game built on op-shop DNA.
## The ledger
### 39.1 — THE ADDRESS LAYER *(Lane A — the approved thing, and the prerequisite for everything else)*
Recover the names and publish the vocabulary. A new **pure** module (no THREE, no fetch, no plan
mutation): `createAddresses(plan, cache|null)``streetOf(edgeId)` · `localityOf(shopId)`
`{street, district, block, side, label}` · `cohort(predicate)``shopId[]`.
- **Real towns:** street name by nearest named way to the edge midpoint (≤8 m tolerance).
- **Synthetic:** no roads cache and only 22 edges → the label comes from `district.kind` + block:
*"the market end"*, *"the arcade"*, *"the backstreets"*. **Same field, different supplier, one
consumer contract** — this matters, because consumers must not branch on town type.
- The synthesis proposes a **one-line** upgrade: write `norm.shift = {shx, shz}` at
`plan_osm.js:510` into the **caller-supplied `opts.report` sink, never onto the plan object**, so
it moves no golden and breaks no classic byte. **Take it if it is genuinely that clean; measure
and report if it is not.**
- **Goldens must not move.** State it plainly with your selfcheck numbers. If one moves, stop.
- Publish the contract in LANE_A_NOTES §39 in your FIRST commit — B and C both consume it.
### 39.2 — THE FOG *(Lane B — the keystone, zero draws)*
`minimap.js:52-63` draws **every lot in the plan from the first frame**, ungated: one M keypress
hands over all 493 synthetic shops. Measured cost of earning that yourself: **5,330 m synthetic /
9,622 m fitzroy / 5,797 m northbridge** of walking — **4.8 / 8.7 / 5.3 game-days** at WALK 4.6 m/s
against the 240-second day.
- Gate the map to shops the player has **walked past**; discovery is **player state**, saved under
the delta law (size it: 24 towns × N shops, bounded, and prove export/import + corrupt-reject).
- **Frame the map to what you know.** The payoff is the reason to do it: a shop rectangle goes from
**0.8×1.1 px to 29×39 px on bowral — a 35× legibility gain** (21× katoomba, 17× adelaide, 11×
fitzroy). The map is currently useless on the 21 towns that are supposed to be 21 mental maps.
- **BINDING corrections from the judges:** discovery is a **proximity probe, not
`chunks.onChunkBuilt`** (real towns are all BIG_CITY ⇒ R=2, so the outermost live chunk centre is
128 m out and its far corner 181 m — chunk-built discovery would hand you shops you never saw).
And classic-gate it **by construction**: `createMinimap(plan)` becomes `createMinimap(plan, game
? knownProvider : null)`, where a null provider is today's exact behaviour — the same pattern
`ground.js` already uses, so `minimap.js` needs no flag test at all.
- Consume A's `localityOf` for street labels on the map once A publishes.
### 39.3 — THE OP SHOP CAN'T BE DUG *(Lane C — the game's namesake activity)*
PROCITY is built on thriftgod's op-shop DNA and **an op shop has no diggable bin**. Its recipe is
clothes racks, metal shelves, a bookshelf, a trestle table and a `crateStack` its own comment calls
back-room dressing. Meanwhile the dig — the crown jewel, soaked since v2 — fires only in record
shops and market stalls.
- **Measure first**: what can a player actually DO in each of the 12 shop types today? Enumerate it
honestly (dig / pull-and-buy / nothing) and put the table in your notes. That table is the
deliverable even if nothing else lands.
- **Then the mechanism**: give the op shop a diggable bin (a bric-a-brac tub, a $2 book crate, a
rummage bin — you own the fitting and the recipe). The *mechanism* is uncontroversial and yours.
- **FLAG, do not decide: what is IN it.** Records mixed in? Books and toys through the existing
pull-and-buy pack? Its own item class? That is a John taste call and it is the difference between
"op shops now dig" and "op shops now dig *records*", which changes the game's economy. Propose,
measure the options, and hold.
- **Spend against SIX draws** (fact 3). Say what your bin costs and prove it.
### 39.4 — TWO MAGPIES, AND THE ARCADE'S ASSETS *(Lane E)*
- **Settle the magpie** (filed from R38): B ships a 182-tri procedural bird with vertex-colour
white; E published an 894-tri tinted GLB that reads properly. **Render them side by side at the
size the bird is actually seen** (64/48/32 px, the same sheet form as your tint render) and
recommend. Fable rules on the picture, not the prose.
- **The arcade** is a real 42 m covered lane with **17 shops** and it is dressed as nothing — no
props, no signage, no roof texture, no reverb. Generate its kit for a later round: a two-dollar-
shop A-frame, a key-cutter sign, hanging shopfront signage, a tiled arcade floor skin. Same laws:
$0, on-device, 🟢, provenance rows, and **size every asset by `tris × the instance count the
consuming lane implies`** — the law your own `paling_fence` bought us.
- Correct `magpie.js`'s two stale tri comments (154 vs measured 182) — **that is Lane B's file, so
write the ask, do not edit it.**
### 39.5 — THE GATES AND THE CLOSE *(Lane F, last)*
Gate 39.139.3 with falsifiability controls; full `qa.sh --strict --matrix`; round close. **No tag.**
Specifically: prove the address layer resolves ≥97% of corpus shops and **fails loudly** on a town
with no roads cache; prove the fog hides what has not been walked and **reveals what has** (both
arms, or it is vacuous); prove classic and `?noassets` untouched; and re-measure the interior
budget against fact 3 if C's bin lands.
## Laws
Everything standing. This round: **zero draws is the requirement for 39.1 and 39.2** — they are
information design and must cost nothing on the street · the interior margin is **six** ·
pathspec-atomic commits (four lanes share the tree) · no pushes, no tags — Fable pushes at close ·
every gate ships its control demonstrated.
⚠️ **Tree note:** a background session may still be editing `web/js/world/venue.js`. No lane touches
it this round.
## Order
1. **Parallel: A (39.1, contract in the first commit) · B (39.2) · C (39.3) · E (39.4).**
2. **Then F (39.5).**
## Standing — for John, when he wants them
The op-shop bin's **contents** (39.3) · whether the fog is default-on or a mode · and the v9 shape
itself: the address layer and the fog are its first two layers, and the third (the unmarked door /
semi-hidden retail) waits on how these two feel.