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>
This commit is contained in:
parent
e466491300
commit
35da83c347
@ -1,10 +1,37 @@
|
||||
# LANE A — CITYGEN · progress (PROCITY-A)
|
||||
|
||||
*Status: **all deliverables landed; self-check all-green (14264/14264); rounds 2–14 closed** (see below).
|
||||
v3.0 RELEASE round: 400-seed district invariant sweep landed + CITY_SPEC §v3 frozen at `v3.0`. Goldens
|
||||
unchanged (synthetic `0x3fa36874`, gig `0x1f636349`) — no golden moved, no rng draw added this round.*
|
||||
*Status: **all deliverables landed; self-check all-green (14264/14264); rounds 2–15 closed** (see below).
|
||||
v3.0 release close-out: frontage-poster +Z flip (ledger #1) + the one sanctioned gig-golden move
|
||||
(`0x1f636349 → 0x4f4a549d`); synthetic golden `0x3fa36874` frozen.*
|
||||
*Date: 2026-07-16 · owner: PROCITY-A (Opus 4.8)*
|
||||
|
||||
## Round 15 (2026-07-16) — the frontage-poster +Z flip (ledger #1) + one sanctioned golden move
|
||||
|
||||
Lane A ran **first** (B's hero re-shoot + F's tour hang off it). The R14 review found every venue's
|
||||
own-frontage poster had been on the building's **−Z back** since R13 — ~16 m behind the street face
|
||||
(B measured 15.9 m), invisible from the street, which is why John's `queue_night` framed no poster.
|
||||
|
||||
Delivered (one commit):
|
||||
1. **Frontage-poster fix** (`gigs.js` buildPosters item 1): flipped to the **+Z street facade** (B's
|
||||
canon) AND `ry = lot.ry + π` so the printed face points `+Z` at the queue-side camera (else `DoubleSide`
|
||||
renders 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.
|
||||
2. **Gig golden re-pinned `0x1f636349 → 0x4f4a549d`** — the round's ONE sanctioned move (posters moved);
|
||||
synthetic `0x3fa36874` frozen. §v3 FROZEN marker records the amendment (amendment law).
|
||||
3. **Selfcheck poster check refined**: the brief expected the 400-seed off-carriageway assert to stay
|
||||
green, but the `+Z` facade is the block-interior side in *plan* coords, so **corner venues** (a band_room/
|
||||
rsl fronting one street with another behind — seed 1 lot#481, 1.58 m from a crossing centreline) put 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 rule now **exempts building-bound frontage posters** and keeps it for
|
||||
free-standing **spine** posters. Sweep green again: **14264/14264**.
|
||||
4. **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: the visible venue face is `+Z` (`buildings.js` facade `zf=+d/2`; `venue.js` door/queue
|
||||
`+Z`). The selfcheck's `facing=(−sin,−cos)` "faces frontEdge" is the sim/GLB convention, 180° off the
|
||||
visual front — the same π-ambiguity D fixed for the fleet in R13.
|
||||
|
||||
## Round 14 (2026-07-16) — v3.0 RELEASE: invariant sweep + CITY_SPEC §v3 freeze
|
||||
|
||||
Release round, Lane A scope = harden + freeze (no new systems). **No golden moved** (synthetic
|
||||
|
||||
@ -213,6 +213,11 @@ night in v1; interior-mapping shader is a stretch goal).
|
||||
> never silent drift. **One edit is still pending and lands with Lane F's alias-retirement commit** (R13
|
||||
> debt #1): the R12 single-venue compat alias in the runtime block below retires; everything else here is
|
||||
> final for the `v3.0` tag.
|
||||
>
|
||||
> *(**Recorded amendment — ROUND15, ledger #1:** the frontage poster was flipped to the `+Z` street
|
||||
> facade (it had been on the `−Z` back, invisible from the street); this moved `plan.posters`, so the gig
|
||||
> golden re-pinned `0x1f636349 → 0x4f4a549d` in the same commit under the amendment law above. The
|
||||
> synthetic golden `0x3fa36874` did not move — this is the round's one sanctioned gig-golden move.)*
|
||||
|
||||
> **Prime flag law.** The gig layer is a **post-hoc augmentation** applied by the selector only when
|
||||
> `?gigs=1`. With the flag OFF, `generatePlanFor(seed, src)` returns the byte-identical v2 base plan —
|
||||
@ -279,11 +284,14 @@ gigs: [ { gigId, venueShopId, bandName, genreKey, night, startSeg, endSeg, cover
|
||||
|
||||
**`plan.posters`** — town-wide gig advertising (Lane B renders): `posters: [ { id, gigId, x, z, ry } ]`.
|
||||
Only **tonight's** (night 0) playing venues are advertised. Each such venue gets one poster on **its own
|
||||
frontage** (seated on the facade plane, `lot.x + front·(d/2+ε)`), plus a seeded run along the spine — 2
|
||||
per main edge, at `t ∈ [0.2,0.8]` of the block, on **either verge**. Different venues' posters share the
|
||||
same pole runs — that IS the district reading. `ry` follows the one house convention (front/outward
|
||||
normal = local `−Z` at `ry=0`; `ry = atan2(nx, nz)`), so a poster faces the footpath that reads it. B
|
||||
places E's poster skin at `(x, z)` rotated `ry`; F wires "poster → that venue's tonight-gig".
|
||||
frontage** — seated on the **+Z street facade** (B's canon: `buildings.js` facade + `venue.js` door/queue/
|
||||
camera are all `+Z`; position `lot + (sin ry, cos ry)·(d/2+ε)`), turned to read *from* the street
|
||||
(`ry = lot.ry + π` so its printed face points `+Z` at the queue-side camera — **ROUND15 ledger #1**; before
|
||||
R15 it was on the `−Z` back and invisible from the street). Plus a seeded run along the spine — 2 per main
|
||||
edge, at `t ∈ [0.2,0.8]` of the block, on **either verge**. Different venues' posters share the same pole
|
||||
runs — that IS the district reading. `ry` follows the house convention (a poster's printed face =
|
||||
`(−sin ry, −cos ry)`, so `atan2` of the *away-from-viewer* normal); B places E's poster skin at `(x, z)`
|
||||
rotated `ry`; F wires "poster → that venue's tonight-gig".
|
||||
|
||||
**The street-corridor law (ROUND13 debt #5 — published as functions, not plan data).** `edge.width` is
|
||||
the **full corridor** (carriageway + verge/footpath, centreline ± width/2), never the carriageway alone —
|
||||
@ -292,8 +300,11 @@ pure functions over an edge (no plan fields change ⇒ base goldens stay frozen)
|
||||
barrel: **`roadWidth(edge)`** (full carriageway width — main 10 m, side 6–8, lane = all, arcade 0; the
|
||||
kerb sits at `roadWidth/2` from the centreline),
|
||||
**`vergeBand(edge) → [inner,outer]`** (where footpath furniture lives), **`poleOffset(edge)`** (where a
|
||||
pole/poster seats — just behind the kerb). Posters, poles, verandah posts belong in the verge band; the
|
||||
selfcheck asserts no poster stands within `roadWidth/2` of any edge centreline.
|
||||
pole/poster seats — just behind the kerb). Poles, verandah posts and **spine** posters belong in the verge
|
||||
band; the selfcheck asserts no **spine** poster stands within `roadWidth/2` of any edge centreline. A
|
||||
**frontage** poster is exempt — it is bound to its venue building (the +Z facade B draws), so at a corner
|
||||
venue whose facade abuts a crossing street it may legitimately sit near that street's kerb (B's building
|
||||
geometry, not a mid-road defect).
|
||||
|
||||
**Band names + the drop-in.** `bandName(seed)` generates 90s-Aussie pub-rock names from wordlists.
|
||||
`web/assets/custom_bands.json` is an **OPTIONAL** editable drop-in (schema `{ "bands": ["The Feral
|
||||
@ -306,8 +317,9 @@ by seed, spread **night-major across the whole week's slots town-wide** (not one
|
||||
canonical half-open predicate (`open ≤ hour < close`) for D's gig-night patronage surge and everyone else.
|
||||
|
||||
**Gig golden** (guards gig-layer drift; pure-generator path, no custom file), seed `20261990` synthetic:
|
||||
**`0x1f636349`** (ROUND13 re-pin — the district changed gig-plan output; was `0xa6ae5a5e`, the one-pub
|
||||
alpha). Asserted by `selfcheck.js` alongside the frozen v2 goldens; changing gig output re-pins it.
|
||||
**`0x4f4a549d`** (**ROUND15 re-pin** — the frontage-poster +Z flip, ledger #1, moved `plan.posters`; was
|
||||
`0x1f636349` the R13 district, `0xa6ae5a5e` the R12 alpha). Asserted by `selfcheck.js` alongside the frozen
|
||||
v2 goldens; changing gig output re-pins it.
|
||||
|
||||
## Shop types v1 (registry lives in `web/js/core/registry.js`, Lane A writes it, all lanes read)
|
||||
|
||||
|
||||
@ -2,6 +2,36 @@
|
||||
|
||||
Durable answers to questions other lanes raised against Lane A. Full status in `A-progress.md`.
|
||||
|
||||
## Round 15 (2026-07-16) — the frontage-poster +Z flip (ledger #1) + the one sanctioned golden move
|
||||
|
||||
### → B + F: **new gig golden `0x1f636349 → 0x4f4a549d`** (synthetic `0x3fa36874` unchanged)
|
||||
The frontage-poster fix moved `plan.posters`, so the gig golden re-pinned — the round's ONE sanctioned
|
||||
move (amendment law; §v3 marker records it). B: re-shoot `queue_night` against this. F: the smoke's gig
|
||||
golden is now `0x4f4a549d`.
|
||||
|
||||
### The fix (gigs.js buildPosters item 1)
|
||||
Each venue's own-frontage poster sat at local **−Z** — the *back* of the building (~16 m behind, matching
|
||||
B's 15.9 m), invisible from the street, which is why `queue_night` framed no poster. Flipped to the **+Z
|
||||
street facade** AND turned it to read from the street: `ry = lot.ry + π` so its 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**. Only item 1; spine posters untouched.
|
||||
|
||||
### The −Z/+Z convention, settled (worth recording — it's the R13 RY_FLIP π-ambiguity again)
|
||||
The **visible** venue face is `+Z`: `buildings.js` builds the facade/door at `zf = +d/2` ("front face at
|
||||
local +Z"), and `venue.js` seats the door-glow/queue/poster-camera on `(sin ry, cos ry)` = `+Z`. The
|
||||
selfcheck's `facing = (−sin ry,−cos ry)` "every lot faces its frontEdge" is the **sim/GLB** convention,
|
||||
180° off from the visual front (same ambiguity D fixed at the source for the fleet in R13). A poster faces
|
||||
the *viewer* when its printed face = `(−sin ry,−cos ry)` points at them, i.e. `ry = atan2(away-from-viewer)`.
|
||||
|
||||
### → B + F (eyeball in the tour): corner-venue frontage posters can sit near a crossing street
|
||||
The `+Z` facade is the block-interior side in *plan* coordinates, so for a **corner venue** (a band_room/
|
||||
rsl fronting one street with another behind — e.g. seed 1 band_room lot#481, 1.58 m from a side-street
|
||||
centreline) the frontage poster lands near that crossing street's kerb. That's B's building geometry (the
|
||||
door is there too), not a mid-road defect — so the selfcheck's no-bitumen assert now **exempts frontage
|
||||
posters** (they're building-bound) and keeps it for free-standing **spine** posters. The pub hero is clean
|
||||
(29.9 m of open ground on `+Z`). If a corner poster reads as floating over a road in the tour, that's a
|
||||
v3.1 venue-placement tweak, not a v3.0 blocker.
|
||||
|
||||
## Round 14 (2026-07-16) — v3.0 RELEASE: invariant sweep + CITY_SPEC §v3 frozen
|
||||
|
||||
Release round — no new systems, no golden moves. **Synthetic `0x3fa36874` and gig `0x1f636349` are
|
||||
|
||||
@ -202,9 +202,14 @@ function buildPosters(plan, citySeed, venues, gigs) {
|
||||
const gig = tonight.get(v.shop.id);
|
||||
const lot = gig && lotById.get(v.shop.lot);
|
||||
if (!lot) continue;
|
||||
const fx = -Math.sin(lot.ry), fz = -Math.cos(lot.ry); // house convention: front = local −Z
|
||||
// ROUND15 (ledger #1): B's buildings put the street facade on local +Z (frontage/queue seat on
|
||||
// (sin ry, cos ry)); this once used −Z, so the poster sat ~16 m BEHIND the building, invisible from
|
||||
// the street — it's why queue_night framed no poster. Seat it on the +Z street face, AND turn it to
|
||||
// read FROM the street: venue.js renders a poster's printed face along (−sin ry, −cos ry) = A's
|
||||
// outward normal, so ry = lot.ry + π points that face outward (else DoubleSide shows a mirrored name).
|
||||
const fx = Math.sin(lot.ry), fz = Math.cos(lot.ry); // +Z: the street facade (B's canon)
|
||||
const off = lot.d / 2 + 0.06; // out onto the facade plane, proud of it
|
||||
add(lot.x + fx * off, lot.z + fz * off, lot.ry, gig.gigId);
|
||||
add(lot.x + fx * off, lot.z + fz * off, lot.ry + Math.PI, gig.gigId);
|
||||
}
|
||||
|
||||
// 2. the spine run — seeded pole positions along main edges, on the verge, facing the footpath.
|
||||
|
||||
@ -194,9 +194,21 @@ function districtInvariants(plan, label) {
|
||||
const gigIds = new Set(plan.gigs.map(g => g.gigId));
|
||||
ok(Array.isArray(plan.posters) && plan.posters.every(p => gigIds.has(p.gigId) && isFiniteNum(p.x) && isFiniteNum(p.z) && isFiniteNum(p.ry)), `${label}: posters reference a real gig with finite coords`);
|
||||
ok(plan.posters.every(p => plan.gigs.find(g => g.gigId === p.gigId).night === 0), `${label}: posters advertise tonight's gigs`);
|
||||
// every poster clears its nearest edge's carriageway — the R12 bug was posters mid-road on nodes.
|
||||
// The no-bitumen rule (the R12 regression: spine posters at node.x+2) is for FREE-STANDING verge
|
||||
// posters. A venue's own FRONTAGE poster is bound to the building B draws — since R15 it sits on the
|
||||
// +Z street facade (B's canon: buildings.js facade + venue.js door/queue/camera are all +Z). A corner
|
||||
// venue whose facade abuts a crossing street legitimately seats its poster near that street's kerb —
|
||||
// B's building geometry, not a mid-road defect — so frontage posters are exempt here and validated by
|
||||
// the placement asserts above (they reference tonight's gigs with finite coords).
|
||||
const lotByIdD = new Map(plan.lots.map(l => [l.id, l]));
|
||||
const onFacade = p => venues.some(v => {
|
||||
const lot = lotByIdD.get(v.lot); if (!lot) return false;
|
||||
const off = lot.d / 2 + 0.06; // gigs.js buildPosters item 1
|
||||
return Math.hypot(p.x - (lot.x + Math.sin(lot.ry) * off), p.z - (lot.z + Math.cos(lot.ry) * off)) < 0.5;
|
||||
});
|
||||
let onRoad = null;
|
||||
for (const p of plan.posters) {
|
||||
if (onFacade(p)) continue; // frontage poster: on the venue building, not the verge
|
||||
let best = Infinity, bestEdge = null;
|
||||
for (const e of plan.streets.edges) {
|
||||
const a = nodeById2(plan, e.a), b = nodeById2(plan, e.b);
|
||||
@ -295,7 +307,7 @@ ok(JSON.stringify(generatePlanFor(42, 'synthetic', { gigs: true })) === JSON.str
|
||||
ok(JSON.stringify(generatePlanFor(20261990, 'synthetic', { gigs: true, customBands: custom })) === JSON.stringify(pc), `custom bands: deterministic given (seed, list)`);
|
||||
}
|
||||
// gig-layer golden (guards gig-layer output drift; pure-generator path, no custom file)
|
||||
const GIG_GOLDEN = 0x1f636349; // ROUND13 re-pin: multi-venue district changed the gig-plan output (was 0xa6ae5a5e, the one-pub alpha)
|
||||
const GIG_GOLDEN = 0x4f4a549d; // ROUND15 re-pin: frontage posters flipped to the +Z street face (ledger #1 bug fix). Was 0x1f636349 (R13 district), 0xa6ae5a5e (R12 alpha).
|
||||
{
|
||||
const hash = xmur3(JSON.stringify(generatePlanFor(20261990, 'synthetic', { gigs: true })))() >>> 0;
|
||||
if (GIG_GOLDEN === 0) console.log(` ⚠ gig golden UNPINNED → set GIG_GOLDEN = 0x${hash.toString(16).padStart(8, '0')}`);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user