Commit Graph

135 Commits

Author SHA1 Message Date
m3ultra
c1e862cf7c Lane A R27 wave 5: THE FACADE FIX — it was every town, not just the real ones (the covenant amended)
selfcheck ALL GREEN 156,352/156,352; consistency green. 51 goldens re-pinned in this one commit per the
amendment law. scaffold_check is RED and CANNOT be green from here — the covenant hashes are duplicated in
LANE F's files; exact values handed to F in LANE_A_NOTES §R27w5 (I don't edit other lanes' files).

THE RULING'S PREMISE WAS WRONG, AND THE WRONG HALF WAS LOAD-BEARING.
Wave 5 says "synthetic follows B's canon so every golden has been green over a wrong product since R18".
Half right. Synthetic does NOT follow B's canon -- it is broken identically, and so is the marched path,
and so are all three checked-in fixtures. It is not "every real town since R18". It is EVERY TOWN, EVERY
PATH, SINCE v1. The ruling told me to measure the marched path rather than assume it was clean "because
that's how this one survived nine rounds" -- so I measured all three, and the same discipline caught the
premise itself.

MEASURED FIRST, IN B'S CANON (+Z = the facade), BEFORE TOUCHING ANYTHING:
  synthetic seed 20261990   0 toward / 681 away   (dot = -1.0000, exactly anti-parallel)
  marched katoomba/fremantle/godverse, fixtures melbourne/katoomba/silverton   0 toward, all away
  real-roads katoomba   0/72   <- B's number, reproduced
637 of 681 synthetic lots had their facade pointing at NO STREET AT ALL (44 hit a different street by
corner coincidence). Then I confirmed it with my own eyes rather than trust the arithmetic: booted
?classic=1, stood on the synthetic main street at lot 0 -> three blank grey boxes. Walked BEHIND them into
the block -> NUMBAT PLAYTHINGS, sign/door/windows/awning, facing the dirt. The classic covenant town has
been a row of back walls since v1.
After the fix, same camera, same seed, same ?classic=1: CROWN TOYS & GAMES · MARBLES & KITES · NUMBAT
PLAYTHINGS -- a strip of shopfronts facing the road.

FOUR SITES, ONE SIGN, AND EVERY ONE OF THEM SAID SO IN ITS OWN COMMENT:
  plan.js:122    synthetic strip   "facade faces back down the outward normal, to the street"  <- it didn't
  plan.js:244    market row        "the facade then faces -(outward) = +x"                     <- it didn't
  plan_osm:330   marched avenue    "facade faces +z (north) to the avenue"                     <- due south
  plan_osm:443   real roads        B's proven one-liner (B measured it, then reverted it -- A's file)
All four were atan2(outward) where the intent was atan2(-outward). The code never did what its comment
said, and CITY_SPEC:71 blessed the result by writing the SIM convention into the LOTS contract. Nobody was
wrong; the spec was. After: synthetic 681/681, marched + fixtures 100%, real-roads katoomba 72/72.

THE COVENANT MOVED -- JOHN RULED IT, I DIDN'T.
Fixing synthetic necessarily moves 0x3fa36874, frozen "forever" since R16. That is not Lane A's call, so I
stopped and asked with the evidence. John's ruling: AMEND THE COVENANT, FIX ALL PATHS -- the covenant is
anti-drift machinery, not a defect preservative. 51 pins in this commit:
  classic/synthetic  0x3fa36874 -> 0x5f76e76
  gig                0xb1d48ea1 -> 0xec7a2d39
  fixtures           melbourne 0x9c7e76b3 · katoomba 0xf3aafec8 · silverton 0x6d74c4
  23 real towns      base + gig (46)
Verified byte-identical across two fresh processes; pack-xor 0xa5058322. CITY_SPEC records the amendment as
a ONE-TIME, ruling-gated precedent -- from this hash forward the law reads as it always did.

A SECOND BUG THE FIX EXPOSED (fixed here, counted). buildRealRoads seated blocks at KERB = 4 m from the
CENTRELINE, but a `main` carriageway is 10 m wide -- its kerb is at 5 m. EVERY MAIN-STREET BUILDING HAS
STOOD 1 m INSIDE THE ROAD SINCE R18. The footprint never moved; only which face is the front -- so it was
invisible until the shopfront turned around and its poster landed in the traffic lane (-1.07 m clearance,
6 real failures). Blocks now seat behind the kerb per A's own published corridor law (roadWidth/2 +
FOOTPATH). Pack drops 6.4% -> 6.6%, counted, not hidden.

THE CROSS-CONVENTION GATE -- built to F's lesson, not to a spec line. F proved that measuring lots against
CITY_SPEC:71's own convention is SELF-AGREEMENT: 72/72 "facing" over a town of blank walls. So this gate
restates nothing. It replicates LANE B'S OWN maths from buildings.js (toWorld(lot, 0, y, d/2 + 0.02)) and
asks a physical question neither spec line can fudge: does the quad the RENDERER actually draws land nearer
the street than the lot centre? It fires if A's ry sign drifts OR if B's zf sign drifts. It would have
caught this on day one of v1.

CITY_SPEC amendments: the lots contract now states facade/door/frontage = local +Z; the SIM/rig convention
is documented separately as the different thing it is, with the explicit rule -- never assert a lot's
facing against a spec line, assert it against the geometry the renderer draws.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 16:28:20 +10:00
m3ultra
4c2702fc58 Lane B R27 w4: poseForShopFront — and the real towns face the wrong way
The micro-task, done and verified. In doing it I found why F photographed
empty road: it is not the pose.

1. THE DELIVERABLE — DBG.poseForShopFront(sel, dist = 8)
Poses at a NAMED shop's frontage: door centred, sign band + R26 crate mark in
shot, under the verandah. clusterPose() answers "where is the town's HEART",
which is the wrong question for a named shop — Red Hill's heart doesn't contain
Monster Robot, which is exactly how F got three frames of empty road.

Keyed through ONE shop selector: F's R22/R24 resolver lived inside enterShop(),
so I extracted it rather than grow a second key scheme beside it. A selector bug
resolves the wrong shop AND looks like it worked (F's own first cut proved it),
so the id-namespace law now has exactly one home.
  poseForShopFront(31)         → Wholefood Cafe (PLAN id) + ambiguous: "31 is
                                 also the godverseShopId of Silky Oak Furnature"
  poseForShopFront('g:31')     → Silky Oak Furnature (the prefix IS the fence)
  poseForShopFront('g:999999') → {error} — never throws, never guesses
Framing proven by projection, not by eye: doorCentreNdcX = 0.0000 exactly, door
+ sign + mark inside the frustum. Derived from buildings.js, not hardcoded: door
is centred on the lot front (off = 0, unlike poseForShop's off = 1.0); sign band
= min(h,FACADE_H)-0.35 ± 0.25 ⇒ y 2.40-2.90; mark = y 2.45-2.52; camY 2.0 sits
below AWNING_Y 2.95, so a ray rising to a target ≤2.9 can never cross it — the
sign is clear BY GEOMETRY at any distance.

2. CORRECTING MY OWN R27 INTEL — I gave F two wrong numbers. I said the mark
"rides high (y≈3.3)" and the vinyl blocks 4% of it. Both wrong: the mark is at
y 2.45-2.52, and I had scanned y 3.0-3.6 — empty awning air above the sign,
which is why it read ~0. Re-measured: the novelty_record disc (top y 2.50)
reaches INTO the mark band and clips ~15% of the strip from EVERY offset;
moving the camera only changes which 15%. "Shoot head-on" survives, but for the
opposite reason to the one I gave.

3. THE FINDING — every real town's shops face away from their street, since R18.
From Musgrave Road (Monster Robot's own frontEdge 1316) the shop is a blank grey
back wall: no sign, no door, no mark. Measured:
  redhill_godverse  35 shop lots: 0 facing, 35 backwards (dot = -1.000)
  katoomba_real     72 shop lots: 0 facing, 72 backwards (dot = -1.000)
  synthetic         correct — always has been
dot = -1.000 exactly on every lot in both towns: a convention, not a defect.
Katoomba's street_noon — the bookmark the tours have shot for nine rounds — is
46 draws / 19,680 tris of bare road.

Root cause: CITY_SPEC contradicts itself and each generator implements one half.
  CITY_SPEC:71  (lots contract) "World facing = (-sin ry, -cos ry)"  ⇒ -Z facade
  CITY_SPEC:335 (posters, R15)  "the +Z street facade (B's canon)"   ⇒ +Z facade
plan_osm.js:443 obeys the first (its comment: "facade (-Z) faces road").
plan.js, buildings.js, venue.js and the R15 posters obey the second. Synthetic —
the town every golden tests — follows B's canon and looks right, which is exactly
why nine rounds of real-town work never caught it. The epoch's own signature
species: a rule meeting a case written after it.

Proven, then REVERTED: one line in A's plan_osm.js (ry = atan2(-nx,-nz)) flips
katoomba 0/72 → 72/72 facing, and turns poseForShopFront's camera from 26m out in
a paddock into 4m from Musgrave Road — the money shot F specified. Not committed:
it is A's file, it moves every real-town plan (goldens re-pin under amendment
law), and a self-contradicting spec is Fable's to rule on, not mine to pick a
side of.

This also re-reads my R22 diagnosis: I recorded "chunk-buildings 348 tris (0.2%)"
in katoomba's busiest block and credited the instancing work. 348 tris is ~29
boxes — that was not efficiency, it was the buildings being ABSENT from frame. I
read the evidence as a win for five rounds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 15:42:50 +10:00
m3ultra
39cfc3d3ed Lane F R27 (v5.0): the tier-2 reader — pick-then-omit, and the server killed mid-session
#2 THE READER, built to C's §8 ruling (direct wire, no hook) and to what the waves measured,
not to the brief's letter:
  · `pack.gone` set, `price` updated IN PLACE — items[] never added to, removed from, or
    reordered, because its identity AND ORDER are the pick's stability (C §8.3). Filtering the
    array instead reshuffles the crate: C measured ONE sale changing 21 OTHER records.
  · fire-and-forget at room build, 1200ms abort, etag-cached, circuit-broken on first failure.
    The dig never blocks on the network (charter risk #1). No await anywhere near the door.
  · fires ONLY for a real-sourced shop. G's fence 404s a mint shop, and asking anyway would be
    R26's blind probe wearing a server. The manifest already knows which is which.

TIER 2 IS OPT-IN (`?live=1` / `?live=<url>`; absent → byte-identical to the beta). That is the
R26 lesson applied to a server: a default boot that probed for a GODVERSE host would ask a
question with no answer on every machine that isn't John's. Tier 2 is a place you go, not a
thing that happens to you. Auto-discovery is a v5.x question with a reachability contract.

PROVEN IN THE BROWSER (formal smoke class still to land):
  · sold-means-gone, via G's make-fixture (production `gone` is EMPTY — 0 sales since
    2026-07-01 — so a live assert would pass vacuously forever; G built the subject before the
    gate could be born blind): 3 sold → gone[3] → items[] 120→120 IDENTITY AND ORDER INTACT,
    117 survivors, COLLATERAL 0. C called this: both pick-then-omit and filter-the-array hide
    the sold record, so "the gone item never renders" cannot tell them apart — the obvious
    assertion is vacuous and goes green. Collateral is the one that discriminates.
  · KILL THE SERVER MID-SESSION → enter took 13.1ms, worst frame gap 14ms, the crate still
    renders its own 120 real covers, and ZERO console errors. Charter law #1 proven by
    execution instead of assertion — the thing A correctly refused to retire from the risk
    list until this gate went green.

Recorded, not hidden: after a mid-session kill the etag-cached `gone` persists for the session,
so a killed server does not resurrect sold records mid-walk. That is tier-1-plus-last-known, not
tier-1-exactly. It is the honest behaviour (a network blink must not re-stock a shop) and a
server-down BOOT is still pure tier 1 — but it is a nuance the brief's "degrades to tier 1
exactly" doesn't cover, so it goes in writing rather than in the gaps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:34:42 +10:00
m3ultra
bee7563a76 Lane E R27 (v5.0): provenance v5-final — and the roster gap the freeze caught (ledger #6)
THE BUG THE FREEZE FOUND: redhill_godverse was ON DISK but NOT IN THE ROSTER — for three rounds. The v5
provenance table needed real numbers, so I measured instead of carrying the v4 row forward. The count
didn't match: 23 caches on disk, 22 rostered. The missing one was redhill_godverse — THE TOWN THE ENTIRE
v5 EPOCH WALKS TO.

Mine, squarely. index.json is Lane E's file (write_index()). G's redhill_godverse landed in R24 (86e2985)
AFTER my last index run (5815dfb) and nobody re-rostered it. An addition isn't done when the cache is
written — it's done when the roster is regenerated. That is the exact mirror of my own R24 lesson ("a
retirement isn't done when the cache is deleted; it's done when the consumers are swept"): I wrote the
lesson for deletions and missed its reflection for additions.

WHY FOUR GREEN ROUNDS NEVER CAUGHT IT — a gate-shape lesson. Nothing was broken for the gates: selfcheck
enumerates web/assets/towns/*.json DIRECTLY (so it saw the town; A even pinned its goldens) and F's crate
smoke boots BY KEY (?town=redhill_godverse). The roster's only consumer is B's HUD selector (hud.js, my
R20 ledger #2 design). So the single symptom was that A PLAYER COULD NOT CHOOSE THE HEADLINE TOWN FROM THE
DROPDOWN — invisible to every automated check by construction. A gate that reads around the artifact under
test cannot test it: the vacuous-gate species, one layer out.
Fixed: re-ran write_index() -> 23 rostered, 23 on disk, 0 missing. Only index.json moved (every cache
byte-identical again). selfcheck ALL GREEN 156,212, golden 0x3fa36874 untouched. qa.sh --strict --matrix
7 passed / 0 failed / 0 warn.

-> F (#5, the tour): the money shot walks Musgrave Road into Monster Robot Party. If any tour frame reaches
that town THROUGH B's SELECTOR rather than by key, it could not have found it before this commit; by key it
always worked. Worth one glance at your framing path.
-> B: the dropdown now carries both godverse towns. Your `${t.state ? ', ' + t.state : ''}` handles their
empty state gracefully — nothing needed, and the defensive write is why this cost nothing cosmetically.
-> G: your godverse caches carry no `state`, so they roster as state:''. Harmless (B degrades cleanly). For
"Red Hill, QLD" in the picker, emit `state` — write_index() already prefers the cache's own field.

PROVENANCE v5-FINAL. The ⟨v5.0-FINAL⟩ rows are measured, not inherited — the town-pack row still claimed
v4's "22 towns / 1192 shops", stale since my R24 ballarat retirement and redhill build (now 21 real / 1196
shops / 299 heroes, + both godverse towns = 23 rostered). Added the two v5 art rows: the real-stock atlas
(1 crate, 120 items, Monster Robot's own POS, sku_ ids) and the mint atlases (14 crates, 224 items, seeded
from real dealgod listings, mint_ ids). These are the table's FIRST AMBER ROWS — everything before v5 was
green web-ok; real product photography is the first asset class this project ships that a human must clear
before public release.

I VERIFIED MY OWN PROSE AND IT CAUGHT ME: I first wrote the mint crates as "6 record · 6 book · 3 toy" —
that is the breakdown of all FIFTEEN crates, which includes Monster Robot's REAL record crate. The 14 mint
crates are 5 record · 6 book · 3 toy. A count attributed to the wrong population, one line from being
frozen into the release record. Every other claim in the table re-measured true (21/1196/299/8 states/23
rostered/roster==disk/72/37/120 items/224 items/both zones in-house-green).

THE LICENCE LINE'S STORY, recorded as a mechanism. The amber rows are guarded by exactly one printed line,
so the freeze says why it took two rounds to make honest: R23's glob matched 0 files and returned 0; R25's
permissive `or` fallback let the print go silent while the check still passed — the flag stopped reaching a
human on real product photos while the gate said OK. Now: one spelling, one lookup with one owner, and the
line is COUNTED (judged N => N lines, or FAIL). Both zones print — mint carries the same in-house-green
flag, because minting changes whose stock a crate CLAIMS to be, never whose photograph it IS. Frozen today
at: atlas-QA OK — 15 per-shop atlas(es) valid, 15 licence line(s) shown, 0 warning(s).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 13:59:49 +10:00
m3ultra
6960bdd279 Lane C R27 (v5.0): the tier-2 seam ruling + LANE_C_PUB v5-FROZEN (ledgers #2, #6)
SEAM RULING (§8): bless the direct wire — NO lifecycle hook. F already holds currentAdapter
(interior_mode.js:67) and passes it to dig.open() PER DIG (:111), so the live read lands, F
updates the pack, the next riffle picks it up; not-landed/slow/dead => the adapter is simply the
tier-1 pack => the dig never blocks (charter risk #1). No C lifecycle change.

BUT THE QUESTION UNDERNEATH IT IS C'S, AND THE OBVIOUS WIRING IS WRONG. pickRealOffers indexes
pack.items[(rr()*len)|0], so FILTERING THE ARRAY RESHUFFLES THE CRATE. Measured, 5 crates: one
record selling changed 21 OTHER records (6/2/2/6/5 collateral). Pick-then-omit (draw from the
stable full list, drop gone after) = 0 collateral: a crate with 3 sold shows 13, not a different
16. Selling one record must remove one record, not re-stock the shop.

THE TRAP: both forms hide the sold record — so F's planned assertion ("a real gone item never
renders") GOES GREEN ON THE WRONG WIRING. It cannot see the 21. -> F: assert on COLLATERAL (the
survivors are unchanged across a gone delta), not absence. Vacuous-gate law, third application,
and the cheapest to miss because it passes.

LANDED (dig.js): pack.gone (Set|array) omitted at PICK time. F's invariant published: update item
FIELDS in place (live price) freely; NEVER add/remove/reorder items[] — that identity+order IS the
seeded pick's stability (R25's positional-id lesson, one layer up).

DETERMINISM BOUNDARY sits exactly here: server down => byte-identical tier 1 (gate-able); server
up => the crate legitimately changes (tier 2 is non-deterministic BY DESIGN), so no gate may
assert dig determinism with the server up, and pack.gone never enters a seeded stream or golden.

SCOPED: the bin fan is decorative (a different seeded pick from the dig's offers) — a sold cover
may linger there until rebuild. That's when I'd publish a post-build hook; the epoch's claim
doesn't need it, because the crate you RIFFLE is true.

VERIFIED: pure-function measurement for the collateral claim, then end-to-end through the real
dig's public surface (pull -> Esc -> scroll -> pull): sold record gone, survivors 4/4, collateral
0, items[] untouched at 120, live in-place price shows on the next pull. (My first harness
returned the same title 4x — I never un-pulled — so its number was an artifact; re-ran it properly
rather than report a metric I'd just watched lie.)

DOCS FREEZE (§6): LANE_C_PUB is v5.0-FROZEN, whole document, with the case law at the top: three
amendments here exist because a rule of mine met a case written AFTER it, and both times the lane
building to my rule took the red. Header now states it: when a line meets a case it didn't
foresee, the line is the stale thing — amend it, don't bend the case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 13:53:02 +10:00
m3ultra
528829eeba Lane F R26 (v5.0-beta): the manifest consumed, the tolerance retired — tag HELD on the mint-id rule
EVERY CRATE IS DIFFERENT, and F measured it rather than taking G's 15/15 on trust — from the
indexes of record, not by entering one lucky shop: 15 keyed crates, 105 pairs, 0 sharing a
title; 0 crates overlap the generic v2 pack; 0 ids reused across crates (G's sku fix holds at
scale — the R24 vacuity dead at the source, not papered over in F's gate). 4 crates in Red Hill
+ 11 in Newtown = the manifest's 15 exactly, and the manifest lists nothing not on disk.

SOURCING, NOT TIER — C was right and the gate follows C. `tier` is the charter's ladder rung and
a mint atlas is ALSO rung 1: still a file, still offline, still deterministic. What differs is
where the stock came from. 15/15 indexes declare sourcing, every one agrees with the manifest,
a mint crate can never report as real, and the gate PRINTS it per room — provenance a human
never reads isn't doing anything (R24's licence lesson, one round on).

THE 404 TOLERANCE IS DELETED, NOT TUNED. R24 probed every keyed shop and ate a 404 per
atlas-less one; F's smoke could only cope by NAMING them, and a tolerance is a confession. F
filed the real fix as a contract ask rather than inventing it; G built the manifest; F now
consumes it — the shell asks for nothing unlisted. Zero 404s because nothing absent gets asked
for, not because the gate stopped looking. AND DELETING IT IMMEDIATELY CAUGHT A LEFTOVER: F had
wired the boot preload but left a second blind probe at the door, 404ing on every
keyed-but-unfetchable shop. While the gate said "8 probes, expected", a ninth was invisible too.
A named exception starts protecting new bugs the moment the real fix exists.

F's beta gate GREEN: distinctness · sourcing (real + mint rooms) · soft fall silent · ZERO 404s ·
0 console errors, no attribution exceptions. Selfcheck ALL GREEN 156,212/156,212.

TAG HELD — atlas-QA FAIL, 14 errors, and it is not the product. E's SLOT_ID_PREFIX = "sku_"
(validate_atlas.py:73) applies to every pack; E reads `sourcing` at :178 but the slot-id check is
sourcing-blind. All 14 mint crates fail; the real crate passes. A mint crate HAS no POS sku — it
was never in that shop's till — so the rule demands what cannot exist, the same shape as R24's
sweep demanding a cafe carry a godverseShopId.

F measured the rule's intent and it holds: mint_<dealgod listing id>, non-positional, sorted by
it, seeded bake, 0 ids reused across all 15 crates. Only the literal prefix fails. And G refused
to go green the easy way for the best reason — F's own R24 collision grown up: a POS sku and a
dealgod listing id are different id spaces, and filing one under `sku_` recreates that bug
INSIDE the economy, where tier-2's sold-means-gone looks up POS skus. R24's collision entered
the wrong shop; the same collision in the money layer sells the wrong record.

F did not fix E's one line: E's file, C's contract, C's call as its author (the principle Fable
ratified when C overruled `tier`) — and F is the party that benefits, since that line is the
only thing between F and the tag. Cost of waiting: one line. Cost of F being quietly wrong: a
gate that green-lights id-space collisions in the layer that moves money.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:38:44 +10:00
m3ultra
36d10ca4ae Lane G R26 (v5.0-beta): the mint baker, the crate menu, the atlas manifest (ledgers #2, #6)
EVERY CRATE DIFFERENT — measured: 15/15 keyed crates distinct, max shared titles between any two
= 0. 14 mint atlases (5 record, 6 book, 3 toy) + Monster Robot's real crate + the manifest.

MINT (ledger #2): the G3 note promoted — random.Random(shop_id) over an ID-ORDERED pool of real
dealgod listings. The shop id IS the seed, so two shops can never draw the same crate. No
TABLESAMPLE, no unseeded random: the two things that disqualified thriftgod's own mint() from
tier 1 (G3 §2). Re-mint + re-bake is byte-identical. Only keyed shops whose type the loader can
fetch get one (record/book/toy, C §7.1); the 13 keyed opshop/video shops get none and stay parody
— an atlas there could never load, and the manifest is what makes that silent instead of a 404.

MANIFEST (ledger #6, C §7.2d): stock_godverse/index.json — 15 shops, 1 real / 14 mint. Derived by
reading the atlases back off disk, so it cannot drift from them: the manifest IS the directory.
Real crate re-emitted with sourcing:"real" + C §7.2c's condition/sleeve_cond (my snapshot always
carried them; I dropped them at emit — that was the hole in C's price card). Atlas bytes unmoved.

THE ONE RED — mint ids vs E's SLOT_ID_PREFIX (E, one line). E asserts `sku_` on every atlas under
stock_godverse/; mint items have no POS sku and carry `mint_<dealgod listing id>`, so all 14 fail.
C §7.2a's RULE is satisfied — derive from the source's own stable key, never position, unique
across ALL packs (measured: 344 ids, 0 clash with the generic packs, 0 positional). What §7.2a
specifies as sku_<POS sku> it specifies "for a real-stock (godverse) pack"; mint is §7.2b's other
thing, written a round later, and the id form was never revisited.

I did not just emit `sku_` to go green: a POS sku and a dealgod listing id are DIFFERENT
NAMESPACES, and this round's own standing note says no code or gate may compare a bare number
across two id spaces — it exists because enterShop(31) entered the wrong shop. Putting both under
`sku_` recreates that bug inside the economy: tier-2's sold-means-gone looks up POS skus, and
sku_6031122 (a dealgod id) is indistinguishable by shape from a sku a POS must resolve. §7.2a's
own reason #2 is exactly about ids being looked up across snapshots. Fix: make the prefix
sourcing-aware (sku_ for real, mint_ for mint) — E's constant and error text are the only places.

THREE MORE FINDINGS, none blocking: [E] FITS_1024=64 cannot be satisfied — 1024²/256² = 16 cells,
so 64 items need 4 atlases and C caps a shop at 2; any 33–64 item pack MUST be 2048². Latent (my
packs are 16→1×1024² and 120→2×2048²); the honest bound is 32. [C/F] the ≤32 MB ceiling doesn't
hold at beta scale because the LRU it assumes hasn't shipped — F's boot preload loads EVERY keyed
shop's pack, measured 46.1 MB/town resident; it's why mint crates are 16 items on one 1024² sheet.
[C] "the crate menu, baked statically" can only be metadata: one base = one index = ≤2 atlases =
128 items, and Monster Robot has 357 crates / 24,646 records — so crate_menu ships the real crate
list (labels + counts) and per-crate STOCK needs a per-crate base, i.e. a C contract line.

MINT HONESTY: sourcing:"mint", an attribution that says "not this shop's stock", and NO POS-claim
field at all — structural, not editorial. Records require a real Discogs artist (dealgod's `brand`
on a record listing is the SELLER — the first bake had "Red Eye Records" as an artist; a shop is
not an act) and use discogs_master_title where present, so Egg Records reads "MC5 — High Time
$50", not "Pre Loved Record - Elton John - Breaking Hearts". Books/toys take `brand` per C's
author/brand convention — sometimes the maker, sometimes the listing store. Real, imperfectly
typed, and never claimed as that shop's.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 10:33:40 +10:00
m3ultra
2f4ab5912f Lane B R26 (v5.0-beta): the stocked shopfront reads from the footpath
Ledger #5 — B's polish pick. A stocked godverse shop now tells you it's
diggable before you reach the door: a crate of seeded spines under the shop
name, and a warm-lamp-over-crates room behind the glass.

Cost: +0 draws / +0 tris. The mark is painted into the chunk's EXISTING
sign-atlas cell; the window cue rides the EXISTING per-shop aTint attribute.
Nothing new is allocated or submitted.

The manifest is the authority, deliberately NOT the godverseShopId key: keyed
means "has a stock identity", the manifest means "a crate is actually here".
Marking keyed-but-unstocked shops would advertise a crate the shop hasn't got
— the street would lie. The mark does not leak tier: "you can dig here" is
equally true of real and mint; provenance belongs on C's price card and in E's
gates. (Second job for ledger #6's manifest, free.)

Measured — true A/B at one pose, manifest 200 vs 404:
  spine-marked sign cells   0 → 3 (18,768 exact-palette px)
  stocked window tint verts 0 → 36
  street_noon               65 draws / 115,502 tris → UNCHANGED
Stocked shopfront (Goulds Books, footpath): 85 draws / 144,730 tris — inside
street law (<=300 / <=200k). Cues agree with ground truth: 3 stocked shops
live → 3 marked cells, 9 stocked window quads.

Covenants re-proved (the prefetch is new code on the boot path), tested with
the manifest present on disk so a stray fetch would 200 and be unmissable:
  ?classic=1        0 keyed, 0 stock fetches, 0 errors  (zero-fetch covenant)
  default synthetic 0 keyed, 0 stock fetches, 0 errors
  manifest 404      18 keyed, fail-soft, 0 page errors

Three traps, self-caught: (1) a module-load fetch would have put a fetch delta
on ?classic=1 — restructured to a lazy reader + plan-driven prefetch, keyed
plans only; (2) the lazy trigger alone raced the first chunk build, so the
first stocked shop you approach built unmarked — prefetch moved to
createChunkManager, before any chunk builds; (3) the first "zero cost" was
VACUOUS (manifest never fetched, so nothing was applied) and the first pixel
detector reported 60 marked cells with no treatment at all — replaced with an
exact-palette signature that reads 0 in control. Vacuous-gate law applies to a
lane's own verification too. Corollary: force-cache serves a deleted file
(transferSize 0, status 200 while disk 404s) — poison the cache or you are
testing your own memory.

B consumes stock_godverse/index.json read-only and emits nothing into it; the
temp manifest used to prove this round was deleted — the directory is G's.
Shape-tolerant + fail-soft, so G's real emission needs no coordination with B.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 09:49:54 +10:00
m3ultra
4f0adf12d8 Lane C R26 (v5.0-beta): three contract lines + the dig price sticker (ledgers #1, #4, #6)
Wave 1 — contract lines published first; G and E build to them.

#1 THE BRIEF SAID `tier`. IT CAN'T BE (§7.2b). G's atlases already emit tier: 1 = the CHARTER'S
LADDER RUNG (0 parody / 1 static-real / 2 live), and `kind` is already the stock type. A mint atlas
is ALSO rung 1 — same mechanism (a statically baked per-shop atlas); only the data's origin differs.
Real-vs-mint is an orthogonal axis, not a rung — overloading `tier` puts two meanings in one name,
the same species as the plan-id/godverse-id collision just standing-noted, and as R25's positional
ids. RULING: top-level `sourcing: "real"|"mint"`, REQUIRED; `tier` stays the numeric rung. A mint
index MUST NOT carry POS-snapshot fields (the separation is the honesty). Gates read `sourcing`;
absent => FAIL.

#4 `condition` ISN'T IN THE INDEX (§7.2c) — the ledger assumed it was. The index carries
artist/title/price/price_band; G's SNAPSHOT has condition + sleeve_cond and drops them at emit, so
pickRealOffers mapped cond:'' and the card rendered dangling separators around a hole. That WAS the
"database row". Ruled optional index fields, emitted when the source has them; no invented grades on
mint items (a plausible-but-fictional grade is what `sourcing` exists to prevent).

#6 THE ATLAS MANIFEST (§7.2d): stock_godverse/index.json is the authority for which shops carry
atlases — no entry => no fetch => zero 404s, so the zero-console-errors law holds with no
attribution exception. Shape + both-ways consistency specified. No manifest + no atlases = a
legitimate silent zero-shop state, not an error.

THE PRICE STICKER (code): the pull panel is now the shop's price sticker — manila card, rotation +
shadow, typewriter caps, italic title, a stamped condition grade, and the round yellow $ sticker the
sleeve art already uses (the panel echoes dig.js's own canvas language instead of fighting it).
Fields compose only when present: a missing field never leaves a stray separator.

VERIFIED (fresh context, 5 card shapes, both star branches): real grail VG+/VG + ★GRAIL; real
standard VG+ + STANDARD; real ungraded COLLECTOR (grade omitted cleanly); parody NM + 1973 PUNK;
parody rare (seed 4) VG + 1973 POP + ★RARE. No dangling separators anywhere.

The verification caught a defect in MY OWN card: a real grail read "GRAIL ★ GRAIL" — `s` carried the
price_band AND `rare` derived from that same band (parody is immune: its `s` is a genre). Fixed at
the mapping. And I didn't leave the parody-rare branch on assumption — scanned seeds until a rare
pull appeared and asserted it says RARE, not GRAIL. An unexercised branch is an unproven one.

Budgets: the card is DOM — zero draws, zero tris, no 3D change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 09:38:42 +10:00
m3ultra
29942002eb Lane F R24 (v5.0-alpha): THE CRATE WALKS — the per-shop wire + a gate that can't lie
You can boot redhill_godverse, walk down Musgrave Road into Monster Robot Party, riffle its
own real crate and buy a real record. Proven falsifiably, not by eyeball:
  base      assets/stock_godverse/3962749/ (its own, not the town-wide)
  TITLES    120/120 the shop's atlas · 0/120 the generic pack
  TEXTURES  2 from stock_godverse/3962749/*.webp · 0 generic — the pixels' own file
  BUY       rec_0000 "Abstract Latin Lounge II (Part II)" @ $15 → cash 191→176, exact
  REBOOT    191/0 restored — gone-this-session, back next boot
Ladder: ?noassets → ZERO network requests · keyed-but-atlas-less shop → 404 → parody, live ·
newtown_real → base null, 350 items: the wire is a NO-OP off the godverse path.
flags_check GREEN (0 fails, 0 warns).

#6a THE WIRE: godverseBaseFor(shop), exported and used by BOTH the shell's boot preload and
the room's lookup — C's cache identity is the LITERAL (type, base) pair, so two sides building
that string differently would drop a real shop to parody, a bug indistinguishable from "no
stock" by eye. One function, one string, one key. Gated on stockReal, never the id alone.

#6b THE GATE: smoke_real_crate + DBG.stockInfo() — permanent, and it cannot pass without
touching its subject (SKIPs with a printed reason when the town/atlas is absent).

FINDING — THE BRIEF'S OWN HONEST-GATE SPEC WAS VACUOUS. It specified id equality. Both packs
number items POSITIONALLY (rec_0000…), so all 120 atlas ids are generic-pack ids too: an
id-equality gate goes GREEN on the generic pack — the exact failure the vacuous-gate law was
written to stop, reproduced inside its first application. Ids there are slot numbers, not
identity. Titles (0 overlap) and the texture URL discriminate; F asserts on those.

FINDING — THE ID SPACES COLLIDE, and it bit F's own selector inside the anti-vacuous gate.
Plan ids (1..N) and godverse ids (31, 767, 3962749) share a numeric space: Silky Oak's godverse
id is 31 and another shop's PLAN id is 31, so enterShop(31) silently entered "Wholefood Cafe"
and the soft-fall assertion PASSED ON AN UNKEYED CAFE. Fixed both ends: 'g:<n>' selects a
godverse id explicitly, a bare number stays the plan id and now REPORTS the collision, and the
smoke asserts it landed in the shop it asked for before asserting anything about it.

FINDING — F'S OWN GATE CRIED THE LOUDEST WOLF WE OWN. classic_regression reported "plan
fingerprint != golden 0x3fa36874 — determinism/prime-law broken" while the covenant was
provably intact. F wrote it in R16 as `hash_ok and returncode == 0` — two assertions, ONE
verdict, reported with the fingerprint's message — so any unrelated selfcheck red screamed that
the byte-identical-forever covenant had broken. Two assertions, two verdicts now. It isn't
enough to fail for a reason; you have to fail for YOUR reason.

FINDING — fail-soft-by-404 vs the 0-console-errors law. The boot preload must resolve a keyed
shop's pack before the door opens (getStockPack is sync), so it probes blind: 9 of Red Hill's
10 keyed shops have no atlas → 404 → parody. That IS fail-soft working, and it is also 8
console errors no .catch() can suppress. Fix is not to loosen the law but to stop probing for
what isn't there: an atlas index in G's namespace (or hasStock on the cache entry, A+G). Filed
as a contract ask, not invented. Until then the smoke counts and NAMES the probes and fails on
any other error — tolerance stated out loud.

Verified the lift is clean: cache 10 keyed → plan 9 keyed, every one a real secondhand shop.
No cafe keyed, zero duplicate ids — there is no mis-stocking.

F did NOT touch A's identity sweep or E's validator. F was the party that would benefit, and
changing a red gate to green in another lane's file to unblock F's own tag would retroactively
devalue every green F has ever reported. Filed instead — and R25 has since landed A's
reconciliation and the six pins, which is the right hands doing it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 08:43:29 +10:00
m3ultra
4314622c1b Lane G R25: sku-derived slot ids — the re-emit (ledger #3), index-only
Per C §7.2a: items[].id = "sku_<POS sku>" (e.g. sku_20260314070442), never positional. One line at
the emit — the snapshot already carried the sku, I was dropping it.

MEASURED: id overlap with the generic pack 0/120, was 120/120 (F's finding). 120/120 unique, all
sku_-prefixed, none left in the generic packs' rec_ namespace. Id equality discriminates again —
verified through the live loader, not just the file. Index-only as briefed: the two atlas .webp
files are sha-identical (bytes did not move), no town cache touched, no goldens moved. uv,
one-material-per-atlas batching, and shop-pack/town-pack coexistence (120/350) all still hold.

C's reason #2 is the one that outlives the gate: position is not identity. Sell one record out of
crate 550 and rec_0050 silently becomes a DIFFERENT record on the next bake — so a wallet
purchase, a saved dig, or above all tier-2's sold-means-gone would point at the wrong item. The
sku is the shop's own identity for that copy (release_id is the pressing; the sku is the copy). So
the positional ids were a latent correctness bug in the ratified §7 economy, not only a vacuous
gate. Fixed while there are two atlases to migrate instead of fifty.

Conflict #1 closed: E's R25 validator prints "LICENCE: ... FLAG BEFORE ANY PUBLIC/COMMERCIAL
RELEASE" against the top-level US `license` and counts it — atlas-QA OK, 1 licence line shown, 0
warnings. The flag guarding real product photos is unmissable. Nothing owed either way.

Scoped: committed by pathspec on main (G's first as a full lane). F's six staged files and E's
in-flight validate_atlas.py left exactly as their sessions have them.

-> F (your file, your call, not touched mid-flight): interior_mode.js:378's comment now reads
false — ids are no longer positional and no longer collide (0/120). Your gate stays canonical
regardless: a texture URL proves which file the GPU sampled, which id equality never could. Only
the rationale is stale; id equality is now available as a second discriminator if you want it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 02:28:44 +10:00
m3ultra
a493c0a13c Lane A round 25 (v5.0-alpha): the sweep reconciled with Ruling 2 + the six pins (ledger #1)
All 8 tree reds cleared. selfcheck ALL GREEN 156,211/156,211; scaffold + consistency green; classic
0x3fa36874 and gig 0xb1d48ea1 frozen. F: the tag is unblocked from my side, nothing of mine is pending.

SIX OF THE EIGHT REDS WERE MY OWN GATE ASSERTING RULING 2 AWAY. I built the R24 identity arm on an
assumption that was true when I wrote it and false the moment G shipped: that a godverse cache is ALL
census shops. Ruling 2 makes it MIXED -- a keyed GODVERSE layer plus an inherited OSM texture layer that
G measured to be load-bearing, not cosmetic (census-only Red Hill: 306 m spacing warn + a poster inside a
kerb). So newtown_godverse (18 keyed + 54 texture) and redhill_godverse (10 + 27) were HEALTHY TOWNS MY
GATE CALLED BROKEN -- it fired 54/72 on a good town. Keyed asserts now run PER-LAYER over the keyed subset
only; unkeyed texture shops raise nothing. The validator's "N/M missing" warn dies with it. The one honest
requirement left at that layer: a `godverse+osm` cache must have a NON-EMPTY godverse layer (else it's an
osm cache wearing the wrong `source`) -- still a warn, for the R24 charter reasons that still hold.

THE UNIQUENESS CHECK WAS BROKEN IN BOTH DIRECTIONS. `new Set(all ids).size === shops.length` collapses
every `undefined` into ONE Set entry, so it (a) failed structurally on any mixed cache -- 54 texture shops
became one entry -- and (b) could HIDE A REAL DUPLICATE behind that same collapse. Now over DEFINED ids
only. And per the vacuous-gate law I made it prove it bites rather than asserting that it does:
validateTownCache rejects duplicates at the front door, so a dup can never reach the plan that way -- the
test feeds one STRAIGHT TO THE LIFT (generatePlanOSM does not validate) and asserts the predicate catches
it, with a healthy mixed cache passing the same predicate. A check nobody can watch fail is not a check.

NEW -- THE ORPHANED-ATLAS GATE (my own R24 finding, now enforced instead of filed). The lift legitimately
drops shops (overlap-resolve, counted since R19). Dropping a shop that HAS a committed atlas means real
stock keyed to a shop that isn't in the town -- exactly the failure I filed in R24, and one F's #7b could
only catch in a browser at the end of a round. Now a node gate: for each godverse town, every
stock_godverse/<id>/ on disk belonging to that cache MUST be seated, else FAIL. Subject-aware -- it SKIPs
by name when a town has no atlas, rather than passing quietly.

It already found one, benign today: redhill's lift drops keyed shop 2286 "Empire Revival" (10 keyed in
cache -> 9 seated). No atlas, so nothing is orphaned and the gate passes -- but it prints, because a drop
must never be silent (the R19/R20 ruling). G: stocking Empire Revival at the beta would orphan it. Monster
Robot Party is seated (lot 8), which is the one that matters this round.

THE SIX PINS, cross-checked two ways before landing -- byte-identical across two fresh processes, AND
matching the three values G stated independently in 86e2985:
  newtown_godverse  base 0xcf69b387  gig 0x1e266f60   (moved by G's keyed re-emit)
  redhill_real      base 0x6046700f  gig 0x673785ee
  redhill_godverse  base 0xb2224939  gig 0xc6f80e18
No other golden moved -- the diff is exactly these six lines.

Two lines still print; both deliberate, neither pending:
  ⊘ SKIP newtown_godverse orphaned-atlas -- correct, the only committed atlas (3962749) keys to Red Hill.
  ⚠ redhill_godverse: 1 keyed shop dropped -- the honest disclosure above.

Committed strictly by pathspec: F's six staged files sit untouched, exactly as its session left them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 02:23:57 +10:00
m3ultra
86e298531e Lane G R24 (v5.0-alpha): the crate's real street — redhill_godverse, the keyed re-emit, and two contract conflicts
THE SHOP HAS A STREET. redhill_godverse: Monster Robot Party seated on Musgrave Road (verified —
lot 8, type record, godverseShopId 3962749), 37 shops on E's 884 real Red Hill roads. Its
coordinate is John-supplied (Google Maps place /g/11g6rlbbc0 -> -27.4553791, 153.0076244) because
it is derivable from nothing we hold: OSM doesn't know the shop, the census doesn't either,
dealgod's stores/store_entity rows are NULL lat/lng, recordgod has no address. Verified inside E's
bbox and on Musgrave Road's own geometry; my own estimate was ~120 m out.

RE-EMIT (ledger #5 + #2): atlas keyed by godverseShopId with US `license` throughout (British
retired, 0 occurrences) — atlas-QA OK, 120 real records, byte-identical re-bake (the .webp bytes
did not move; only the index). newtown_godverse re-emitted with ids (18 keyed). godverse_town.py:
psycopg2 -> psql, EXTRA_SHOPS roster, and Fable's R22 Ruling 2 finally implemented.

RULING 2 WAS LOAD-BEARING, NOT COSMETIC (measured): census-only Red Hill is unshippable —
9 shops = 306 m spacing warn; +Monster Robot = 10 shops = 261 m warn AND a frontage poster seated
INSIDE edge 1037's kerb (-2.95 m); + the donor's texture layer (37) = no warn, poster passes.
261 m is worse than the 255 m that retired ballarat this round: the alpha's headline town would
have shipped flagged "scattered, not a high street, or retire the town". 9 donor heroes swapped
for census entries (18 in Newtown), counted per the ruling.

CONFLICT #1 — C §7.3 vs E's validator. C says lift provenance to TOP LEVEL, US `license`, British
retired, "exactly what E's validator reads". Measured: it is not. validate_atlas.py:98 reads
NESTED `provenance`; :105 reads `licence` British-first. Lifting-and-retiring as written FAILS the
gate; my R23 atlas already passed it untouched. Same species as the bug that held the tag — a doc
asserting what code does without running it. Resolved: E's check accepts `licence or license`, so
US-nested passes; the four also ride at top level (C's contract + the town-cache convention) off
one source of truth. -> E, one line: :198 PRINTS `licence` British-only while the check accepts
both, so C's mandated US spelling silently stops printing the licence flag — which :199's own
comment calls a human call. Gate passes; evidence line vanished. Fix: .get("licence") or .get("license").

CONFLICT #2 — Ruling 2 vs A's identity gate. NEEDS A RULING; it is why the tree is red (6 of 8).
Ruling 2 makes a godverse cache mixed: a keyed GODVERSE layer + an inherited OSM texture layer.
A's sweep asserts EVERY shop is keyed -> partial FAILs. Texture shops carry no godverseShopId
deliberately: an OSM milkbar has no GODVERSE identity, and minting one from its OSM id pushes a
third id space into a field that already carries two — A's validator calls a duplicate
mis-stocking, charter risk #3's nightmare with Monster Robot's crate as the prize. And A's own two
checks disagree: the validator says "Missing = tier 0 (soft). Duplicate = mis-stocked (hard). They
are not the same failure", while the sweep fails partial keying because it "mis-stocks the rest" —
conflating exactly those two. Proposed (A's call, Fable's ruling): assert coverage over the
godverse layer, not the inherited texture layer.

THE 8 RED CHECKS, ITEMISED: newtown_godverse base+gig goldens (2) moved by the re-emit exactly as
ledger #2 intends — A re-pins, base 0xcf69b387 gig 0x1e266f60; godverse identity x3 per godverse
town (6) = conflict #2. Nothing else. Classic covenant 0x3fa36874 intact. redhill_godverse pins:
base 0xb2224939. Verified live: the shop's 120-record pack and the town-wide 350 pack now COEXIST
through C's type+base fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 01:31:07 +10:00
m3ultra
5815dfbd58 Lane E R24 (v5.0-alpha): the crate's real street, the honest gate, and Ballarat retired
THE STREET (ledger #3). redhill_real: Red Hill, Brisbane — 36 shops (9 heroes + 27 texture,
-29 subsampled), 884 roads, median NN 73 m. **Musgrave Road is in roads[] (41 ways, primary +
residential)** — that was the point: Monster Robot Party's real shop now has its real street.
One bounded Overpass fetch under the standing authorization; raw snapshots in _raw/, ODbL, C's
mapping. This is G's donor for godverse_town.py -> redhill_godverse.

TWO HAZARDS HANDED TO G/A, both measured against the real geometry (notes R24 §1):
(a) The shop is NOT in OSM — no shop=music node, no name match anywhere in the bbox (checked the
raw snapshot, not the emitted cache). It cannot arrive via the fetch; G must inject id 3962749
from the census or the town ships without the shop the release is about.
(b) THE SEATING HAZARD: A's lift seats on the NEAREST edge, and from G's geocode three streets
are nearer than the addressed one — Zig Zag Street 38.6 m (residential), Craig Street 46.1 m,
Musgrave Road 51.6 m. The shop would seat on Zig Zag St and the headline would quietly become
false. Measured fix (G's call): the point on the real Musgrave centreline nearest G's geocode is
-27.455169, 153.006902 — 0 m to Musgrave, next candidate 43 m. Snaps the street, does NOT verify
the house number; I have no address data for where #147 sits along the road.

THE HONEST GATE (ledger #4). F's catch was right and there were FOUR bugs: the glob used the
published-contract name the runtime can never load (0 matches -> returned 0: it passed identically
whether atlases were absent, misnamed, or perfect); the code read provenance top-level while my own
docstring said nested (G nested it correctly — the gate would have failed G's real artifact);
licence/license; and a stale ceiling. Rebuilt on the "runtime is the authority" ruling: globs
stock_godverse/<id>/stock_<type>_index.json, type in {record,book,toy}. Vacuous-gate law implemented
literally — 0 matches + stray files FAIL (listing them); 0 matches + empty dir prints
"atlas-QA SKIP: no atlases present (0 files matched glob ...)"; plus an id equality
(shop.godverse_id == dir) so it proves it touched its subject. Proved on four cases: empty -> loud
SKIP, misnamed (F's exact bug) -> FAIL, unparseable -> FAIL, G's real atlas -> PASS (120 items,
2 atlases, licence printed). My own test found a fifth hole — the glob still matched the old
stock_shop_* name, so the misnamed case failed only incidentally; added a STOCK_TYPES name check
so it fails for the RIGHT reason. A gate that fails for the wrong reason will pass for the wrong
reason later.

BALLARAT — RETIRED, counted, and a DIFFERENT illness from Toowoomba (notes R24 §3). Toowoomba was
dead everywhere. Ballarat is alive exactly where the game isn't: 103 POIs, densest 400 m disc = 47
of them (Toowoomba's was 3) — but that disc is cafes/clothes/bakeries while the op-shops sit 854 m,
1042 m and 1709 m out. Heroes and density don't coincide, so no bbox holds both. Real builds at
every span: 1.0 km -> 8 shops/184 m/hub 4-8 but ZERO op-shops (a thrift town with no thrift shop);
2.0 km -> 12/186 m/3-12; 3.0 km as shipped -> 20/255 m/4-20. Every row worse than any shipped town.
THE BINDING CONSTRAINT WAS MINE, NOT OSM'S: with 2 heroes the 3x texture cap keeps 6 of 47 texture
POIs and the subsample is spatially blind, so survivors scatter at any span — part of the 255 m A's
warn caught was my own cap's fingerprint. Seeding texture near heroes fixes the class but moves
every town's golden -> filed as a v5.x proposal, not done in a release round.

I OVERSTATED MY R23 ADVICE TO A: the hub fraction is NOT a standalone discriminator — glebe (shipped,
healthy) reads 13% and redhill 14%; a hub threshold would false-flag both. Median NN is the robust
primary; hub is only comparable at equal shop counts (toowoomba 2/12 vs darwin 7/12 was fair because
both had 12). The raw-vs-seated calibration point stands.

METHODOLOGY, recorded because it nearly shipped: I picked Ballarat's span from an offline simulation
that predicted 68 m / hub 5-8, and had already written those numbers into a config comment as fact.
The real build returned 184 m / 4-8 — same counts, different sample. Never trust a re-implementation
of the pipeline's own selection; run the pipeline.

-> A (batched pins): ADD REAL_TOWN_GOLDENS['redhill_real']=0x6046700f and
REAL_TOWN_GIG_GOLDENS['redhill_real']=0x673785ee (the headline town currently only WARNS as
UNPINNED — ungated until you pin it). REMOVE ballarat_real 0xf0a9e8a1 / 0xf097c331 — dead config by
your own R23 note.
-> F: tools/qa/tour_shots.py still shoots town=toowoomba_real, which I deleted in R23 — the v4 tour
breaks on a missing town. Your file, your call. A retirement isn't done when the cache is deleted;
it's done when the consumers are swept.
-> C: built to the runtime + G's real artifact per the ruling; LANE_C_PUB §7 line 271 still names the
contradictory stock_shop_<id>_index.json. I reconcile when your corrected contract lands.

Determinism receipt: the retirement forced a full 21-town rebuild from cached raw (no refetches) and
every existing cache came back byte-identical — only ballarat, redhill and index.json moved. Pack:
21 real towns · 1196 shops · 299 heroes (22 rostered with G's newtown_godverse). Selfcheck ALL GREEN
149,696, synthetic golden 0x3fa36874 unchanged. qa.sh --strict --matrix: 7 passed / 0 failed, MATRIX
GREEN 10x7.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 01:06:00 +10:00
m3ultra
1eb0b45bd0 Lane A round 24 (v5.0-alpha): the identity field — godverseShopId, published first (ledger #2)
The optional shop key that resolves `stock_godverse/<godverseShopId>/`. Schema STAYS v2 (optional field ⇒
every shipped cache still valid, the 21 osm caches untouched by construction). Published to
web/assets/towns/README.md — the doc G and E build to — plus CITY_SPEC. selfcheck ALL GREEN (+15 checks),
synthetic 0x3fa36874 frozen, NO golden moved.

THE BRIEF'S "THE POS SHOP ID IS THE ID — NO MAPPING TABLE" IS FALSE FOR THE ONE SHOP THIS ALPHA IS ABOUT.
G's own docstring says it: Monster Robot Party is NOT in thriftgod's census, so its id is its DEALGOD STORE
ID 3962749, while census shops use thriftgod ids (max 2992) -- two disjoint spaces, deliberately kept clear
of each other. Had I coded "godverseShopId == shop.id" or derived it from the census, the headline shop
could never be keyed. So it is an OPAQUE key: no derivation from `id`, no equality assert, no mapping table
(the R12 gigKey law -- one key, zero mapping; G emits, everyone reads).

THE FIELD HAD TO SURVIVE THE LIFT OR IT WAS DECORATION. plan_osm builds a FRESH shop object and copies
nothing unknown, and the runtime reads plan.shops[], never the cache -- so a cache-only field could never
reach F's per-shop base. It's now carried through, CONDITIONALLY: absent ⇒ the key isn't written ⇒
JSON.stringify byte-identical ⇒ every pinned golden holds until G re-emits (that re-emit IS the sanctioned
move). Proven end-to-end: a keyed cache puts `stock_godverse/3962749/` on the plan with census ids
(101..107) coexisting alongside it.

ARMS SPLIT BY HAZARD, NOT TIDINESS:
- malformed  -> ERROR. It names a path segment; "3962749" vs 3962749 is the same folder but different JSON,
  and that coercion drift is the exact species that broke C's atlas contract (licence/license).
- duplicate  -> ERROR. Two shops keyed to one atlas IS mis-stocking -- charter risk #3 forbids it by name.
- missing on a godverse cache -> WARN + fail-soft to tier 0.

RECORDED DEPARTURE (Fable's to overrule): ledger #2 says validateTownCache "requires" the field; I made
MISSING a warn. Three reasons. (1) The charter's determinism boundary is "world = seeded, frozen, gated;
stock = data tiers" -- an error inverts it, failing to load a TOWN because its STOCK identity is absent;
tier 0 must always boot. (2) Charter risk #3 names the remedy for identity gaps: "fail-soft to tier 0,
never mis-stocked" -- missing IS the soft case, duplicate is the hard one; they are different failures and
now get different arms. (3) Sequencing: newtown_godverse carries 0 ids today, it is G's to re-emit in wave
2 (their namespace, no census DB on m3), so a hard error would red the tree for C and E through all of wave
1 to say what the warn already says.
The requirement keeps its teeth where R23 taught us to put them -- the VACUOUS-GATE LAW: selfcheck FAILS on
partial keying (a half-keyed town silently mis-stocks the rest) and prints an explicit
"⊘ SKIP ... 0/18 shops carry godverseShopId. Subject absent ... binds the moment one id lands" at zero. It
names its subject, proves it touched it with a count, and cannot pass vacuously.

FILED FOR G BEFORE THEY START (measured in wave 1, so it costs them minutes not a wave): redhill_godverse
cannot contain Monster Robot from EITHER source. godverse_town.py takes roads from the OSM donor and shops
from the census, and the shop is in neither -- not in the census (G's R23 finding), and NOT in E's
redhill_real, which I checked the moment it landed: 36 shops, ZERO of type `record`, nothing matching
/monster|robot/. As written the adapter yields a Red Hill of census charity shops while the atlas keys to a
shop that isn't in the town -- F's #7b id-equality gate would fail at the end of the round. It must be
injected explicitly; the opaque-key design exists precisely to serve that case. Second trap on the same
path: redhill_godverse must still clear MIN_TOWN_SHOPS (6) from the census bbox or the cache is rejected
outright (hard error). E's donor is otherwise good: valid, no warns, 73.3 m median spacing.

HOUSEKEEPING: removed toowoomba's two stale pins -- E retired the cache in R23, and a golden for a town
that cannot load can never fire (the vacuous-gate law, one layer down). E's attempt also proved my R23
spacing metric is GAMEABLE: the re-bbox fixed the median (395.7 -> 89.4 m, "passes") while hub density fell
3/12 -> 2/12, the pack's worst. It is necessary, not sufficient -- D's hub test is the complement, and E
used both and refused to game it. Ballarat (255 m) is still flagged and still E's call; I pin what moves.

PINS NOT TAKEN YET, DELIBERATELY: redhill_real is untracked/in-flight (E still editing build_towns.py), and
redhill_godverse + the re-keyed newtown_godverse don't exist until wave 2. Pinning a moving file buys a
false green or a spurious red. The round's law says A pins these BATCHED -- that batch lands when E commits
and G's caches are in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 00:45:45 +10:00
m3ultra
ba901d4a75 Lane C R24: the contract fix — the runtime is the authority (ledger #1, the root cause)
F held the tag because my published atlas contract and my own loader were mutually
incompatible. That was mine. Closed, and published FIRST so G and E re-emit against it.

WHAT WAS WRONG: my R22 §7 invented `stock_shop_<godverseShopId>_index.json`; the loader
(stockpack.js:25) fetches `${base}stock_${type}_index.json`. An index named per the contract
can never be fetched by the code meant to load it. G built runtime-compatible (correct), E
built contract-compatible (also correct — the contract said so), and E's validator globbed
stock_shop_*_index.json -> zero files -> vacuous pass. Nobody was wrong; the contract was.

§7 REWRITTEN AGAINST THE CODE (LANE_C_PUB):
- Authority rule: stockpack.js IS the contract; doc vs loader disagreement = doc bug.
- Layout ratified as G shipped it: assets/stock_godverse/<godverseShopId>/stock_<type>_index.json
  (`type` is load-bearing — SLOT_FOR picks the slot). stock_shop_* RETIRED.
  -> E: the glob becomes stock_godverse/**/stock_*_index.json (the vacuous gate's actual cause).
- Runtime-read vs ignored stated exactly: reads atlases[] + items[{atlas,uv}] (uv top-left, the
  loader flips V); ignores version/atlas_px/cell*/count/kind/tier/shop/crate/provenance.
- Provenance drift dies: runtime reads none of it, so the authority is E's validator + the 23
  shipped town caches -> TOP-LEVEL `license` (US), attribution, generator, snapshot. British
  `licence` retired; G lifts+renames those four, keeps its rich nested provenance{} as colour.
  atlas_px stays REQUIRED (checked against real dims). cell* informational — C reads uv, never
  cell; do NOT shrink the cell for VRAM (the dig renders covers close-up).

CODE (F's filed item): stockpack cache identity is now `${base}|${type}`;
getStockPack(type, base = DEFAULT_STOCK_BASE); new opts.stockBase on buildInterior = the seam F
wires. Omitted => town-wide packs, byte-identical to today. Pre-v5 callers untouched.

VERIFIED FRESH — and I fixed my own metric first: R23's "8/8 atlas-backed" only checked that a
map exists, but a parody canvas has a map too (same species as the vacuous gate). Re-asserted
falsifiably: every sleeve's texture source IS stock_godverse/3962749/stock_record_atlas_00/01.webp,
pack items == index items by id; negative control — the parody room's textures are (canvas, no src)
and touch the atlas zero times, so the metric discriminates. Collision FIXED (shop 120 + town 350
coexist). Fail-soft FIXED with a populated cache (missing base -> null -> parody). 98 draws with
real covers, pathOK, 0 carves, 0 console errors.

SCOPED NOT SLID: the LRU+dispose (§7.6) lands at v5.0-beta — one stocked shop can't accrete, and
safe eviction needs a room-exit hook (a live room holds the pack's shared material) that arrives
with F's per-shop preload. Written into the contract so it can't slide silently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 00:43:50 +10:00
m3ultra
84f3641791 Lane G R23 (v5.0-alpha): THE FIRST REAL CRATE — 120 real records from a real crate + the G3 draft
godverse_stock.py splits at THE SNAPSHOT BOUNDARY: `snapshot` (runs where the DBs are; freezes
every source row + every cover's sha256) -> `pack` (pure: snapshot + bytes -> atlas, no DB, no
network). That split is what lets E's validate_atlas gate G's output on m3 without dealgod.
Artifact: web/assets/stock_godverse/3962749/ — crate 550 "DEEP HOUSE", 120 real records, 2
atlases (2048^2, 256px cells, E's contract verbatim). Byte-identical re-bake verified; resolves
through C's untouched stockAdapter (120 items, real titles/prices, one material per atlas =>
one draw); missing atlas -> null -> parody, zero console noise.

THE BRIEF'S PREMISE DIDN'T HOLD (measured): no Newtown record shop has stock in any database
(Egg Records / Papa Disquo / Haze Guitars / Vintage Record / Downtown Music: 0 items each).
dealgod.stores is not a census — 8,754 of 9,285 are Discogs seller accounts, zero Newtown.
thriftgod.item is a demo seed (2,221 items, 29 shops, all Brisbane/Newcastle charity, zero
record shops). mint() cannot produce tier 1: TABLESAMPLE SYSTEM (0.5) + unseeded random.* —
random.seed appears nowhere in server.py — and it assigns other sellers' listings to shops that
never owned them, voiding the licence law's "the stores' own product shots" green and making
write-back meaningless. Not risk #3's fuzzy matching: a population mismatch, nothing to match to.

What we shipped instead is truer: monsterrobot (147 Musgrave Rd, Red Hill, Brisbane — John's
ruling) is one real shop in three datasets — recordgod (its POS: 28,624 live vinyl, 24,914 in
357 real crates with real labels and slot numbers), monsterrobot.party (its own site: the covers
are the SHOP'S OWN product shots), dealgod store 3962749 (the cover cache + the godverse id;
clear of the census space, thriftgod max shop id = 2992). 99.3% of its crate stock joins to a
cached cover by Discogs release_id. Drops counted: 120 of 122 baked, 2 lacked an own photo.

John's R23 rulings recorded: the crate ships as the shop it really is (Red Hill, not Newtown);
real titles/artists at tier 1 — an amendment to the no-real-trademarks law build_stock_pack.py
enforces, same shape as the licence law (in-house green, flagged before anything public).

G3_ECONOMY_DESIGN.md drafts the API surface, async enrichment (the dig never blocks), failure
modes, identity, the PII fence (recordgod holds real customer/staff/sales — pipeline reads only
inventory/crate/disc_cache), and frames the write-back question for John (§7) against a real
trading shop with Square sync and an existing hold_expires_at primitive. No default, per law #4.

Asks in G-progress (both outside G's namespace, both gate the crate reaching a room): per-shop
packs aren't wired (stockpack.js caches by type alone — confirmed live: a base override is
silently ignored, so two stocked shops collide; C owns the wording, G re-emits), and redhill_real
doesn't exist (needs E's build_towns.py + one Overpass fetch; G touched neither).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:27:28 +10:00
m3ultra
84e0a1b764 Lane E R23 (v5.0-alpha): the atlas validator + toowoomba retired (ledger #4)
1. validate_atlas (the G2a format gate). pipeline/validate_atlas.py, wired into validate_manifest so it
   runs in qa gate 3. Judges Lane G's tier-1 atlases from the COMMITTED FILES ALONE -- no dealgod DB, no
   network. No atlases yet => clean pass, so it's in place before G's lands. Enforces: provenance
   {license, attribution, generator, snapshot} (charter law #3 + determinism); NO private-individual item
   fields (law #3); 1 atlas/shop hard cap 2 (C §7.1); <=1024², 2048² only for a 60+ item shop (C §7.2);
   declared atlas_px == the atlas's REAL pixels + every listed atlas exists; schema/UV/bands/dup-ids
   (C §7.3). The licence string is PRINTED, not pattern-matched -- clearing photos for public release is
   a human call, so the gate surfaces it. Dependency-free PNG/WebP header parser. Tested against a
   10-case matrix (real 2048² WebP + 1024² PNG): good passes clean, all 9 violations caught.

2. toowoomba RETIRED (my call, counted). Tried the re-bbox FIRST: 3.0km CBD-wide -> 1.6km on the Ruthven
   St heart. It fixed the named metric (median NN 395.7 -> 89.4m raw, 'passes') but made the real thing
   WORSE: hub density 3/12 -> 2/12 within 160m, the pack's worst (D's alive-darwin is 7/12). Its shops
   are PAIRS strung along a road, not a high street; densest 300m cluster is 3 shops (< MIN_TOWN_SHOPS),
   so no tighter box exists. Shipping it would have gamed the number while leaving a town nobody shops in
   (D: 0 finds / 1417 checks). Config entry kept commented with the rationale. Pack: 21 real + 1 godverse
   = 22 rostered, 1180 shops, all 8 states/territories (QLD keeps westend). selfcheck ALL GREEN 152015.

-> Lane A, before you freeze the spacing warn (#5): (a) your validator sees the CACHE (raw lat/lon) but
   D's numbers are SEATED (post-lift) -- darwin is 27m seated vs 68.3m RAW, so a threshold picked off D's
   table would FALSE-WARN darwin; calibrate on the raw spread (daylesford 11.6 ... braddon 119.2,
   ballarat 254.6 -- a ~200m line has daylight). (b) median NN alone is GAMEABLE: my re-bbox improved it
   4.4x while the town got worse -- the hub fraction is the discriminator, and my raw hub metric
   reproduces D's darwin exactly (7/12), so it's directly encodable (alive ~38-75%, dead <=20%).
   (c) ballarat is a SECOND spread town D's two-town comparison missed (NN 254.6m, hub 4/20 = 20%) -- it
   will trip your warn, correctly. Not retired: the ledger named toowoomba only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:14:00 +10:00
m3ultra
47f05ecaa8 Lane D R23 (v5.0-alpha): the GIG_RANGE chunk-neighbour fix — scoped to the gig path (ledger #6)
My carried v4.x finding, fixed post-release as scheduled. Runtime-only: no plan, no
golden, no flag, no fetch. selfcheck ALL GREEN 161300/161300, 0x3fa36874 frozen.

THE FINDING GREW WHILE IT WAITED: filed at 8.7% (measured at katoomba's isolated pub);
A's R21 cluster bias made it WORSE — venues now sit inside the retail cluster where peds
converge from every side, so 42.6% of in-gig-range peds (5094/11971) were chunk-blind.

THE OVERRIDE (measurement wins): the brief asked for "extend to chunk + 8 neighbours"
AND "byte-identical flags-off". I built the literal version and measured that those
cannot both hold: on the synthetic town (what ?classic=1 boots, gig layer absent) a full
3x3 scan sourced 127 of 855 finds (14.9%) from neighbour chunks — finds v2 never made.
The frozen v2 crowd would shop ~15% more. Covenant breach, in a clause of the same brief.

So the fix is scoped to the GIG path — which is what I actually filed:
- ordinary shops: own chunk only (v2 semantics, frozen — noticed from its own block)
- gig venues: the full 34m radius, honest across chunk edges ("follow the sound" is the
  whole reason GIG_RANGE 34 > PATRON_RANGE 18)
- no gig on -> _gigVenues empty -> neighbour loop skipped entirely -> ?classic and every
  flags-off boot take the IDENTICAL code path and cost to v2. Byte-identical BY
  CONSTRUCTION, not by measurement luck.
Both ranges < CHUNK(64) so 3x3 is exact, not approximate; fixed dz/dx order keeps ties
deterministic as the old single-list scan was.

BEFORE -> AFTER: cross-chunk in-range peds seeing the gig 0% (structural: v2 scanned only
the ped's own chunk) -> 100% (katoomba 4/4, fitzroy 11/11). Same-chunk unchanged 100%.
Classic neighbour-sourced finds: 0 (127 under the rejected full scan). Determinism
identical. 0 NaN on katoomba/fitzroy/synthetic. Sim 0.056 -> 0.057 ms/frame (+2%, i.e.
0.006% of a 16.7ms budget); lookup 0.58us unchanged with no gig, 1.3-2.7us with a gig on
(fires per PATRON_STRIDE, not per frame). Fitzroy clean at 376 peds.

CARRIED, documented: PATRON_RANGE keeps v2's own chunk-blindness — fixing it costs the
classic covenant, and the covenant wins. A frozen v2 quirk now, not an oversight.
Known minor: a scheduled-but-closed gig still runs the loop for nothing (0.58->1.3us).

D->F: no blocker for v5.0-alpha; classic untouched by construction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:06:07 +10:00
m3ultra
292b07aa91 Lane A round 23 (v5.0-alpha): the spacing warn — D's thin-tail finding as law (ledger #5)
validateTownCache now warns when medianShopSpacing(cache) > MAX_MEDIAN_SPACING_M (150 m). Metric +
threshold exported from the barrel so no lane re-derives them. WARN, NEVER ERROR: a flagged cache still
boots a valid district (toowoomba shipped green through the entire v4.0 pack) — E curates, A flags.
selfcheck ALL GREEN 161,372/161,372 (+72); synthetic 0x3fa36874 frozen; NO golden moved (only E's
toowoomba re-bbox may move one this round, per the round's law).

THE THRESHOLD IS MEASURED, NOT PICKED. The brief offered darwin 27 m / toowoomba 388 m as "plenty of
daylight for a line" — but that's 2 points. Measuring all 23 towns shows a near-continuum, and the line
is FORCED into (119.3, 254.9]: braddon at 119.3 m is ALIVE by D's own hub test (7 shops within 160 m,
identical to darwin's 7), ballarat at 254.9 m is not. 150 m sits in the pack's widest gap (x2.14), with
1.26x margin below and 1.70x above. Flags 2 of 23.

TWO TOWNS FLAG, NOT ONE. The brief names only toowoomba (D spot-checked the two 12-shop towns). The
measurement adds BALLARAT at 255 m — nobody has looked at it, and it's independently one of the three
towns my R22 graded cluster fallback fired on (no venue candidate at the >=3-shops/160 m floor). Two
signals agree. Filed for E as a curation call, counted either way.

THE BRIEF'S ANCHORS WERE IN THE WRONG SPACE, AND IT MATTERS. D's 27 m is PLAN space (post-lift metres);
validateTownCache is CACHE space (raw lat/lon — the only thing that exists at ingest, and the layer where
a bad bbox must be caught). Darwin is 68.3 m in cache space, not 27. Interpolating a threshold between
D's figures would have silently mixed spaces. I verified the hypothesis before trusting it: computing the
metric plan-side reproduces D's numbers exactly (darwin 27.2 vs 27, toowoomba 386.8 vs 388, hubs 7 and 3).

Cache space is correct HERE and provably safe: the lift marches shops at a regularised cadence, so it
COMPRESSES dense towns (darwin plan/cache 0.40) but not sparse ones (toowoomba 0.98, ballarat 1.01) --
the error lives at the dense end, the warn only fires at the sparse end. Verified all 23 towns in both
spaces: exactly ONE disagrees, newtown_godverse (94.4 cache passes / 158.3 plan would warn). Filed for
G/Fable, NOT acted on: no cache-space line catches it without false-positiving braddon, and godverse is a
census subset (18 thriftgod shops over the footprint that carries 72 OSM shops) so its sparsity is
coverage, not a bad bbox — re-bboxing, the warn's only remedy, cannot fix it. Worth knowing since R23
stocks the real crate in that town and the beta asks "fitzroy_godverse if the census is dense there".

Also fixed en route: the R17 silent-fallback trap bit again in my own scratch harness — an unregistered
town key resolves to the melbourne fixture rather than erroring, so five towns silently measured
identical. Registered the caches; noting it because it has now cost two rounds.

Coverage: sparse cache warns + still boots (structural + district suites on a flagged town), compact
cache does NOT warn (no false positive), metric edge cases (< 2 shops -> null, coincident -> 0, no throw
on empty), and an exact-value check (a 100 m pair measures 100 m, projection sane).
Cost: ~1 ms/town at registration (25.6 ms for all 23 incl. fitzroy's 160 shops) vs a <100 ms plan budget.

E -> use the warn as your acceptance test for #4: re-bbox, re-run, warn goes silent = the town has a high
street. If your fix moves toowoomba's or ballarat's cache, ping me — goldens are mine to re-pin, and only
what you move.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:04:43 +10:00
m3ultra
8ac3b18b36 Lane F R22 (v4.0 — THE EPOCH CLOSE): the re-measure, the selector, the release tour, the tag
The blocking gate is CLOSED, and the epoch closes green.

- #1b THE BLOCKING RE-MEASURE: F's R21 re-measure made the tri diet blocking; B diagnosed layer-by-layer,
  the driver traced A -> E (A's own commit: "B's numbers say the fix is E's"), E fixed it, F re-measured:
  katoomba venue_night 221,935 (+11%) -> 108,365 (-51%); bendigo 201k -> 124,682; fremantle -> 88,397.
  Worst 124,682 — the 200k stress edge is closed. The measure-first loop worked end to end.
- #3 DBG.enterShop(selector) (Lane G's ask): id · registry type · exact name · name substring, resolved
  most-specific-first so an id-shaped string can't be shadowed. One-liner QA on any of 23 towns.
- #4 The release tour -> docs/shots/release_v4/: the Fremantle hero · the Fitzroy mecca · the Toowoomba thin
  tail · the synthetic control · the ?classic=1 covenant. Every real-town frame poses through F's R21
  cluster primitive; B's R22 bookmarks anchor on the same retail heart, so tour and bookmarks agree by
  construction. HUD hidden throughout (F's R21 ruling corollary).
  The primitive earned itself twice: the first cut posed via street_noon and the MECCA CAME OUT AS BARE
  BITUMEN — the same trap as R21. Re-posed through the cluster, Fitzroy reads.
- HONEST FINDING (filed v4.x): the brief asked for the thin tail as "proof the floor holds". It does not,
  and the frame says so — Toowoomba reads as an empty road. The floor is a RATIO, not a count: 0.008
  shops/edge vs the heroes' 0.06-0.08. Shipped labelled honestly rather than swapped for a flattering town.
- #6 Docs: README v4 section (the towns ARE the product), LANE_F_NOTES §22, F-progress.

qa.sh --strict --matrix GREEN 7/7; MATRIX GREEN — 10 towns × 7 gates (the budget gate green everywhere for
the first time); selfcheck 161,300/161,300 (A's 36 goldens + the 23-town pack).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:32:32 +10:00
m3ultra
d81e499194 Lane E R22 (v4.0): the venue_night tri diet — B's #1a driver was mine, fixed (BLOCKING #1b)
B's diagnosis nailed it: 149,161 of 163,015 tris (91.5%) at katoomba venue_night were four of my GLB
street props. Buildings 348, posters 222 (A's cap worked, never the lever), pools 0. B's sharpest point:
it is NOT the density widening -- road density drives the bench/bin/shelter cadence (~100 props on a
966-edge real graph).

Fix (collapse-decimate via the R13 instrument tool; originals kept as _hi):
  bench       1942 -> 500   rendered 60,202 -> 15,500
  bus_shelter 7998 -> 2500  rendered 55,986 -> 17,500
  bin         3000 -> 800   rendered 18,000 ->  4,800
  food_cart   4991 -> 1000  rendered 14,973 ->  3,000
  furniture total 149,161 -> 40,800 (-108,361)
Projected view ~54.7k (B's 163,015 baseline) / ~113.6k (vs F's 221,935) -- PASSES the 200k gate either
way with 86-145k spare. F: these are projections off B's per-instance attribution; yours is the real
measure. -> F: RE-MEASURE.

Eyeballed every prop; two needed re-cutting: bus_shelter @1000 shredded (thin roof plate on a
voxel-remeshed shell) -> @2500 clean; bin @400 creased -> @800 clean. food_cart's black base slab is in
the SOURCE model (confirmed against the pre-diet thumb from git), not a decimation artifact.

Zero blast radius: dims/footprints/heights identical -> manifest.json byte-identical -> B's placement and
A's goldens untouched. Published 4 diet + 4 _hi archives to the depot (John re-authorized explicitly;
GLBs are git-ignored so the depot IS the archive).

-> Lane B (your 2nd note, cause found, NOT fixed by design): the MeshPhysicalMaterial on bench+food_cart
   is KHR_materials_specular in the glTF, and it survives a Blender re-export. Fix = neutralise specular
   pre-export. Deliberately deferred to v4.x: the gate is tris (cleared), and changing shipped shading in
   a release round without a visual re-verify is risk for no gate benefit. Same list: food_cart is 3.1MB
   on the depot -- 28 textures now dominate (tris are 1000); a texture-merge item, not a tri item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:04:56 +10:00
m3ultra
af8a6db020 Lane B round 22 (v4.0): #3 per-town bookmarks — anchor on the retail heart (Lane G's filed bug) + F's primitive
ROOT CAUSE: every "nearest" resolver in dbg.js sorted by distance from the WORLD ORIGIN. That's the town
centre only on a synthetic plan -- a real OSM town is projected about its cache's bbox centre while its shops
cluster hundreds of metres away, so bookmarks teleported into arbitrary far-flung geometry, exactly as G
reported. Measured origin-pick distance from the retail heart: katoomba 408m, newtown 626m, fremantle 371m.

FIX: resolve bookmarks about the town's DENSEST SHOP CLUSTER (grid-bin shop lots at 120m; heaviest bin's
centroid = the retail heart) instead of the origin -- byDist, lotsByDist, streetViewPose, stopPose, and
crossroadsPose's tie-break.

GATED on the REAL-ROADS signal (edges > 200) -- the same primitive as the R20 tram fence -- so synthetic and
the marched fixtures keep their exact origin-centred behaviour and F's release-tour control shot cannot move.
The gate is load-bearing, not cosmetic: synthetic's anchor is only 117m out but it DOES re-pick (Anglibarn Op
Shop -> Dusty Pages), so an unconditional switch would have silently moved the control. Same reason the new
crossroadsPose tie-break is gated (a degree tie would otherwise resolve differently on synthetic).

Verified across the town set: synthetic(22 edges)/melbourne(15)/katoomba-fixture(15)/silverton(1) -> origin,
UNCHANGED; newtown_godverse(1626) -> anchor(98,-629); katoomba_real(993) -> anchor(-227,-625). G's own town
is fixed.

Result on katoomba: shopfront bookmarks went from ~408m adrift to <=42m of the retail heart (arcade 7m,
milkbar_dusk/patronage_door/shopfront_detail 24m, market_square 26m, dig_real 42m); strip views ~195m on the
high street; venue_night/queue_night ~345m (A's venue placement, not the bookmark). All 19 resolve, 0 errors;
synthetic 19/19 unchanged. warehouse_fringe sits 3,074m out -- correct by design (it's the far:true fringe
shot; on a 5km town the fringe genuinely is 3km away).

-> F (ledger #4, the shared posing primitive): published on the harness as DBG.townAnchor {x,z,n,anchored,ref}
   (the retail heart + whether it's in use) and DBG.clusterPose(kinds) (stand on the road at the densest
   cluster, look along it). Your cluster-pose finding as a dbg.js-consumable -- the tour and the bookmarks now
   resolve through the SAME primitive, so a tour shot and its bookmark can't drift apart.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 22:01:41 +10:00
m3ultra
3face97046 Lane A round 22: absorb the town pack — 23 towns, 36 goldens pinned in one commit (v4.0, ledger #2)
E's 17 new towns + Lane G's newtown_godverse fed through the lift. ONE batched golden commit as
briefed: REAL_TOWN_GOLDENS + REAL_TOWN_GIG_GOLDENS go 5 -> 23 towns each, zero unpinned.

THE HEADLINE: everything built this epoch held at 23-town scale, FIRST TRY. 1,210 shops -> 1,133 seated
(77 dropped, 6.4%, all counted by cause); 1 CONNECTED COMPONENT and 3 VENUES on every one of the 23 towns.
fitzroy — 160 shops, 2x anything absorbed before — landed 139 seated, 1 component, 3 venues, 212 posters,
all invariants green. The junction-protected DP, fragmentation ruling, cluster bias, poster cap and
capacity fence needed NO new hardening: the pack needed absorbing, not fixing.

- Graded cluster fallback (the one refinement). Three towns have no candidate at the floor at all
  (ballarat/toowoomba/newtown_godverse top out at 2 shops within 160m); R21's bias switched off entirely
  there, stranding venues at 0. It now falls back to the DENSEST AVAILABLE — ballarat 0,2,0 -> 2,2,2,
  godverse 0,1,1 -> 2,2,2, toowoomba 1,0,0 -> 1,2,1. Fires only where the floor is unreachable, so NO
  already-pinned town moved (verified). Acceptance at pack scale: 20 of 23 towns have every venue >=3;
  the three above sit at their town's genuine ceiling — the carved-out case, stated explicitly.
- Drop outliers, counted not hidden: daylesford 19% (32 shops on a 171-road graph, the thinnest in the
  pack, all overflow), fitzroy 13%. RGAP is already 0.5m and NODE_CLEAR 3m; the only lever left is
  spilling overflow onto a DIFFERENT street, which buys a few percent by putting a shop on a road it
  isn't on. Same ruling as R20: drop and count beats teleport.
- selfcheck ALL GREEN 161,300/161,300; scaffold + consistency GREEN; cross-process deterministic
  (pack-xor 0xca140954). classic 0x3fa36874 / gig 0xb1d48ea1 / marched fixtures FROZEN.

Handshake -> C + D + F: the pack is in, 23 towns pinned, start your verifies. Tri diet (ledger #1): if
B's layer-by-layer names plan geometry as the venue_night driver, I own the fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:55:05 +10:00
m3ultra
a7289d0550 Lane E R22 (v4.0): MODELBEAST notes refresh + provenance v4-final + G2a atlas review
Ledger #3 (E's G item), #6 (provenance prep), + the C/E contract review.

- MODELBEAST notes (#3): pipeline/README.md's toolchain row claimed sf3d/trellis_mac were 'HF-gated
  (setup needed)' -- ultra was right, that was stale (weights cached; trellis_mac 15/15 on thriftgod
  Tier-1; the :8777 queue also runs bg_remove_local/mflux_image_edit/seedvr2_upscale). Corrected.
  Ultra's finish-farm post-mortem folded into the props section VERBATIM + credited, with Fable's
  Ruling 1 amendment (NO-DRACO: drop --compress draco, rest of the command stands). Noted that our
  bake_lowpoly.py / decimate_props.py are NOT the finish farm, so nobody conflates them.
- Provenance v4-FINAL (#6): the frozen table carries the pack (22 towns, all 8 states/territories,
  1192 shops + roads[], ODbL, raw snapshots) + a row for Lane G's newtown_godverse attributed to G.
  The licence spine is complete -- nothing shipped is unaccounted.
- BUG: index.json still listed 22 -- generated before the dd4489c merge, so newtown_godverse was
  invisible to B's selector while R22 verifies at 23-town scale. Regenerated -> 23 towns (selfcheck
  ALL GREEN 161300/161300). Index is now self-describing: state reads from the cache first, then my
  config, so any lane's town rosters itself.
- G2a atlas contract review (E's half; C answers interior ceilings in LANE_C_PUB): Fable's priors all
  hold. Atlas-per-shop is an UPGRADE if the loader disposes on room exit -- today stockpack.js never
  disposes (R9: 181MB resident, accreting). Without dispose, per-shop strands ~16MB/shop (~190MB per
  town visited, unbounded across 23 towns). With dispose: ~4MB resident at 1024², ~45x better than
  today. Also: size the atlas to the shop (<=1024², not 2048² for a 6-item shop); reuse my index
  schema verbatim so stockpack.js/fail-soft-to-parody/?noassets/validate_pack all work unchanged;
  the R8 parody law (parodied metadata, real cover art) is unchanged.

-> Lane G: add "state":"NSW" to newtown_godverse.json and the index picks it up automatically.
-> Lane C: the R9 dispose-on-exit cache-cap is now load-bearing for G2a (my VRAM numbers above).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 21:54:49 +10:00
m3ultra
dd4489c70e Fable (integrator): merge Lane G R1 at the v4.0-beta boundary — godverse adapter + newtown_godverse (per FABLE_TO_LANE_G ruling)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 21:42:04 +10:00
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
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
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
type-two
223fbcaf72 Lane G (GODVERSE, ultra) R1: real-shop census adapter — 18 real Newtown shops on the real road graph
godverse_town.py marries a donor OSM cache's roads[] with thriftgod's DealGod-scraped
shop census (2,928 real AU secondhand shops) -> <town>_godverse.json, schema v2 unchanged.
First artifact newtown_godverse boots clean (?plansrc=osm&town=newtown_godverse).
Lane brief + asks (Draco ruling, per-town bookmarks, enterShop selector) in
docs/LANES/LANE_G_GODVERSE.md + G-progress.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 20:19:14 +10:00
m3ultra
5d29863b78 Lane A round 20: absorb E's density widening — capacity, pub facade bias, goldens pinned (ledger #2)
E's five caches landed at 3-6x shops (292 total: katoomba 20→80, fremantle 21→80, newtown 18→72,
bendigo 9→36, castlemaine 6→24). All five absorb cleanly and still place 3 venues; the R20 poster cap
auto-scaled off the live shop count exactly as designed (katoomba 111 posters at 80 shops).

- CAPACITY WIDENED (the R18 overflow fence, load-tested). At 4x the dominant drop cause was OVERFLOW —
  an edge-side holding more shops than fit (katoomba 10 of 11 drops). Tightened the run: NODE_CLEAR 6→3
  and a ROADS-ONLY RGAP 2→0.5 (the shared marched GAP is untouched ⇒ marched fixtures stay frozen).
  Drops 7.9% → 5.5% (16/292). 0.5m also reads truer — a real AU main street is continuous terrace
  shopfronts, not detached boxes. Stopped there deliberately: the next lever (spilling overflow onto a
  DIFFERENT street) buys ~1% by putting a shop on a road it isn't on — dropping a crowded shop is the
  honest trade. Residual drops stay COUNTED, now BY CAUSE (dropped_overflow/_overlap/_stranded).
- VENUE FACADE BIAS NOW COVERS pub. R16 exempted pub ('spine-fronted, +Z always open') — true on the
  synthetic/marched towns, but on a REAL graph at density the pub landed where its frontage poster
  overhung a cross street (newtown, -0.91m). The POSTER_CLEAR filter now covers every venue kind; still a
  NO-OP on synthetic (every pub candidate already clears) ⇒ gig golden 0xb1d48ea1 frozen.
- Goldens re-pinned ONCE (base + gig, all five towns). classic 0x3fa36874 / gig 0xb1d48ea1 / marched
  fixtures FROZEN. selfcheck ALL GREEN 51866/51866; scaffold + consistency GREEN; cross-process
  deterministic.
- Fixed: my real-cache loader globbed *.json and tried to validate E's new index.json as a town cache —
  it now skips it (that's B's selector index, not a cache).

Handshake → all: densities absorbed, goldens pinned. → F: re-measure venue_night + gate the five towns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 20:05:11 +10:00
m3ultra
94e56ed5fa Lane B round 20 (v4.0-beta): the tram ruling — route by shop adjacency + per-town fence (ledger #3/#4)
Verified fresh Chromium across 9 town configs (synthetic, 3 fixtures, 5 real).

TRAM RULING (ledger #3): spinePolyline now walks from each main-subgraph dead-end, greedily taking the
unused main edge fronting the most shops (lot.frontEdge), keeping the best-scoring path (ties -> longer).
SYNTHETIC + FIXTURES BYTE-IDENTICAL by construction AND measurement (a synthetic main node has <=2 mains so
there's never a choice; its two dead-ends tie exactly and strict > keeps the pre-R20 start). Old vs new
logic on the same plan = identical polylines (Boolarra: 7 pts, 6 edges, 810m, 172 shops, 2 stops).

The alpha tram fronted 0 shops on 4 of 5 real towns (it was a highway bus). New: katoomba 0->3, newtown
0->8, fremantle 0->2, bendigo 0->1, castlemaine 1->6. Where the best main chain still fronts <5 shops the
tram is FENCED per-town (Fable's fallback). RUNS: synthetic, all fixtures, newtown (8 shops/1924m/16 stops),
castlemaine (6/2184m/10 stops). FENCED: katoomba (3), fremantle (2), bendigo (1) -- highway, not high street.
The fence keys off the REAL-ROADS signal (edges>200), NEVER shop count alone: the marched fixtures front 0
shops on their mains (bare spine, avenues carry shops) so a naive fence would have killed their v2 tram.
routeInfo{fenced,reason,shopsFronted,routeMetres} exposed for F's smoke.

BUG FOUND+FIXED: the stop projection accepted every shelter in the town with no distance gate -- harmless on
synthetic (2 shelters on the spine), nonsense on real graphs: Newtown made 149 phantom stops (~9 min of dwell
at points the tram never passes). Added a 30m gate (a shelter sits halfRoad+1.7 <=~16m off its centreline, so
genuine stops survive): newtown 149->16, castlemaine 37->10; synthetic 2 / fixtures 3 unchanged.

GROUND POLISH (ledger #4): measured, NO fix needed. Real Katoomba has 325 deg-3+ junctions, 28 under 30 deg,
worst 4.3 deg (near-parallel). At grazing eye level the worst reads clean -- no z-fight, no gaps. Layers are
already y-separated (road 0.0/foot 0.02/kerb 0.06) and road-on-road overlap is invisible by design (OVERLAP=1.5
overruns nodes on purpose; one skin, one y, one merged draw on uniform asphalt). Cosmetic only: footpath/kerb
double up on the sliver between <10deg near-parallel roads -- v4.0 candidate, not a defect.

Selector polish (ledger #5): BLOCKED -- E's towns/index.json not landed (build_towns.py WIP); REAL_TOWNS
hardcode stands, one-line swap when E lands.

-> A (finding, measured): only a slice of shops front a MAIN edge on real towns -- katoomba 7/69, fremantle
   4/79, bendigo 7/35, newtown 32/64, castlemaine 11/22. The real high street classifies as 'side', which is
   WHY three towns need the fence. If the main/side classifier promoted shop-dense ways to main, the fence
   would lift. Note onMain also gates gigs.js pickVenues pub placement.
-> F: tram verdict above; selector gating (HUD vs ?dbg) is your call, one line either way.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 19:35:56 +10:00
m3ultra
078245f7bd Lane E R20 (v4.0-beta): the density widening — widened fetch, 5 caches re-emitted, towns index
Ledger #2 (E's half), built to C's LANE_C_PUB §6 table under John's SUBTLE directive.

- Widened fetch: C's tasteful staple list (shop=* + amenity=cafe per C's dagger note), mapped through
  C's copy-paste table onto EXISTING registry types (no new archetypes). Guardrails honoured: no
  vehicle/fuel/funeral/storage/industrial, no pure services. New raw snapshot per town (the fetcher
  auto-refetches when the class list changes -- query recorded in each snapshot), committed like the first.
- SUBTLE by construction: secondhand HEROES never subsampled; texture capped at 3x heroes (top of C's
  ~2-3x band), over-cap towns seed-subsampled deterministically (sha256(townKey:osmId)) with every drop
  counted in counts.textureDropped. Result 3.0x in all five: katoomba 20+60 (-4), newtown 18+54 (-156),
  fremantle 20+60 (-81), bendigo 9+27 (-81), castlemaine 6+18 (-43). Density 6-21 -> 24-80 shops (3-4x).
- web/assets/towns/index.json (new, E-owned): {schema, generated, license, attribution, towns[{key, town,
  state, shops, roads}]} -- B's selector can drop the REAL_TOWNS hardcode (hud.js:11).
- Deterministic (byte-identical re-run, 0 re-fetch). ODbL: SOURCES.md + per-cache license/attribution.

-> Lane A (absorb pass): (1) 10 expected golden re-pins -- the widening moves every real town's base+gig
   golden (designed E->A handoff); synthetic 0x3fa36874 UNMOVED, fixtures frozen. (2) SEAM: index.json
   trips selfcheck's town glob (selfcheck.js:467 takes every top-level towns/*.json as a cache) -- one-line
   fix in your file: .filter(f => f.endsWith('.json') && f !== 'index.json'). Didn't touch selfcheck.js
   (yours, you're mid-round in it); Fable spec'd the index at this path so the path stays.
-> Lane C: kept video_games -> video (absent from your §6 table; was already shipping as video pre-widening,
   so the fallback would have regressed it to opshop). Same family, same target -- flagging for your table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 19:30:50 +10:00
m3ultra
955ec3497b Lane A round 20: spine-poster cap scaled by shop count (v4.0-beta, ledger #1)
Closes my own R19 finding + F's one open budget edge. A sparse REAL town has few shops but a big edge
graph, so the 'two posters per main edge' pole run reads busy (katoomba 438) and drove venue_night to
200,965 tris (+0.5% over the 200k soft ceiling).

- gigs.js buildPosters caps the spine pole run at POSTER_PER_SHOP × shops (1.5/shop, floor 12) — a seeded
  subsample. SCALED BY SHOP COUNT, not edge count (the whole point). katoomba 438→31 posters (~2x the
  synthetic feel), fremantle 32, castlemaine 14. NO-OP on the shop-dense synthetic town (493 shops ⇒ cap
  ~740 ≫ its ~15 posters), so the synthetic gig golden 0xb1d48ea1 stays FROZEN.
- Posters are gig-layer (withGigs), so the real-town BASE goldens are unchanged (correctly green). Added
  REAL_TOWN_GIG_GOLDENS (the full district+capped-poster plan per town: katoomba 0xbd332e83, …) to
  regression-guard the capped output byte-exact, not just via districtInvariants. classic/gig/marched
  fixtures frozen; selfcheck ALL GREEN 51675/51675; scaffold + consistency GREEN; cross-process deterministic.

→ F: re-measure venue_night, the +965 edge should close. Density absorb (ledger #2) pends E's widened
caches — the poster cap already reads the live shop count, so it auto-scales to the widened towns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 18:27:29 +10:00
m3ultra
73694c97aa Lane B round 19 (v4.0-alpha): in-game town selector (ledger #4, beta pull-forward, non-blocking)
Shipped the town picker in hud.js (which already owns its DOM overlay -> NO index.html seam). A compact
<select> in the HUD (top-left, pointer-events:auto), 9 options: synthetic + 3 OSM fixtures (osmTownKeys
minus _real) + 5 real-road caches (Katoomba/Newtown/Fremantle/Bendigo/Castlemaine, hardcoded REAL_TOWNS --
no manifest yet, beta derives it). Selecting navigates: synthetic clears plansrc/town; a town sets
?plansrc=osm&town=<key>, preserving all other params. Current pre-selected; unknown-current still shown.
Verified end-to-end: picked katoomba_real through the dropdown -> booted real Katoomba (966 edges/323
intersections/3 venues), 0 errors. Lives inside #pc-hud so hud.setVisible(false) hides it for money shots.

-> F (B->F seam): NONE -- self-contained in hud.js (already constructed by createHUD). Gate it behind ?dbg
   with one setVisible call if you prefer; left always-in-HUD as a modest debug-grade feature.

Corner-strips spot-check (R18 failure-item #3): ground fills real intersections OK -- degree-4 junction
(58 exist) shows road strips overlap-filling the junction, lane markings + zebra crossing render, no gross
gap. Acceptable for alpha; finer acute-angle pass = beta.

Budget note -> F (measured vs A's UNCOMMITTED WIP -- caveat, not a defect): F's BIG_CITY one-liner is live
(chunks 50->26). But venue block still ~237k tris at night against the current tree, which carries A's
uncommitted R19 finalization (plan_osm modified; graph grew 799->966 edges, junction-joining in but the
far-island CULL not yet). Fable's ruling: the cull is "half of B's tris problem" -> the <=200k gate needs
F's fix AND A's committed cull. Re-measure the busiest real block after A pins (the deferred tris-post-cull
re-measure genuinely waits on A's commit; the dev server serves other lanes' uncommitted edits).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 17:38:59 +10:00
m3ultra
6fc4b40632 Lane A round 19: the v4.0-alpha close — fragmentation ruling + findings hardened + goldens pinned
A's finalization (ledger #1), the round's spine. Every filed R18/R19 finding resolved; the tag is F's.

- Fragmentation (D's finding; Fable ruled, A owns details). The naive real graph fragmented (katoomba 105
  components, 58% street-metres on islands). plan_osm.buildRealRoads now: (a) JUNCTION-PROTECTED
  Douglas-Peucker — a point shared by >=2 ways is a junction; simplify only BETWEEN junctions, never
  through one (the collinear tee-off drop, the root cause) → 94-100% main-net alone; (b) cull/bridge —
  main component + near-fragments joined (JOIN_TOL 12m; shop-island bridge <=200m), far SHOPLESS islands
  culled. Result: 1 connected component on all 5 towns (katoomba 100% main-net, 2 islands culled). Every
  dropped shop COUNTED in norm.dropped (ruling): katoomba 19/20 (1 crowd drop — R18 overflow prediction
  measured), the other four kept all.
- E's poster-clearance finding fixed (gigs.js): a spine poster overhanging a real crossing carriageway is
  skipped, measured exactly as the selfcheck kerb floor — a NO-OP on synthetic (gig golden frozen, pr()
  consumed before the check). 23 real-town clearance failures → 0.
- Goldens pinned (A->E->A finalization): all 5 real towns on their real-roads output (katoomba 0xb7ffbca2,
  newtown 0x6f984c81, fremantle 0xfb197000, bendigo 0x21179b3b, castlemaine 0x7c47f639). synthetic
  0x3fa36874 / gig 0xb1d48ea1 / marched fixtures / classic / default FROZEN — the alpha changed nothing
  outside the cache-schema path. selfcheck ALL GREEN 51670/51670; scaffold + consistency GREEN. Cross-
  process deterministic.
- New finding filed (beta, non-blocking): spine-poster density scales with edges (katoomba 438 vs ~14
  synthetic; draws low via instancing) → a beta posters-per-town cap.

Handshake fired → B/C/D/F: katoomba_real boots real roads, golden pinned, findings resolved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 17:37:01 +10:00
m3ultra
e6fcb7b365 Lane F R19 (v4.0-alpha): B's BIG_CITY one-liner — big-graph towns stream like big cities
Real towns can have FEW shops but a HUGE road graph (real Katoomba: 20 shops / 799 edges / 5 km), so the
shop-count-only heuristic left them on small-town streaming and blew the tri budget (280k > the 200k gate).
Extend the trigger to the graph: BIG_CITY = shops>120 || edges>200. B proved the effect; landed EARLY so
D/B's post-fix re-measures see it (per the R19 order).

Verified: katoomba_real 799 edges -> BIG_CITY -> 61 draws / ~12k tris (was 280k), 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 17:19:08 +10:00
m3ultra
10db373e67 Lane E R18 (v4.0-alpha): the other 4 towns' road geometry (data-only) + Overpass retry
Newtown/Fremantle/Bendigo/Castlemaine now schema v2 with roads[] (1086/622/1552/397 real streets),
same fidelity cut (street tier only). Data-only: only katoomba gates the round; A hardens against these.
build_towns.py: added Overpass retry/backoff (public API 504s under load — hit one mid-run).

The poster-clearance finding is SYSTEMATIC: it reproduces on all 5 real-road towns, every seed (23
checks, -0.9 to -4.7m), confirming it's plan-level poster placement (A's pickVenues/POSTER_CLEAR), not
town data. Scoping holds: only the real/* v2 path fails; synthetic + fixtures + classic + default boots
stay green. A's one fix generalizes to all five. ODbL: raw roads committed, SOURCES.md current.

-> Lane A: all 5 towns' roads live; the systematic poster finding is yours to resolve + re-pin goldens.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 16:32:10 +10:00
m3ultra
dbb52c2390 Lane E R18 (v4.0-alpha): katoomba_real real road geometry (schema v2, ledger #3)
Extend build_towns.py: bounded way[highway](bbox) out geom per town -> raw cached in-repo -> roads[]
in A's v2 contract ({id,kind,pts:[[lat,lon]]}, kind=raw OSM highway class). katoomba_real is now
schema v2 with 484 real streets (Bathurst Rd, Cliff Drive, ...). Fidelity cut (charter risk #4, flagged
to A): fetch every ROAD_KIND tier -> raw; EMIT the town street tier only, excluding service/track/
footway/path/steps/cycleway (1461 of 2506 Katoomba ways = bushwalking tracks/sidewalks/stairs/driveways).

A's lift builds a real town from it (verified): 484 streets -> 872 nodes/799 edges (main 232 side 531
arcade 36) -> 12 blocks, 20 lots, 3 venues (pub/band_room/rsl), 12 gigs. pickVenues lands venues on the
real graph (ledger #2 met).

FINDING for A (alpha failure-list, charter risk #3): on the real graph, spine posters overhang crossing
carriageways -- selfcheck kerb-clearance fails on 4 seeds (-1.6 to -2.5m; e.g. seed 20261990 poster 50 vs
edge 58 = -2.42m). Same class as A's R15/R16 corner-poster fix, now on real cross-street geometry. Owner:
A (pickVenues/POSTER_CLEAR on the real graph, the 'A again' harden step) -- my roads data is VALID (cache
validates; failures are plan-level poster placement). Golden settles after A's fix (pre-fix 0x6014a8e6).
ODbL: raw roads committed, SOURCES.md updated.

-> Lane A: katoomba roads live; harden the lift + resolve the poster finding + re-pin the golden.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 16:27:55 +10:00
m3ultra
a78dc76f84 Lane A round 18: the real-graph lift — OSM ways → CityPlan street graph (v4.0-alpha REAL ROADS)
The epoch headline (ledger #2). A v2 cache's roads[] now builds the CityPlan street graph FROM real
OSM geometry instead of marching shops onto synthetic avenues. SAME CityPlan schema out — B/C/D/F consume
it unchanged by contract. roads absent ⇒ the v1 marched fallback, so classic/gig/osm goldens are FROZEN.

plan_osm.buildRealRoads: project ways+shops to the local metre frame → simplify each way (Douglas-Peucker
eps~6m, the fidelity knob) → snap coincident points (<=3m) to shared nodes = real intersections →
straight-segment edges → classify main by OSM highway class + shop density → seat each shop on its NEAREST
real edge (real order, real side), marched with regularised spacing + a deterministic overlap-resolve pass.

Fidelity (charter risk #4): real edge/order/side + regularised spacing — NOT pixel positions (real shops
overlap; the no-overlap invariant is load-bearing). Alpha failure list in LANE_A_NOTES §R18: overflow drop
on short edges; intersections = shared-coordinates only (a D sim-graph risk); per-edge frontage-strip
blocks not planar faces (a B ground-render item); crowded-intersection overlap-resolve.

Proven: a committed synthetic irregular graph (main + two cross streets + a real intersection + an acute
angle + a dead-end lane + a curve) passes the FULL structuralSuite + gig district + byte-identical
determinism; mutation-tested non-vacuous (flip the facade facing → 'faces its frontEdge' fails). Robust on
messy inputs (single road, coincident dups, disconnected ways, all-roads-too-short → marched). All osm
goldens frozen; E's 4 trailing caches pinned on v1; katoomba_real UNPINNED (its real-roads golden pins when
E lands roads — the A->E->A finalization). selfcheck ALL GREEN 16810/16810; scaffold + consistency GREEN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 16:10:14 +10:00
m3ultra
4dc80c2146 Lane A round 18: town-cache schema v2 (roads[]) — published FIRST (v4.0-alpha REAL ROADS)
The half-day handshake so E's build_towns.py can fetch road geometry (ledger #1). Optional roads[]
on the town cache carries real OSM way geometry; plan_osm's graph lift (consuming it) follows in the
next commit. v1 caches (roads absent) stay valid — the marched fallback — so nothing shipped regresses.

- validateTownCache accepts schema procity-town-cache/1 AND /2; when roads[] is present each road must be
  { kind:string, pts:[[lat,lon],…] } with >=2 finite points (else rejected); <2 pts dropped, unmapped
  highway kind → 'side' (warnings). ROAD_KIND maps OSM highway=* → CityPlan edge kind (main/side/lane/arcade).
- Full v2 contract in web/assets/towns/README.md (the doc E builds to): shape, road validity, the kind map,
  the fidelity knob (charter risk #4), and the bbox-bound-the-roads rule.
- E's 5 existing v1 caches re-validate clean; selfcheck ALL GREEN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:54:19 +10:00
m3ultra
e4a49b5bc8 Lane F R17 (v3.2): real towns boot in the engine + the town-matrix scout gate (ledger #7)
F wired the last mile of the real-map scout and gated the whole matrix.

- index.js barrel re-exports registerTownCache/validateTownCache; the shell fetches + registers
  assets/towns/<key>.json before generatePlanFor when the town isn't a checked-in fixture — so
  ?plansrc=osm&town=bendigo_real boots a REAL AU town in the engine (the gap: E's caches were on disk +
  in the node selfcheck, but the shell never loaded them → silent Melbourne fallback). Fail-soft
  (404 / invalid / ?noassets -> fixture fallback); opt-in, never on the default or ?classic path.
- tools/qa/town_matrix.py (opt-in qa.sh --matrix): boot / determinism / budget / district / ?noassets
  across 10 towns (2 synthetic hero seeds + 3 osm fixtures + E's 5 real AU caches). ALL 5x10 GREEN —
  Castlemaine at the 6-shop floor still lands a 3-venue district. The existing CityPlan contract eats real
  Australian geography: the evidence John charters v4 = THE REAL MAP on.
- docs: LANE_F_NOTES §17 (the town x gate table), README real-town row, F-progress R17.

qa.sh --strict --soak GREEN 7/7. Verified: ?plansrc=osm&town=bendigo_real -> Bendigo, 9 shops, 3 venues, 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 15:23:15 +10:00
m3ultra
64ded4ea01 Lane D R17 (v3.2): bench-sit loiter (ledger #2) — the carried R16 stretch
Street peds occasionally sit during a window-shop loiter (verandah/footpath
edge). makeActor gains an opt-in setSitting with a SCALE-AWARE re-plant (the
R16 spawnRig re-plant was scale-naive; the sim scales these rigs per-citizen),
played only on sit so walkers/placeholders/?classic are byte-identical. Seeded
via a dedicated benchsit rng stream (no shift to turn/loit/patron; identity
signature unchanged). Classic inert at the source (roll gated on sitClip).

In-shell (default, seed 20261990): head bone 1.466->1.070, bone span
1.667->1.299 (in seated gate [0.9,1.5]), feet re-plant to y=0 and hold through
sit-idle, stand-up restores inner.y 0.929 byte-for-byte, procitySeated tagged,
innerRotY:pi throughout. 9 distinct peds sat naturally per soak. Classic:
fleetSitClip:false, everSat:0. Plan golden 0x3fa36874 unchanged. Draws 35/tris 6k.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 14:53:22 +10:00
m3ultra
483a4b75c6 Lane E R17 (v3.2): the real-map scout — 5 AU town caches + publish --verify fix
Ledger #4 (warm-up): publish.py --verify no longer false-flags non-procity_ published assets
(sit.glb, vintage-cash-register). It compares the _published.json name record against the depot's
full file list (fetch_depot_files) instead of a procity_ prefix filter; only OUR namespace flags as
unrecorded. --verify now: all 39 recorded assets live.

Ledger #6 (the scout): new pipeline/build_towns.py ports thriftgod build_city()'s Overpass route to
per-town caches in A's procity-town-cache/1 contract. 5 real compact AU towns under web/assets/towns/
(katoomba/newtown/fremantle/bendigo/castlemaine, 6-21 shops, spans <2.4km): bounded Overpass query ->
raw cached in-repo (re-runs never re-fetch) -> dedupe/suburb-fill/parody (trademarked chains only;
indie shops keep real OSM names)/type-map. Deterministic (byte-identical re-run, no RNG). ODbL:
SOURCES.md licence table + license/attribution on every cache. All 5 boot through the full
structural+gig suites (selfcheck 16596/16596 green; synthetic golden 0x3fa36874 unmoved). Overpass
fetch John-authorized (Standing #2).

-> Lane A: caches live under web/assets/towns/; pin the per-town goldens selfcheck printed (katoomba
   0x61760542 newtown 0x95978b45 fremantle 0xee9fd09a bendigo 0x5e3e76a6 castlemaine 0xf1a628a1) +
   feed through plan_osm. E->A handshake.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 14:49:40 +10:00
m3ultra
6671cf08f4 Lane D R17 (v3.2): the drummer's pelvic-lean (ledger #1)
The R16 seated drummer sat bolt-upright (the sit clip can't carry a pelvic tilt
— Hips.quaternion is unusable on these rigs). Fix: a small constant forward torso
lean applied POST-MIX. spawnRig({seated}) caches the mid-spine bone (seatBone);
seatedLean(spine) rotates it forward ~0.34 rad each frame after the mixer resets
it (constant offset, not accumulation); band.js calls it for m.seated members.
The drummer leans into the kit — head 0.28m forward of the hips, reads as a real
drummer from the side.

Byte-identical (my signature): standing rigs get no seatBone (found only in the
seated block) and seatedLean runs for seated figs only. Verified with the lean
live — walkers 188/188 face travel, keeper standing rig (stature 1.718,
hasSeatBone:false, innerRotY pi). No existing consumer moves.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 14:32:58 +10:00
m3ultra
6fffd19043 Lane A round 17: v3.2 the town-cache contract (published first) + plan_osm hardened for real data
The real-map scout (ledger #6), A's half. Scope fence held: NO new plan features, NO golden moved
(classic 0x3fa36874, gig 0xb1d48ea1, all three osm fixtures frozen). The scout proves the EXISTING
?plansrc=osm contract eats real geography.

- The town-cache contract (published FIRST — E builds build_towns.py to it). plan_osm.js gains
  validateTownCache() (authoritative {ok,errors,warnings}), registerTownCache(), a generatePlanOSM(..,
  {cache}) seam, and TOWN_CACHE_SCHEMA/MIN_TOWN_SHOPS(6)/MAX_TOWN_SPAN_M(5km). Shape: {schema,key,town,
  source,license,attribution,center{lat,lon},shops[{id,name,type,lat,lon,suburb?}]}. Home declared:
  web/assets/towns/<key>.json (+ README.md full spec). Documented in CITY_SPEC v3.2 + LANE_A_NOTES R17.
- plan_osm hardened: blank name -> registry label; the validator gates finite center/coords + a >=6-shop
  floor and warns on unknown-type(->opshop)/dup-id/span>5km. Proven vs thriftgod's real 2,828-shop
  city_source.json: boots a valid plan, 0 bad coords, 0 'undefined' names.
- selfcheck: a committed synthetic-adversarial contract suite (valid-messy caches boot + pass structural/
  gig; invalid reject; wide-spread warns; registry seam) + an auto-loader for web/assets/towns/*.json
  (validate -> suites -> pin per-town golden), empty and green until E lands caches. ALL GREEN 15277/15277.
- v4 charter risk list (LANE_A_NOTES R17): the MEGA-STRIP (unbounded bbox -> 11.6 km strip; town selection
  is E's real lever, warned >5km); sparse compact towns (2 km inner-Canberra held 6 shops); osm facades
  clear (rows 54 m apart) so R16's bias is a no-op on real towns.

E->A handshake: E drops a cache in web/assets/towns/, the selfcheck prints its golden, I pin it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 14:32:14 +10:00
m3ultra
ee16545941 Lane B round 17 (v3.2): wind sway SHIPS -- weather-driven gum-tree sway (ledger #5, parked since R7)
Verdict: shipped, not killed. The R7 park reason ("touches shared materials") is a non-blocker under
R16's measurement-over-brief standard: the gum-tree billboard material is B-owned (furniture.js), so
this is entirely Lane B -- no C/E material seam. Verified fresh Chromium seed 20261990.

- New web/js/world/wind.js: shared uniforms (uWindTime/uWindAmp) + applyWind(material) (onBeforeCompile
  vertex patch: top-weighted horizontal sway, per-instance world-position phase, USE_INSTANCING-guarded)
  + updateWind(dt,intensity). furniture.js applies it to the tree material; weather.js drives it from
  update(dt) (base breeze 0.05 clear -> 0.05+intensity*0.30 ~0.35 rain gusts).
- Trees only. Awnings excluded by MEASUREMENT: rigid posted-verandah box slabs don't flutter (fabric
  canopy ripple = separate v3.3, shares the rigid awning InstancedMesh today).
- Byte-identical when weather off (the covenant): updateWind runs only inside weather.update, and the
  weather system isn't constructed under ?weather=0 / ?classic=1 -> uWindAmp stays 0 -> sin(...)*0.0==0.0
  -> identical vertices. Proven: amp=0 two times = 0/180000 px differ; ?weather=0 boot = 0 tree-motion px;
  ?classic=1 = amp 0, trees render, 0 errors. No plan/fetch/rng change -> F's classic gate untouched.
- Sway works: rain amp 0.305 moves ~14100/180000 region px over 0.8s (exaggerated 2.5 -> 101k); trees
  render clean, no glitch. ~0 draws (ALU ops in the existing tree InstancedMesh vertex program), 0 errors.

-> Lane F (B->F handshake): SWAY SHIPPED. In old frames under the default boot; ?classic=1/?weather=0
   sway-free + byte-identical. Procedural (no asset -> E has nothing to do).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 14:30:09 +10:00
m3ultra
a4946b7ca2 Lane F R16 (v3.1 THE FLIP): defaults on + ?classic covenant + seated-stature gate (ledger #1, #3)
The town shows its best by default. gigs / weather / winmap / tram flip ON (each keeps a ?flag=0 opt-out;
?classic=1 forces the exact v2 boot). The prime-law covenant MOVED from "flags off" to "?classic=1" —
byte-identical forever (synthetic fingerprint 0x3fa36874). The default boot is now the full experience,
deterministic to the gig golden 0xb1d48ea1 (A's R16 corner-poster re-pin).

- index.html: CLASSIC + flagOn(); gigs/weather/tram default-on; loadPedFleet({sit:!CLASSIC}) for the seated
  drummer (?classic keeps the zero-fetch-delta covenant); a window.PROCITY.flags intent surface for the gates
- buildings.js: winmap default-on + classic-aware (the one cross-lane flip line the flag placement requires)
- flags_check.py: flags_off_regression -> classic_regression (?classic=1 byte-identical); a new default_boot_gate
  (all four flags on, gig layer present, gig golden, budget); every gig smoke re-pointed at the DEFAULT boot
- seated-stature gate (ledger #3, published for D): interior_scale_check.py + flags_check.py accept
  fig.userData.procitySeated at stature [0.9,1.5] m (the drummer); standing figs stay [1.4,2.0]
- qa.sh flags-harness gate name updated (classic regression + default-boot gate)

Verified: ?classic byte-identical (0x3fa36874, gig layer absent); default boot = the full town (14 gigs, 15
posters, tram, gig golden green, 112 draws @ the venue block); the seated drummer passes at 1.32 m stature;
district (3 venues / 3 genres), continuity, and cover all green on the default boot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 13:20:43 +10:00
m3ultra
ab7a8d0edf Lane D R16 (v3.1): the drummer sits + backline unification (ledger #2, #5)
Ledger #2 — drummer sits. E's sit.glb is wired into the shared rig stack:
- FINDING: Fable's prescribed _rotWithHips (keep Hips.quaternion) MANGLES the
  pose in-shell (head folds to hip height / laid flat) — the fleet rigs' bind
  Hips orientation is incompatible with the Mixamo clip's, exactly what _rotOnly
  documents. So the sit clip rides _rotOnly (drops Hips.quaternion) like every
  clip; _rotWithHips removed. The seated read comes from the leg bends + a new
  spawnRig({seated}) foot-replant (opt-in; standing spawns skip it).
- Drummer uses fleet.sitClip when present (retires SEAT_DROP), tags
  fig.userData.procitySeated=true (F's gate). Stature ~1.1-1.3m in [0.9,1.5];
  reads seated from the crowd POV (kit hides the legs). Graceful SEAT_DROP
  fallback when sitClip absent (?noassets / before F wires {sit}).
- BYTE-IDENTICAL proof (load-bearing): with sitClip null AND loaded, keepers are
  standing rigs (stature 1.718, innerRotY pi, replanted:false) and walkers 188/188
  face travel. Parallel/opt-in path; _rotOnly + makeActor untouched.
- F seam: loadPedFleet(base, {sit}) — pass sit:<gig active> (false under
  ?classic → no sit.glb fetch, classic covenant intact). Default off, graceful.

Ledger #5 — backline unification. _addBackline plants E's guitar_amp at C's
stage.backline[0] (== D's R15 pose, 0.75m bass clearance) instead of a hardcoded
pose. C dropped its primitive ampStacks, so D owns the backline: placeholder-
persists (primitive amp → GLB swap) with the primitive as the ?noassets fallback.
Verified: GLB swaps, primitive under noassets, no crash, 0 fetch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 12:49:44 +10:00