43b035aa2e
22 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
d485b18ecc |
Lane A round 22: close the tri-diet loop — B's numbers say the fix is E's, not A's (ledger #1)
Docs-only handshake close; no code, no goldens. Filed so F isn't waiting on A for the re-measure. My R22 notes left ledger #1's ownership open on purpose: "if B's layer-by-layer names plan geometry (lot or poster counts) as the venue_night driver, I own the fix and will take it." B's diagnosis ( |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
2b13dd4ad7 |
Lane A round 16: v3.1 corner-poster clearance bias (#6) + no-spine osm fixture (#7)
Ledger #6 fix + the round's one sanctioned gig-golden re-pin, and ledger #7. Classic/synthetic golden 0x3fa36874 frozen (classic boot byte-identical across all seeds); base plan untouched. - Corner poster: the R15 finding (frontage poster near a crossing kerb) is NOT fixable by the brief's 'nudge along the facade' — proved the crossing edge is PARALLEL and spans the facade (0/187 slides help); band_room/rsl land on through-lots on narrow warehouse blocks whose +Z wall (B's door side) overlaps the block's other street by up to ~3 m. Surfaced to Fable; ruling: bias pickVenues. It now prefers a band_room/rsl candidate whose +Z facade clears every carriageway by >= POSTER_CLEAR (0.5 m), broadening off-spine if the fringe is uniformly narrow. Result: 0/851 frontage posters below floor across 400 seeds (worst 0.51 m); pub untouched (hero shot unmoved). - Gig golden re-pinned 0x4f4a549d -> 0xb1d48ea1 (posters moved). selfcheck's R15 blanket frontage exemption becomes a real floor: frontage >= POSTER_CLEAR, spine >= 0 (POSTER_CLEAR exported from the barrel). Mutation-tested non-vacuous. - No-spine osm fixture 'silverton' (single-row town, 0 main edges) proves pickVenues' no-spine branch + buildPosters' no-main fallback, closing the R14 sweep gap. Base golden pinned 0xd4b351c9; sweep asserts 0 main edges + graceful 2-4-venue placement. selfcheck ALL GREEN 14769/14769; scaffold + consistency GREEN. - CITY_SPEC v3 amended (golden, poster clearance-bias prose, no-spine note, recorded amendment). Left the prime-flag-law blockquote for F (the v3.1 classic-law + flags-table is F's amendment). For F: default-boot golden = 0xb1d48ea1; ?classic=1 target = 0x3fa36874. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
35da83c347 |
Lane A round 15: frontage poster +Z street-face flip (ledger #1) + gig golden re-pin
R14 review found every venue's own-frontage poster on the building's −Z BACK since R13 (~16 m behind the street face, B measured 15.9 m) — invisible from the street, why queue_night framed no poster. Ledger #1, A-first (B's hero re-shoot + F's tour hang off this). - gigs.js buildPosters item 1: flip to the +Z street facade (B's canon: buildings.js facade zf=+d/2 + venue.js door/queue/camera are +Z) AND ry=lot.ry+π so the printed face points +Z at the queue-side camera (else DoubleSide shows a mirrored band name). Proven: pub+rsl frontage posters now sit 0.06 m from B's door, printed-face·(+Z street)=1.000. Spine posters untouched. - Gig golden re-pinned 0x1f636349 → 0x4f4a549d (the round's ONE sanctioned move; posters moved). Synthetic golden 0x3fa36874 frozen. §v3 FROZEN marker records the amendment (amendment law). - selfcheck: the +Z facade is the block-interior side in plan coords, so corner venues (band_room/rsl fronting one street with another behind — seed 1 lot#481, 1.58 m from a crossing centreline) seat the frontage poster near that street. That's B's building geometry (the door is there too), not a mid-road defect — so the no-bitumen assert now EXEMPTS building-bound frontage posters, keeps it for spine posters. 400-seed sweep green again: 14264/14264. - CITY_SPEC §v3 amended (poster prose → +Z facade + ry+π; golden line; frontage/spine carriageway split; recorded amendment in the FROZEN marker). LANE_A_NOTES §R15 hands B/F the new golden + a corner-venue eyeball note. Convention settled: visible venue face is +Z; selfcheck's −Z 'faces frontEdge' is the sim/GLB convention (π-off the visual front, the R13 RY_FLIP ambiguity). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
a3911a4590 |
Lane A round 14: v3.0 release — 400-seed district invariant sweep + CITY_SPEC §v3 frozen
Release round: harden + freeze, no new systems. No golden moved (synthetic 0x3fa36874, gig
0x1f636349 both re-verified frozen); selfcheck.js is the only code touched, so no seeded generation
stream gained a draw (release-round law).
- selfcheck.js: factored the district checks out of gigSuite into districtInvariants(plan,label)
(behaviour-preserving — hero-seed gigSuite runs byte-identical), then added a 400-seed synthetic
sweep + the large edge seeds asserting the full district contract each (2-4 venues, >=1 pub, never
the openLate shop, no band twice/night town-wide, per-venue 4-6 nights, every poster off the
carriageway). Asserts the seeded count spans {2,3,4} across 400 seeds (146/121/133 — range is
exercised, not pinned). osm graceful placement: katoomba (19 shops, no warehouse district) still
lands 2-4 valid venues incl. a pub for every hero seed. Poster check kept at roadWidth/2 (a literal
poleOffset compare would false-fail corner posters); added -1e-6 epsilon on the strict boundary.
ALL GREEN 14264/14264 in ~0.7s.
- CITY_SPEC §v3: final wording pass, marked FROZEN at v3.0 (round 14) with a v2-style marker + an
explicit carve-out for F's pending alias-line deletion. Fixed the roadWidth prose (full carriageway
width, not 'half-corridor'). Genres final (pubrock/grunge/covers).
Coordination: the R12 single-venue alias line stays in §v3 for F to delete atomically with the
gig_state.js getters (debt #1) — deleting now would be doc-ahead-of-code (alias still live) and race F.
Flagged to F that the runtime block omits nightOf(id); to B that venue.js:228 is a 2nd bare-string
site. Verified: mutation-tested the sweep (non-vacuous — catches 5-venue/7-night/on-road violations)
+ adversarial pass (goldens frozen, freeze matches code, deterministic).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
6fba79a1cb |
Lane A round 13: v3.0-beta the district (?gigs=1) — 2–4 venues, week schedule, town-wide posters, verge fix
Publishes the multi-venue plan.gigs interface C/D/B/F hang off (half-day handshake, A first). - pickVenues: seeded 2–4 shops converted in place → pub (spine end) / band_room (warehouse fringe) / rsl (off-spine); 4th = 2nd pub at far end. Registry gains weight-0 band_room+rsl kinds + venueKind/genreKey/placement. Never the openLate landmark; osm-safe fallbacks. - gigKey contract (debt #1): gigKeyFor(genreKey) => 'gig-'+genreKey, the single exported genre→bed mapping. No table anywhere; F deletes the GIG_BED bridge. - plan.gigs goes district: 7 nights × every venue, each plays a seeded 4–6 (dark reads true); cover skewed by kind; no band plays two venues on one night; custom names spread night-major. - plan.posters goes town-wide: tonight's playing venues each get frontage + seeded spine run. - Verge fix (debt #5): new corridor law roadWidth/vergeBand/poleOffset(edge) in registry.js (road-vs-verge split of edge.width, published as functions ⇒ base goldens frozen). Posters seat on the verge, never bitumen; selfcheck asserts no poster on a carriageway. - registry pub.interior 'band_room'→'pub' (unread field; avoids collision with band_room type). Gig golden re-pinned 0xa6ae5a5e→0x1f636349 (multi-venue changed output; in-commit per amendment law). selfcheck ALL GREEN 3273/3273; scaffold_check + consistency GREEN; flags-off byte-identical. CITY_SPEC §v3.0-beta + LANE_A_NOTES §Round 13 updated in this commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
e5d4679471 |
Lane A round 9: freeze CityPlan v2 contract in CITY_SPEC + closing-time occupant ruling
Ship round. Docs + one selfcheck log-line only; no generator change ⇒ all three goldens unchanged (synthetic 0x3fa36874, osm/melbourne 0x34cfdec0, osm/katoomba 0x0f652510). 1. CITY_SPEC v2 contract FROZEN — new "CityPlan v2 — frozen producer contract" section: producer API, goldens table (keyed seed/plansrc/town) + how to pin a new one, town-key mechanism, osm normalization rules, hours/openLate/storeys laws. Matches code as shipped (F diffs claims vs code). Refreshed the stale round-6 Plan-sources blockquote to multi-town reality. Layer-1 changes now require a CITY_SPEC amendment + golden re-pin in the same commit. 2. Recipe sanity — DRY-RAN end-to-end: appended a throwaway Newtown (42 shops), selfcheck auto-ran the full parity suite (1931/1932, only golden unpinned) and printed a paste-ready `newtown: 0x9045e577,`. Reverted; no 3rd town shipped. Added the selfcheck `⚠ UNPINNED — add to OSM_GOLDENS` line so the recipe is mechanical; fixed the recipe wording to match. 3. Closing-time occupant ruling (D's on-call Q) — ratifies + freezes what D's sim.js already does: half-open hours, no new entry when closed, occupants DRAIN (finish bounded dwell) never popped, player not force-ejected, openLate video is the night crowd. In CITY_SPEC + LANE_A_NOTES. No code change asked of D. qa.sh --strict GREEN; selfcheck 1727/1727. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
f952f513d0 |
Lane A round 8: OSM to parity + a second town (Katoomba) — carried R7 brief, full
The carried brief (slipped R7) lands complete — all four items, qa.sh --strict GREEN.
1. Selfcheck PARITY: extracted structuralSuite(plan,label) and run the FULL invariant suite
on every (source, town) — synthetic + both OSM towns get identical coverage (storeys,
one-shop-per-lot, facing, within/cross-block overlap, corridor coverage, determinism,
exactly-one-openLate). ALL GREEN 1727/1727 (was 1362; OSM went subset → full ×2 towns).
2. SECOND TOWN: Katoomba (Blue Mountains, 19 shops, op-shop/book heavy) — regional contrast
to inner-Melbourne. osm_fixture.js → OSM_TOWNS{melbourne,katoomba}+DEFAULT_TOWN;
generatePlanFor(seed, source, {town}); ?plansrc=osm&town=katoomba. Golden 0x0f652510.
Melbourne 0x34cfdec0 + synthetic 0x3fa36874 UNCHANGED (town key kept off the plan).
3. "Add a town" recipe in LANE_A_NOTES (R8): extract → OSM_TOWNS → pin golden → tell F.
4. Normalization + LOG: importer bends real data to the contracts (unknown kind→opshop,
hours-clamp so only one shop is openLate, video-preferred landmark w/ fallback) and logs
it via {report}; selfcheck prints per-town (e.g. melbourne hoursClamped:5, openLate:video).
For F: three goldens to pin, gate keyed (seed, plansrc, town); selector gained {town} — see
LANE_A_NOTES R8. Screenshots docs/shots/laneA/osm-{melbourne,katoomba}.png.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
52eb1090ef |
Lane A round 6: second plan source ?plansrc=osm (real-data OSM import) — full seam
The carried-over OSM plan source (no-showed R4–R5) lands complete, invariants green — a second CityPlan producer behind the same contract, so B–F consume it unchanged. - osm_fixture.js: 95 REAL inner-Melbourne secondhand/charity/music/book/toy/antique shops, extracted deterministically from thriftgod city_source.json (Overpass cache), imported as a module ⇒ ZERO network. - plan_osm.js: generatePlanOSM(seed) — project lat/lon→metres, bin shops into latitude-band avenues off a spine (real row + real E–W order preserved), march into a valid non-overlapping CityPlan, centre on origin, report true 362×486 bbox, real shop names, one openLate video. - index.js: generatePlanFor(seed, source) selector — default 'synthetic' BYTE-IDENTICAL (golden 0x3fa36874 untouched); 'osm' → the importer. generatePlanOSM exported for F. - selfcheck.js: parameterized by source — OSM runs the full structural invariant suite (frontEdge/facing/no-overlap/chunk-coverage/finite/JSON/determinism/openLate) + its own golden 0x34cfdec0; synthetic-only brief checks skipped. ALL GREEN 1362/1362. - map.html: ?plansrc=osm renders it (reference wiring for F). Screenshot in docs/shots/laneA/. - CITY_SPEC: plan-source note; LANE_A_NOTES R6: seam + goldens + shape-diffs for F's gate (F2). Honest cut: street geometry regularized (real row+order drive it, exact metres do not); name-parody deferred. qa.sh --strict GREEN. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
5b8c806271 |
Lane A round 4: harden openLate contract (hours>=22 ⟺ openLate == the video), confirm F2
v1-tag round. Two confirmations + one hardening fix; qa.sh --strict GREEN (4/4).
A2 — openLate: F's night gate `hours[1] >= 22` matched 4–15 shops/seed (regular videos
jitter base-21 → 22), not the single landmark the shell assumes. Fixed in plan.js: regular
shops close by LATE_HOUR-1 (21:00); only the deterministically chosen openLate landmark
reaches ≥22, pick is now video-first. So `hours[1] >= 22` and the `openLate` field are the
same singleton, always the video rental (verified 15 seeds). Makes generation match
web/index.html:159-161 + soak.py:68 ("at night only the openLate shop is open"). selfcheck
asserts exactly-one / field⟺threshold / is-video. ALL GREEN 1301/1301.
A1 — Lane F's F2 permittedMax storeys scoping: confirmed 0 warnings across 7 seeds + a
false-negative test (injected video@2 in a scratch checker → caught every seed).
GOLDEN.hash 0x098eec2b → 0x3fa36874: intended A2 output change (a few videos close 21 not
22 for seed 20261990), NOT drift; F2 is tooling-only. Same lots/shops/types/names/skins.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
b20b3b08f5 |
Lane A round 3: verify F finding #5 (storeys) stale, harden selfcheck + document corner-anchor rule
Per ROUND3_INSTRUCTIONS 'Lane A — on-call + one verification': - F finding #5 (shops with storeys outside registry range) verified STALE across 8 seeds: zero violations. Single-storey types (video/milkbar/stall) never exceed 1; the only shops above registry max are the intentional 3-storey corner anchors (tall-capable types), exactly per CITY_SPEC. Round-1 cornerBoost gate already prevents the reported bug. This is also the source of qa.sh's 5 benign storeys warnings (flagged for Lane F to scope to permittedMax). - Hardened the selfcheck storeys assertion from the too-lax <=max(mx,3) to the exact permitted range (max>=2 ? min(max+1,3) : max), so a single-storey type exceeding 1 now fails loudly. Proven non-vacuous. selfcheck.js only — plan output/fingerprint unchanged (golden 0x098eec2b still matches, confirmed per task 2). - Documented the storeys corner-anchor rule in the CITY_SPEC schema. - hours/openLate contract unchanged; ready for Lane F's §3.5 consumer. qa.sh --strict GREEN (4/4). Committed atomically by pathspec (shared-tree race). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
3e98f05a52 |
Lane A: flag commit-4235060 mislabel for Fable (shared-tree race note)
My round-2 Lane A changes were committed under Lane C's message (
|
||
|
|
42350607a0 |
Lane C: keeper stand pose on the counter contract (Lane D/F integration)
Answers Lane F §8 (the counter is kind:'counter' in `places`) and closes the
keeper-spawn gap: buildInterior now returns room.counter = { mesh, pose, stand }
and tags the counter interactable with userData.keeperStand. `stand` = {x,z,ry}
where a shopkeeper stands (service side, facing the customer), in room-local
space, rig-front = local -Z per keepers.js. Deterministic; purely additive.
Verified in-browser: 36-build type sweep + 50-room soak — stand in-bounds,
faces customer (dot>0 all), carried on `places` (deep-equal), deterministic;
no change to existing placement, path, leaks, or perf (avg 3.6ms / worst 7.7ms,
geo/tex leak 0).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
8b7ca9aae4 |
Lane A (CityGen): deterministic town generator, registry, names, 2D map, self-check
Layer-1 CityPlan generator per CITY_SPEC schema v1 — pure data, no THREE, all randomness
through core/prng, deterministic + JSON-serializable + <1ms.
- web/js/citygen/plan.js: generatePlan(citySeed) → CityPlan (spine, cross-streets, market
square + dept anchor, arcade, warehouse fringe, residential collar w/ corner milkbars,
laneways) + chunkIndex (Amanatides–Woo edge supercover) + corner overlap-resolution pass.
- web/js/core/registry.js: SHOP_TYPES (all 9) + district weights + enums (shared vocabulary).
- web/js/citygen/names.js + wordlists.js: seeded 90s-AU shop/town names, 50+ patterns.
- web/js/citygen/index.js: canonical barrel entry (adopts Lane F's integration shim).
- web/map.html: standalone Canvas-2D plan debugger (pan/zoom/hover, layers, export JSON).
- web/js/citygen/selfcheck.js: node acceptance harness — determinism, golden fingerprint,
facing, within- AND cross-block no-overlap, chunk+edge coverage, finiteness, assets. ALL GREEN
(1271/1271) over 6 seeds. web/package.json ({"type":"module"}) lets node run it.
- docs/shots/laneA/: 5 seeds screenshotted, each reads as a town.
Fixes from an adversarial multi-agent review (15 confirmed defects): market facades faced the
wrong way; cross-block corner overlaps; chunkIndex skipped chunks incl. the origin/spine;
stall frontEdge z-band; doubled-possessive names; unparseable map road colour; +others.
CITY_SPEC amendment (treaty, same commit): shop-types table aligned to the registry lanes
import; documented lot.ry/frontEdge, block.kind/district-id, and web/package.json.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|