Commit Graph

29 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
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
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
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
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
55f6698fb2 Lane E R14 (v3.0 release): provenance freeze + doc-consistency fixes
Provenance close-out for the v3.0 tag. Verified via a 6-agent inventory+audit workflow
(both adversarial audits PASS, 0 blockers) cross-checked against glb_stat/ffprobe/manifest.

- LANE_E_NOTES: v3.0-FROZEN provenance table + full audio(28)/GLB(38)/skins(96)/packs(3)
  inventories; by-design notes + v3.1 deferrals (street_bin decimation).
- AUDIT.md: add R13 gig-layer finalization section (14k decimation, _hi published, gigKey
  rename + 2 beds, depot publish done) — ledger was stale at R12.
- manifest glb_law string: state the documented <=8k-hero / <=14k-instrument tiers so the
  frozen contract is self-consistent (regenerated; 1-line diff, Gate 3 still 0/0).
- gen_audio: roomtone-video gain 0.3 -> 0.35 to match the shipped manifest.

Gate 3 GREEN; publish.py --verify clean; 0 quarantine assets in manifest; goldens unmoved
(synthetic 0x3fa36874, gig 0x1f636349). No new synthesis (genres final); no poster templates
(no ask from B).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 01:18:40 +10:00
m3ultra
bf98b41b16 Lane E R13 (v3.0-beta): gigKey rename + grunge/covers beds + instrument decimation
- debt #1: the manifest music key IS the gigKey, always gig-<genreKey>. Renamed
  pubrock-live -> gig-pubrock (files + gen_audio + build_manifest); old files deleted.
  B/F switch readers, F deletes the GIG_BED bridge (both fail soft to silence til then).
- two new gig beds: gig-grunge (band_room, quiet-loud dynamic) + gig-covers (RSL, mellow
  organ-led); procedural/seeded/loopable/$0. New organ() + grungechord() synth helpers.
- decimate the 5 instrument GLBs to 14k tris each (was 43-96k; fleet 236k->70k, -70%) via
  collapse (thin features survive); _hi hi-poly originals kept for depot; thumbs re-rendered.
- manifest regen (validates 0/0 incl --depot); app boots clean flags-off / ?gigs=1 (3-venue
  district, all 3 beds resolve) / ?noassets=1&gigs=1 (0 audio+GLB fetches).
- depot re-publish (14k bytes + _hi originals) gated on John's OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 23:03:14 +10:00
m3ultra
7795780336 Lane E R12 (v3.0-alpha gig layer): 5 instruments + 4 posters + 3 gig audio
Instruments (MODELBEAST flux_local concept -> trellis_mac -> normalize):
electric_guitar, bass_guitar, drum_kit, guitar_amp, mic_stand -> manifest
fittings + thumbs, published to the tailnet depot. All 5 reconstructed
cleanly (thin mic-boom + cymbals survived); heavy tris (30-96k, amp the
outlier) accepted like the R3 props. gen_props.py gains --batch;
gig_instruments.json + gig_norm_batch.json + _gig_results.json.

Posters (flux_local, gen_skins.py --posters): poster-xerox/screenprint/
grunge/retro -> skins.poster with nameZone for band-name overprint, blank
name-band (no baked text) like blank-signboard facades.

Gig audio (procedural, gen_audio.py): music-pubrock-live (original 90s
pub-rock riff), ambience-crowd-walla, sfx-applause -> manifest audio,
flagged gig:true for F. Pack now 26 assets, 9.1 MB of 25.

build_manifest reads _gig_results.json + emits skins.poster + gig audio;
validate_manifest green (--depot 0 err, all live). Provenance in AUDIT.md
(section Round 12); README + E-progress updated. Touched no other lane's
files. F owns the v3.0-alpha tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 19:44:48 +10:00
m3ultra
acf734a1e5 Lane A round 12: v3.0-alpha gig layer (?gigs=1) — venue, plan.gigs, band names, closing-time debt
Publishes the gig interface the whole round hangs off (A runs first). Everything is
behind ?gigs=1 as a POST-HOC augmentation (gigs.js withGigs, applied by the selector),
so generatePlan is untouched and all v2 goldens stay frozen (synthetic 0x3fa36874, osm
melbourne 0x34cfdec0, katoomba 0x0f652510). Source-agnostic (synthetic + osm).

- Venue: one 'pub' per town — a spine-end plain shop converted in place (keeps lot
  id/geometry, enterable), shop.venue=true, never the openLate landmark. Registry gains
  a weight-0 'pub' type (interior:'band_room' for Lane C) → never auto-placed → base
  plan byte-identical.
- plan.gigs: 7 nightly {gigId,venueShopId,bandName,genreKey:'pubrock',night,startSeg:5,
  endSeg:5,cover}; cover ~half free / half $2-$10 (F charges at the door).
- Band names: bandName(seed) generator (90s pub-rock) + OPTIONAL web/assets/custom_bands.json
  drop-in (priority into the pool; absent → pure generator, no fetch under ?noassets).
- plan.posters: ~6 seeded {id,gigId,x,z,ry} for Lane B.
- Closing-time debt paid: isOpen(shopOrHours,hour) exported (half-open law as code, D consumes).
- map.html?gigs=1: venue ring + poster pins + gig panel line. Flags-off unchanged.

Self-check ALL GREEN 3074/3074 (gigSuite ×2 sources, flags-off≡base, gig golden
0xa6ae5a5e). qa.sh --strict GREEN 6/6. Verified in-browser both modes. CITY_SPEC v3
section + LANE_A_NOTES handshake for C/D/B/F. Atomic pathspec commit (shared-tree race).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:33:53 +10:00
m3ultra
be9f967d19 Lane E R11 (audio): procedural audio pack — 23 assets, free/on-device
gen_audio.py: a numpy synthesis engine (osc / ADSR / filters / reverb /
seamless-loop crossfade + note sequencer + drum synth). Renders 6 ambience
beds (street day/night, rain, 3 interior roomtones) + 13 sfx (doorbell,
door, till, record-riffle, toast, tram bell/rumble, 6 footsteps) + 4
instrumental 90s music loops (record-shop, milkbar, video-synth, arcade)
-> web/assets/audio/ as OGG/Opus + M4A/AAC. 8.1 MB of the 25 MB budget.

Tool = 100% procedural synthesis (not a neural model): $0, deterministic/
seeded, perfectly loopable, parody-safe by construction. Documented in
README (§ audio) + AUDIT.md provenance.

manifest audio:{ambience,sfx,music} — file + m4a fallback + loop + gain;
interior roomtone/music carry types[] (seed-pick per shop, like facades);
footstep is {surface:[variants]}. build_manifest.py builds it,
validate_manifest.py checks it. qa.sh --strict green (audio 23, 0 err).

Verified technically (peaks <= -0.4 dBFS, all loops seamless, durations)
via spectrogram sheet + numeric — subjective ear-check is John's/F's.

E leads the audio round; F owns the v2.1 tag + push. Not pushed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 14:50:15 +10:00
m3ultra
019304d647 Lane E round 5 (E2): depot growth — street bin + record-crate stack (consumer-driven)
v2 features are procedural (no forced GLB needs), so E2 is light per Fable's "no
unconsumed entries": two synthetic depot props with clear homes — council-bin ->
procity_street_bin_01 (Lane B street dressing) + milk-crate-stack ->
procity_fit_crate_stack_01 (Lane C floor piles / dig). Both 3k tris, base-origin,
re-normalized to procity names + thumbs, published, verified loading, validate --depot
0 err. Manifest 18 fittings + 10 furniture (28 GLBs). Also noted B3 resolved
(novelty_record 26.5k->8k via E1 bake).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 21:27:13 +10:00
m3ultra
8644d3f7ac Lane E round 5 (E3): fal Hunyuan glass_case + bus_shelter + magazine_rack (~$0.64)
The 2 R3 TRELLIS glass rejects + optional magazine-rack, generated on fal.ai
Hunyuan3D v2 (John-authorized, $22 balance). pipeline/gen_props_fal.py drives the
fal operator using the FAL_KEY from MODELBEAST settings (never hardcoded). Frosted/
opaque flux_local concepts gave the reconstructor a surface (clear glass defeated
TRELLIS). glass-case 1 att, bus-shelter 2 att (opaque back wall), magazine-rack 1 att
= ~$0.64 total, guardrail held. All baked to <=8k via bake_lowpoly.py (switched to
EMIT albedo bake — Hunyuan materials bake near-black under DIFFUSE). Verified loading
in vendored GLTFLoader, published, validate --depot 0 err. Manifest 17 fittings + 9
furniture; aliases wire glass_case/glass_cabinets/magazine_rack/fridge/listening_corner.
Costs logged in AUDIT R5. Last 2 primitive-only fittings retired.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 21:20:44 +10:00
m3ultra
c52246444d Lane E round 5 (E1): bake 6 hero props to <=8k tris (288k->48k), live on depot
pipeline/bake_lowpoly.py — Blender headless: voxel-remesh -> decimate -> Cycles
base-colour bake onto fresh UVs (R3 lesson: simplify-only floors on TRELLIS
shell-soup; the re-bake is the point). drinks_fridge/milkshake_mixer/arcade_cabinet/
listening_booth/novelty_record/counter_till all 25-77k -> <=8k, ~0.9M each. Every
prop eyeballed (docs/shots/laneE/props_baked.png) + verified loading in vendored
GLTFLoader; footprints unchanged (no C re-map needed). Re-published; validate --depot
0 err. Originals gitignored in pipeline/.props_orig/. Unblocks C's interior re-measure
+ F's v1.1 tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 20:56:07 +10:00
m3ultra
dafb079ff4 Lane E round 4 (E2): fix record_crate + ship counter-with-till, both live on depot
- record_crate: R3 normalize left a sourceless texture (packed AO/roughness map
  didn't survive WebP export; metallicRoughness+occlusion pointed at it) → three.js
  'undefined uri' crash. New pipeline/fix_glb_textures.py strips material slots that
  reference a sourceless texture. Verified loads in vendored GLTFLoader; re-published.
- counter_till (new fitting): ~2m timber counter + period till, flux_local→trellis_mac
  on-device, 1.61x0.64m / 1.15m tall, 32k tris. Verified loads; published. Lane C maps
  kind counter -> counter_till (balcao 4m 'counter' kept for long-bar use).
- publish.py: --only <name> filter + passwordless tailnet detection (GOD3_DEPOT override).
- manifest rebuilt (15 fittings, alias counter->counter_till); validate --depot 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 19:07:15 +10:00
m3ultra
bd40ec7e7a Lane E round 3 (landed by Fable after review): 5 hero props gen'd local + published, local-depot mode, manifest 14 fittings + 8 furniture
- gen_props.py: flux_local -> trellis_mac -> normalize pipeline; 5/8 props kept
  (arcade-cabinet, listening-booth, drinks-fridge, milkshake-mixer, novelty-record)
- magazine-rack -> primitive (thin-wire gotcha); glass-case + bus-shelter -> fal.ai fallback
- cash-register reused from depot; all 22 GLBs live, validate --depot 0/0
- loaders.js ?localdepot=1 + stage_local_depot.py for network-free GLB validation
- qa.sh --strict GREEN 4/4 at commit time

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 18:03:03 +10:00
m3ultra
063a959e29 Lane E (assets): pipeline, manifest + 23 on-device facade skins
Audit -> normalize (16 GLBs + thumbs) -> web/assets/manifest.json (the
contract Lanes B/C/D read) -> facade gap-fill.

Step 4 facades generated locally on the M3 Ultra via MODELBEAST
flux_local (FLUX.2-klein-4B / MLX on MPS): 23 skins, free, ~5.7s each,
blank signboard, eyeballed, harvested, mapped to shop types. Every
registry type now has >=3 facades (stall 2->4, closing the Lane A gap).
Corner-lot -side walls tagged face:"side" with empty types so no shop
front ever selects a windowless wall. manifest validates green.

Still gated on John (both optional -- the game runs asset-free):
publish the 16 GLBs to 3GOD (needs GOD3_PW), MeshGod hero props (~$2.70).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 13:48:25 +10:00
jing
a702a69f1e PROCITY scaffold: spec, research, 6 Opus lane prompts, core modules, vendored three r175, 69 inherited skins
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 10:46:40 +10:00