Lane A R37 (v8 wave 0 §0.1, ruling-side): the poster gate was VACUOUS — corrected to three arms with a permanent control
The audit's claim against my lane, re-measured and CONFIRMED exactly: on the default
boot (synthetic 20261990, gigs default-ON) there are 14 posters, all 14 stand inside
e.width/2 — the bitumen ground.js paints — and 0 stand inside the ruled kerb
roadWidth/2. One refinement it did not make: 12 are spine posters at poleOffset=6m,
8m inside the paint (genuinely mid-road); 2 are frontage posters clipping the corridor
edge by 0.06m (FACADE_PROUD past their venue's facade plane).
WHY the gate was green: my placer seats posters via poleOffset, which is DERIVED FROM
roadWidth, and my selfcheck asserted clearance against roadWidth/2. Gate and subject
were the same function agreeing with itself — the R27 cross-convention trap recurring
inside the very file whose header explains it. It never read a number that came from
Lane B, so no change to where the road is painted could make it fail.
The correction (selfcheck.js, districtInvariants), three arms:
1. no poster on a carriageway — measured through vergeBand(e)[0], the published law
itself, the same call B's ground now consumes, so gate and renderer move together
2. every SPINE poster stands INSIDE some edge's vergeBand — the outer bound the old
check never had ("not on the road" also passed for a poster in a paddock).
Frontage exempt BY MEASUREMENT: 18/108 gig plans have a frontage poster past every
corridor edge (worst 3.98m, launceston_real) via plan_osm's lot setback.
Spine violations over the same corpus: 0/108.
3. THE CONTROL — count posters standing on bitumen under the PRE-RULING ground
(?verge=0, road quad = full e.width) and assert it is NOT ZERO on every gig plan
(min 3 / max 212 / never 0 across 510 plans), pinned at EXACTLY 14 on the default
boot. A control allowed to drift toward zero is how a gate goes vacuous.
The replica is pinned to B's FLAG, not to a line number that will drift.
FALSIFIABILITY PROVEN. Simulated ?verge=0 honestly — vergeBand switched to the
pre-ruling reading, poleOffset pinned to the true band so the PLACER stays
byte-identical (it is a render flag: paint changes, plan does not; fingerprint and
every gig golden green in both runs, so the gate's reading is the only variable):
corrected (R37) gate → FAIL, 1020 failures (2 arms x 510 plans)
pre-R37 (HEAD) gate → ALL GREEN 156,352/156,352 — structurally blind
GOLDENS: NOTHING MOVED, ZERO RE-PINS. 0x5f76e76, GIG_GOLDEN 0xec7a2d39, 25 base town
goldens and 24 real-town gig goldens all untouched — correct and predicted, since the
only generator-adjacent file changed is the selfcheck, which validates output and never
produces it. 156,352 -> 157,407 checks (+1,055), 10.3s.
Corridor law CONFIRMED for Lane B, semantics unchanged, contract published in full
(LANE_A_NOTES §37) with four hazards flagged loudly while B consumes it in parallel:
roadWidth and edge.width are both FULL widths but one is carriageway and one corridor
(that naming IS why this bug existed); lane's band is NOT the literal [2,2] the round
instructions state (2 synthetic edges are, 56 real lane edges are [4,4] — branch on
outer<=inner); arcade is all footpath with coincident kerbs to skip; the inward
extension never inverts (0 of 31,039 edges). Two charter numbers corrected: the "9m
band / 18m of every main" figures are synthetic-only — on every real town a main is
24m => 7m band, and the corpus's dominant edge is side@12 at 22,415/31,039 (72%) with
a 3m footpath.
FILED, NOT FIXED — v8 debt ledger, four entries (LANE_A_NOTES §37): D1 chunkIndex
(two impls, THREE divergences, header comment promises a swap that would break three
ways — owner B) · D2 isOpen (three impls + an ad-hoc fourth site; A's canonical one has
ZERO importers; the live shell copy treats no-hours as CLOSED where A's law says OPEN —
latent until v8 adds an hours-less lot — owner F) · D3 two shop registries (B's missing
all three venue kinds => buildings.js:344 renders op-shop signage on every gig venue
since R13 — owner B) · D4 NEW, mine: the poster gate's inner bound is NEAREST-EDGE and
an arcade (kerb 0) camouflages a real carriageway — 8 real-town plans hide a spine
poster up to 1.78m inside a main, 0 on synthetic. Cost measured decision-grade:
synthetic 0/4 plans move, 11/26 town gig goldens re-pin, poster counts unchanged.
Deferred to R38 on purpose — it moves plan output for a reason that is NOT the kerb
ruling, and the "did the kerb ruling move a golden?" answer must stay a clean no.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
62c0a2185d
commit
e4d77629c5
@ -1,8 +1,73 @@
|
|||||||
# LANE A — CITYGEN · progress (PROCITY-A)
|
# LANE A — CITYGEN · progress (PROCITY-A)
|
||||||
|
|
||||||
*Status: **all deliverables landed; self-check ALL GREEN (156,352/156,352); rounds 2–30 closed**.
|
*Status: **all deliverables landed; self-check ALL GREEN (157,407/157,407); rounds 2–30 + 37 closed**.
|
||||||
R30 (v7.0-alpha ledger #6): the rotation boundary VERIFIED — F's `day` salt rides runtime streams only,
|
R37 (v8 wave 0 §0.1): the poster-clearance gate was VACUOUS — it validated my own placer against my own
|
||||||
plan generation structurally cannot receive it; all goldens frozen, zero re-pins.*
|
law and stayed green while all 14 posters on the default boot stood on B's bitumen. Corrected to three
|
||||||
|
arms with a permanent control; proven to fail on the pre-ruling geometry where the old gate cannot.
|
||||||
|
All goldens frozen, zero re-pins.*
|
||||||
|
|
||||||
|
## Round 37 (2026-08-03) — v8 WAVE 0 §0.1: THE KERB (ruling-side) — the gate I owned was the vacuous one
|
||||||
|
|
||||||
|
Full detail in LANE_A_NOTES §37. Four jobs, all measured before they were written.
|
||||||
|
|
||||||
|
**1. Verified the audit against my own lane — CONFIRMED, exactly, with one refinement it did not make.**
|
||||||
|
Default boot (synthetic, seed 20261990, gigs default-ON): **14 posters, all 14 inside `e.width/2` (the
|
||||||
|
bitumen B paints), 0 inside the ruled kerb `roadWidth/2`.** The refinement: they are two populations —
|
||||||
|
**12 spine posters at `poleOffset` = 6 m are 8 m inside the paint (genuinely mid-road); 2 frontage posters
|
||||||
|
clip the corridor edge by 0.06 m** (13.94 of 14, 6.94 of 7 — `FACADE_PROUD` pushes them a fingernail past
|
||||||
|
their venue's facade plane). Both are inside the paint; "14 in the middle of the road" would over-claim.
|
||||||
|
Also confirmed: B's `ground.js` road quad is `hQuad(…, e.width, 0)` — the full corridor, kerbs at
|
||||||
|
`e.width/2 + 0.12`, nine metres outside mine on a main.
|
||||||
|
|
||||||
|
**2. Diagnosed WHY the gate was green, and it is our own documented lesson recurring.** My placer seats
|
||||||
|
posters via `poleOffset`, which is *derived from* `roadWidth`; my selfcheck asserted clearance against
|
||||||
|
`roadWidth/2`. Gate and subject were the same function agreeing with itself — the R27 cross-convention
|
||||||
|
trap, inside the very file whose header (`selfcheck.js:33-40`) explains it. It never read a number that
|
||||||
|
came from B, so no change to the street could make it fail.
|
||||||
|
|
||||||
|
**3. Corrected it — three arms, the third a permanent control.** (1) no poster on a carriageway, measured
|
||||||
|
through `vergeBand(e)[0]`, the published law itself — the same call B's ground now consumes; (2) every
|
||||||
|
**spine** poster stands *inside* some edge's `vergeBand` (the outer bound the old check never had —
|
||||||
|
frontage exempt **by measurement**: on 18/108 gig plans a frontage poster legitimately stands past every
|
||||||
|
corridor edge, worst 3.98 m, launceston_real; spine violations 0/108); (3) **the control** — count the
|
||||||
|
posters that would stand on bitumen under the pre-ruling `?verge=0` ground and assert it is **> 0** on
|
||||||
|
every gig plan (measured min 3 / max 212 / never 0 across 510 plans), **pinned at exactly 14** on the
|
||||||
|
default boot, because a control allowed to drift to zero is how a gate goes vacuous in the first place.
|
||||||
|
The replica is pinned to B's **flag**, not to a line number that will drift as B edits.
|
||||||
|
|
||||||
|
**Proved it fails on the old geometry, and that the old gate cannot.** Simulated `?verge=0` honestly —
|
||||||
|
`vergeBand` switched to the pre-ruling reading, `poleOffset` pinned to the true band so the **placer is
|
||||||
|
byte-identical** (it is a render flag: the paint changes, the plan does not; fingerprint and every gig
|
||||||
|
golden stayed green in both runs, so the gate's reading is the only variable). **Corrected gate: ✗ FAIL,
|
||||||
|
1020 failures — 2 arms × 510 plans. Pre-R37 gate: ✓ ALL GREEN 156,352/156,352.**
|
||||||
|
|
||||||
|
**4. Confirmed the corridor-law exports for B and published the whole contract** (LANE_A_NOTES §37 —
|
||||||
|
B is consuming them in a parallel session, so it is written as a warning, not a reference). Semantics
|
||||||
|
unchanged; nothing ambiguous was altered mid-round. Flagged loudly: `roadWidth` returns a **full** width
|
||||||
|
and so does `edge.width`, but one is carriageway and the other corridor — that naming is *why* this bug
|
||||||
|
existed; **`lane`'s band is not the literal `[2,2]` the round instructions state** (2 synthetic edges are,
|
||||||
|
**56 real lane edges are `[4,4]`** — branch on `outer <= inner`); `arcade` is all footpath with coincident
|
||||||
|
kerbs to skip; and the inward extension **never inverts** (`roadWidth > e.width`: **0 of 31,039 edges**,
|
||||||
|
though a `side` under 6 m would — guard it). Two charter numbers corrected: the "9 m band / 18 m of every
|
||||||
|
main" figures are **synthetic-only** (main 28 m); **on all real towns a main is 24 m ⇒ 7 m band**, and the
|
||||||
|
corpus's dominant edge is `side`@12 — **22,415 of 31,039 (72%)**, a **3 m** footpath.
|
||||||
|
|
||||||
|
**GOLDEN VERDICT: nothing moved, zero re-pins** — correct and predicted, since the only file I changed on
|
||||||
|
the generator side is the *selfcheck*, which validates output and never produces it. `0x5f76e76`,
|
||||||
|
`GIG_GOLDEN 0xec7a2d39`, 25 base town goldens and 24 real-town gig goldens all green and untouched.
|
||||||
|
Checks **156,352 → 157,407** (+1,055), runtime 10.3 s.
|
||||||
|
|
||||||
|
**Filed, not fixed — v8 debt ledger, four entries** (LANE_A_NOTES §37): D1 `chunkIndex` (two impls, three
|
||||||
|
divergences, and a header comment promising a swap that would break three ways — owner B); D2 `isOpen`
|
||||||
|
(three impls plus an ad-hoc fourth site; A's canonical one has **zero importers**; the live shell copy
|
||||||
|
treats *no hours* as **closed** where A's law says *open* — latent today, fires the moment v8 adds an
|
||||||
|
hours-less lot — owner F); D3 two shop registries (B's missing all three venue kinds ⇒ `buildings.js:344`
|
||||||
|
falls back to **op-shop** signage on every gig venue since R13 — owner B); **D4, new, found this round**:
|
||||||
|
my own poster gate's inner bound is **nearest-edge**, and an `arcade` (kerb 0) camouflages a real
|
||||||
|
carriageway — 8 real-town plans hide a spine poster up to **1.78 m inside a main**, zero on synthetic.
|
||||||
|
Cost measured decision-grade: synthetic **0/4 plans move**, **11/26 town gig goldens re-pin**, poster
|
||||||
|
counts unchanged. Deliberately deferred to R38 — it moves plan output for a reason that is not the kerb
|
||||||
|
ruling, and the "did the kerb ruling move a golden?" answer must stay a clean **no**.
|
||||||
|
|
||||||
## Round 30 (2026-07-18) — the rotation boundary verify (ledger #6, small round as briefed)
|
## Round 30 (2026-07-18) — the rotation boundary verify (ledger #6, small round as briefed)
|
||||||
|
|
||||||
|
|||||||
@ -394,10 +394,28 @@ barrel: **`roadWidth(edge)`** (full carriageway width — main 10 m, side 6–8,
|
|||||||
kerb sits at `roadWidth/2` from the centreline),
|
kerb sits at `roadWidth/2` from the centreline),
|
||||||
**`vergeBand(edge) → [inner,outer]`** (where footpath furniture lives), **`poleOffset(edge)`** (where a
|
**`vergeBand(edge) → [inner,outer]`** (where footpath furniture lives), **`poleOffset(edge)`** (where a
|
||||||
pole/poster seats — just behind the kerb). Poles, verandah posts and **spine** posters belong in the verge
|
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
|
band. A **frontage** poster is exempt from the band — it is bound to its venue building (the +Z facade B
|
||||||
**frontage** poster is exempt — it is bound to its venue building (the +Z facade B draws), so at a corner
|
draws), so at a corner venue whose facade abuts a crossing street it may legitimately sit near that
|
||||||
venue whose facade abuts a crossing street it may legitimately sit near that street's kerb (B's building
|
street's kerb (B's building geometry, not a mid-road defect); on a real town it may legitimately stand
|
||||||
geometry, not a mid-road defect).
|
**past** every corridor edge, because `plan_osm.js` sets a lot back at `max(KERB, roadWidth/2 + FOOTPATH)`
|
||||||
|
— measured worst 3.98 m (launceston_real, R37).
|
||||||
|
|
||||||
|
**ROUND37 — THE KERB IS FOOTPATH (John's ruling), and the poster gate that was green over a wrong
|
||||||
|
street.** The band between `roadWidth(e)/2` and `e.width/2` is **footpath**, and Lane B's ground paints
|
||||||
|
it as footpath rather than as road. The selfcheck's poster-clearance check used to ask one question —
|
||||||
|
"is the poster outside `roadWidth/2`?" — which A's own placer already guaranteed, because `poleOffset` is
|
||||||
|
*derived from* `roadWidth`. Gate and subject were the same function agreeing with itself, so it stayed
|
||||||
|
green for 24 rounds while all **14** gig posters on the default boot stood on painted bitumen. It is now
|
||||||
|
**three arms**: (1) no poster on a carriageway, measured through `vergeBand(e)[0]` — the published law
|
||||||
|
itself, the same call B's ground consumes, so gate and renderer cannot drift apart; (2) every **spine**
|
||||||
|
poster stands *inside* some edge's `vergeBand` (the bound the old check never had — "not on the road"
|
||||||
|
also passed for a poster in a paddock); (3) **the control** — count the posters that would stand on
|
||||||
|
bitumen under the pre-ruling ground (`?verge=0`, road quad = full `e.width`) and assert that count is
|
||||||
|
**not zero**, pinned at exactly 14 on the default boot. Arms 1–2 prove nothing unless arm 3 shows the two
|
||||||
|
geometries are distinguishable. Proof of falsifiability, measured: with `vergeBand` switched to the
|
||||||
|
pre-ruling reading and the placer held byte-identical, the corrected gate goes **red 1020×** (2 arms ×
|
||||||
|
510 plans) while the pre-R37 gate is **ALL GREEN 156,352/156,352** — structurally blind to where the
|
||||||
|
road is painted.
|
||||||
|
|
||||||
**Band names + the drop-in.** `bandName(seed)` generates 90s-Aussie pub-rock names from wordlists.
|
**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
|
`web/assets/custom_bands.json` is an **OPTIONAL** editable drop-in (schema `{ "bands": ["The Feral
|
||||||
|
|||||||
@ -2,6 +2,194 @@
|
|||||||
|
|
||||||
Durable answers to questions other lanes raised against Lane A. Full status in `A-progress.md`.
|
Durable answers to questions other lanes raised against Lane A. Full status in `A-progress.md`.
|
||||||
|
|
||||||
|
## Round 37 (2026-08-03) — v8 WAVE 0 §0.1: THE KERB, and the gate that was green over a wrong street
|
||||||
|
|
||||||
|
### → Lane B (URGENT, you are consuming these RIGHT NOW): the corridor law, stated plainly
|
||||||
|
|
||||||
|
**The exports are correct and you should consume them as-is. I changed no semantics this round.**
|
||||||
|
`roadWidth` / `vergeBand` / `poleOffset` in `web/js/core/registry.js:217-240`, re-exported from the
|
||||||
|
barrel `citygen/index.js:18`. But **four things about them will bite you**, and three of them are things
|
||||||
|
the round instructions state in a way that is true only for the synthetic town:
|
||||||
|
|
||||||
|
**1. `roadWidth` is a TRAP OF A NAME, and it is why this bug existed.** It returns a **full width**, and
|
||||||
|
`edge.width` is *also* a full width — but `edge.width` is the **corridor** (road + both footpaths) and
|
||||||
|
`roadWidth(e)` is the **carriageway alone**. Two full widths, similar names, nine metres apart on a main.
|
||||||
|
Your `ground.js` painted the road quad `e.width` wide for 34 rounds because of exactly this. The kerb is
|
||||||
|
at **`roadWidth(e)/2`**, i.e. `vergeBand(e)[0]`. Prefer `vergeBand(e)[0]` over `roadWidth(e)/2` in new
|
||||||
|
code — same number by construction, but it reads as what it is and it survives a change to the split.
|
||||||
|
|
||||||
|
**2. `lane`'s verge band is NOT `[2,2]`.** The round instructions say it is; that is the **synthetic**
|
||||||
|
lane (width 4). Measured over 31,039 edges across synthetic + all 26 town caches: **58 lane edges, 2 at
|
||||||
|
`[2,2]` (synthetic, width 4) and 56 at `[4,4]` (real, width 8).** The invariant is not a literal — it is
|
||||||
|
**`outer === inner` ⇒ the edge has no footpath at all** (a lane is all carriageway by law). **Branch on
|
||||||
|
`outer <= inner`, never on the number 2**, or you emit a zero-width strip on the synthetic town and a
|
||||||
|
wrong-width one on every real town.
|
||||||
|
|
||||||
|
**3. `arcade` is `roadWidth 0` ⇒ band `[0, width/2]` — the WHOLE corridor is footpath.** 1,102 arcade
|
||||||
|
edges in the corpus (1 synthetic at width 5, 1,101 real at width 6). Skip the road quad *and* both kerb
|
||||||
|
strips: at `roadWidth 0` your two kerbs are coincident on the centreline and will z-fight.
|
||||||
|
|
||||||
|
**4. The inward extension is never negative — measured, not assumed.** `roadWidth(e) > e.width` would
|
||||||
|
make your inward footpath strip negative-width. **0 occurrences in 31,039 edges.** It is nonetheless
|
||||||
|
*reachable*: `side` returns a flat 6 for any width < 18, so a `side` edge narrower than 6 m would invert.
|
||||||
|
No such edge exists in any shipped cache. Guard it anyway (`Math.max(0, …)`) — it costs a call.
|
||||||
|
|
||||||
|
**The whole contract, exhaustively — the entire corpus reduces to nine (kind, width) pairs:**
|
||||||
|
|
||||||
|
| kind | `edge.width` | `roadWidth` | `vergeBand` | footpath each side | `poleOffset` | count | where |
|
||||||
|
|---|---|---|---|---|---|---|---|
|
||||||
|
| `arcade` | 5 | 0 | `[0, 2.5]` | 2.5 | 1 | 1 | synthetic |
|
||||||
|
| `arcade` | 6 | 0 | `[0, 3]` | 3 | 1 | 1,101 | real |
|
||||||
|
| `lane` | 4 | 4 | `[2, 2]` | **0** | 2 | 2 | synthetic |
|
||||||
|
| `lane` | 8 | 8 | `[4, 4]` | **0** | 4 | 56 | real |
|
||||||
|
| `main` | **24** | 10 | `[5, 12]` | **7** | 6 | 7,446 | **real** |
|
||||||
|
| `main` | 28 | 10 | `[5, 14]` | 9 | 6 | 6 | synthetic |
|
||||||
|
| `side` | 12 | 6 | `[3, 6]` | 3 | 4 | **22,415** | both |
|
||||||
|
| `side` | 14 | 6 | `[3, 7]` | 4 | 4 | 8 | synthetic |
|
||||||
|
| `side` | 20 | 8 | `[4, 10]` | 6 | 5 | 4 | synthetic |
|
||||||
|
|
||||||
|
**Two corrections to the charter's numbers, both measured.** The charter and the audit both describe
|
||||||
|
"the 9 m band" and "18 m of every main street stops being painted as road". **That is the synthetic town
|
||||||
|
only** — its main is 28 m wide. **On every real town a main is 24 m**, so the band is **7 m** and 14 m of
|
||||||
|
each main stops being road. And the dominant edge in the whole corpus is not a main at all: **`side` at
|
||||||
|
width 12 is 22,415 of 31,039 edges (72%)**, with a **3 m** footpath. Size your tri estimate off that, not
|
||||||
|
off the 9 m headline. (The +0 draws claim is yours to prove; I have no visibility into your merge.)
|
||||||
|
|
||||||
|
**On `?verge=0`:** keep it reverting to *exactly* the pre-ruling geometry — road quad at the full
|
||||||
|
`e.width`, kerb at `e.width/2 + 0.12`, footpaths outside the corridor. My selfcheck now pins the count of
|
||||||
|
posters standing on that geometry at **exactly 14** on the default boot, and Lane F's control leg asserts
|
||||||
|
the same failure at runtime. If `?verge=0` drifts into something that is not the pre-ruling street, three
|
||||||
|
gates in two lanes stop meaning what they say.
|
||||||
|
|
||||||
|
### → Fable / Lane F: the vacuous gate was mine, and it is now falsifiable — with the proof
|
||||||
|
|
||||||
|
**The audit's claim against my lane is CONFIRMED, exactly, and I can add a number it did not have.**
|
||||||
|
Default boot (synthetic, golden seed 20261990, gigs default-ON since R16): **14 posters. All 14 stand
|
||||||
|
inside `e.width/2` — the bitumen B paints. Zero stand inside the ruled kerb `roadWidth/2`.** The audit's
|
||||||
|
"all 14 gig posters are standing in the road" is precise, not rhetorical.
|
||||||
|
|
||||||
|
*One honest refinement it did not make:* the 14 are not one population. **12 are spine posters seated at
|
||||||
|
`poleOffset` = 6 m, i.e. 8 m inside painted bitumen — genuinely mid-road.** The other **2 are frontage
|
||||||
|
posters clipping the corridor edge by 0.06 m** (13.94 m of 14, and 6.94 m of 7) — they sit on their
|
||||||
|
venue's facade plane, and `FACADE_PROUD = 0.06` pushes them a fingernail past it. Both classes are inside
|
||||||
|
the paint and the fix lands both, but "14 posters standing in the middle of the road" would be an
|
||||||
|
over-claim: **12 are, 2 are 6 cm over the kerb line.**
|
||||||
|
|
||||||
|
**Why the gate was green.** My placer seats spine posters via `poleOffset(e)`, which is *derived from*
|
||||||
|
`roadWidth`. My selfcheck asserted clearance against `roadWidth(e)/2`. **The gate and its subject were
|
||||||
|
the same function agreeing with itself** — the R27 cross-convention lesson recurring inside the very file
|
||||||
|
that documents it (`selfcheck.js:33-40` already says a self-consistent check over a self-contradicting
|
||||||
|
spec passes under either convention). It could not see B's geometry because it never read a number that
|
||||||
|
came from B.
|
||||||
|
|
||||||
|
**The correction (`selfcheck.js`, districtInvariants), three arms — arm 3 is the control:**
|
||||||
|
1. **No poster on a carriageway** — now measured through `vergeBand(e)[0]`, the published law itself, the
|
||||||
|
same call B's ground consumes. Floors unchanged (frontage ≥ `POSTER_CLEAR`−0.02, spine ≥ 0; a `lane`
|
||||||
|
pole seats exactly *on* its kerb, so 0 must stay legal).
|
||||||
|
2. **Every SPINE poster stands INSIDE some edge's `vergeBand`** — the bound the old check never had.
|
||||||
|
"Not on the road" also passed for a poster standing in a paddock; this asserts it stands on paint B
|
||||||
|
actually lays. Frontage posters exempt **by measurement, not convenience**: on 18 of 108 gig plans a
|
||||||
|
frontage poster legitimately stands past every corridor edge (worst **3.98 m**, launceston_real),
|
||||||
|
because `plan_osm.js:459` sets a real-town lot back at `max(KERB, roadWidth/2 + FOOTPATH)`. Spine
|
||||||
|
violations over the same corpus: **0/108**.
|
||||||
|
3. **THE CONTROL** — count the posters that would stand on bitumen under the **pre-ruling** ground (B's
|
||||||
|
road quad at full `e.width`; the `?verge=0` geometry, replicated in `preRulingRoadPosters()` and
|
||||||
|
pinned to the **flag**, not to a line number that will drift as B edits). Assert it is **> 0** on every
|
||||||
|
gig plan, and **exactly 14** on the default boot. Arms 1–2 prove nothing unless the two geometries are
|
||||||
|
distinguishable; this is what makes them non-vacuous, and pinning 14 rather than `> 0` alone is
|
||||||
|
deliberate — *a control allowed to drift toward zero is how a gate goes vacuous in the first place.*
|
||||||
|
Measured range across 510 plans: **min 3, max 212, never 0.**
|
||||||
|
|
||||||
|
**THE FALSIFIABILITY PROOF — the new gate fails on the old street, the old gate cannot.** Simulated
|
||||||
|
`?verge=0` honestly: switched `vergeBand` to the pre-ruling reading (`[width/2, width/2]` — whole
|
||||||
|
corridor is carriageway) in a scratch copy of the tree, and **pinned `poleOffset` to the true band so the
|
||||||
|
placer is byte-identical** — `?verge=0` is a *render* flag, the paint changes and A's plan does not.
|
||||||
|
Fingerprint `0x5f76e76` and every gig golden stayed green in both runs, so the only variable is what the
|
||||||
|
gate reads. Result:
|
||||||
|
|
||||||
|
| gate | under the ruled geometry | under `?verge=0` geometry |
|
||||||
|
|---|---|---|
|
||||||
|
| **corrected (R37)** | ALL GREEN 157,407/157,407 | **✗ FAIL — 1020 failures** (2 arms × 510 plans) |
|
||||||
|
| **pre-R37 (HEAD)** | ALL GREEN 156,352/156,352 | **✓ ALL GREEN 156,352/156,352** |
|
||||||
|
|
||||||
|
The old gate is not merely wrong about the street — it is **structurally blind to it**. No change to
|
||||||
|
where the road is painted can make it fail. That is the vacuous-gate species in one table.
|
||||||
|
|
||||||
|
**GOLDEN VERDICT: NOTHING MOVED. Zero re-pins.** Fingerprint `0x5f76e76`, `GIG_GOLDEN 0xec7a2d39`, all
|
||||||
|
25 base town goldens and all 24 `REAL_TOWN_GIG_GOLDENS` green and untouched. Correct, and predicted: the
|
||||||
|
only generator-adjacent file I touched is the *selfcheck*, which validates output and never produces it.
|
||||||
|
Check count **156,352 → 157,407** (+1,055 new assertions), runtime 10.3 s.
|
||||||
|
|
||||||
|
### → Fable: v8 DEBT LEDGER — filed, not fixed (four entries, three of them the audit's)
|
||||||
|
|
||||||
|
**D1 — `chunkIndex`: two implementations, THREE divergences, and a header comment that is false.**
|
||||||
|
A's `citygen/plan.js:414` `chunkIndex(plan, chunkSize = CHUNK)` vs B's `world/planutil.js:37`
|
||||||
|
`chunkIndex(plan)`. The audit named one divergence; there are three:
|
||||||
|
(a) **bucketing** — A puts a lot in every chunk its rotated-AABB touches, B puts it in the chunk
|
||||||
|
containing its centre only; (b) **container** — A returns a plain object keyed `"cx,cz"`, B returns a
|
||||||
|
`Map`; (c) **element type** — A's buckets hold **ids** (`lots:[lot.id]`), B's hold **objects**
|
||||||
|
(`lots:[lot]`). `planutil.js:4` says *"If Lane A later ships an official chunkIndex(plan) we swap the
|
||||||
|
import; the shapes match."* — **the shapes do not match, on any of the three axes**, and that sentence is
|
||||||
|
the trap: it invites exactly the one-line swap that would break the streamer three ways at once.
|
||||||
|
Consumers are split today: **the runtime streamer uses B's** (`chunks.js:7,16`), **the debug map uses
|
||||||
|
A's** (`map.html:89,315`), and `sim.js:48-55` re-derives the key math a *third* time, locally, on purpose
|
||||||
|
(so the standalone sim page needs no Lane B module) — that third copy is defensible and documented.
|
||||||
|
*Canonical:* **B's for the runtime** (centre-bucketing is what a streamer wants — an AABB-spanning lot
|
||||||
|
would build in up to four chunks). A's AABB form is right for *coverage* questions, which is what my own
|
||||||
|
selfcheck asks of it (`selfcheck.js:130-155`). **Cost:** rename, not reconcile — give them distinct names
|
||||||
|
(`chunkIndexByCentre` / `chunkIndexByCoverage`), delete the false comment, and state which question each
|
||||||
|
answers. Half a round. **Owner: B** (the file and the runtime consumer are B's); A supplies the rename.
|
||||||
|
|
||||||
|
**D2 — `isOpen`: three real implementations plus an ad-hoc fourth site, and A's canonical one has ZERO
|
||||||
|
importers.** Canonical: `citygen/plan.js:28`, half-open `open ≤ hour < close`, **no hours ⇒ open**,
|
||||||
|
re-exported at `citygen/index.js:10`. **Nobody imports it** — grep-verified across `world/`, `citizens/`,
|
||||||
|
`interiors/`. The live one is `web/index.html:454`, published to `window.PROCITY.isOpen` (`:603`) and
|
||||||
|
consumed by `world/audio.js:270` and **14 call sites across `tools/`** (`flags_check.py`, `shots.py`,
|
||||||
|
`v2_tour.py`, `qa/interior_scale_check.py`). **It has a real semantic divergence:**
|
||||||
|
`shop && shop.hours && …` returns **falsy for a shop with no hours**, where A's law says *no hours ⇒
|
||||||
|
always open*. Third: `citizens/sim.js:363` `_openAt(hours)` — A's semantics, but its own clock
|
||||||
|
(`(this.timeOfDay % 1) * 24`) instead of `currentHour()`. Fourth site, ad-hoc rather than a rewrite:
|
||||||
|
`world/dbg.js:241,279,286` inline hour predicates (`hours[1] >= 22`, `hours[0] <= 12 && hours[1] > 13`)
|
||||||
|
for screenshot bookmarks. **No shipped shop lacks `hours`** (my selfcheck asserts every shop has sane
|
||||||
|
hours), so the divergence is **latent, not live** — it fires the day a venue, cart, stall or civic lot
|
||||||
|
carries no hours, which v8's whole slate is about adding. **Cost:** the shell imports A's `isOpen` and
|
||||||
|
passes `currentHour()`; sim keeps its clock but calls the same predicate; ~5 lines, 1 line of risk.
|
||||||
|
**Owner: F** (the shell is F's; A's export is already correct and needs no change).
|
||||||
|
|
||||||
|
**D3 — two shop registries, and the venue signs are the visible bite.** A's `core/registry.js:32`
|
||||||
|
`SHOP_TYPES` = 12 types with `sign:{bg,fg,accent,style}`; B's `world/fixture_plan.js:28` `SHOP_REGISTRY`
|
||||||
|
= **9 types**, missing `pub` / `band_room` / `rsl` entirely, with only `signBg`/`signFg`. Its own header
|
||||||
|
(`:26-27`) says *"Lane A owns web/js/core/registry.js; it hasn't landed yet, so Lane B carries the slice
|
||||||
|
it needs"* — **registry.js landed in R13; that comment has been stale for 24 rounds.** The bite is one
|
||||||
|
line: `buildings.js:344` `const reg = SHOP_REGISTRY[shop.type] || SHOP_REGISTRY.opshop;` — so every gig
|
||||||
|
venue renders **op-shop** signage (`#2c2820` on `#f0e2c0`) instead of the registry's gilt / stencil / club
|
||||||
|
palettes, on 2–4 venues per town across 27 towns, since R13. Confirmed as the audit reported it.
|
||||||
|
*Also drifted, but harmless:* the facade pools differ on four types (`toy` 3→2, `book` 3→2, `pawn` 4→3,
|
||||||
|
`stall` 2→1) — **dead config on the live path**, because `buildings.js:405` takes the skin from
|
||||||
|
`shop.facadeSkin` (A's plan field); B's pool is only reachable on the `fixture_plan` fallback when citygen
|
||||||
|
is absent (`index.html:138`). **Cost:** `buildings.js` imports A's `SHOP_TYPES` and reads
|
||||||
|
`.sign.bg`/`.sign.fg`; `SHOP_REGISTRY` shrinks to the fallback-only table it actually is, with an honest
|
||||||
|
header. Sign atlas colours change on venue lots ⇒ **a screenshot golden may move; not a plan golden.**
|
||||||
|
Half a round. **Owner: B**, with F re-pinning any shot.
|
||||||
|
|
||||||
|
**D4 — NEW, found this round, and it is the same disease one layer down: the poster gate's inner bound
|
||||||
|
is NEAREST-EDGE, and an `arcade` edge camouflages a carriageway.** Both my selfcheck's arm 1 and my
|
||||||
|
placer's `gigs.js:304 onCarriageway()` resolve the *nearest* edge and test against that one edge's kerb.
|
||||||
|
The nearest edge is not always the binding one. Measured over 108 gig plans: the nearest-edge rule reports
|
||||||
|
**0 violations**; an **all-edges** rule finds **8 plans** (all real towns) where a spine poster stands
|
||||||
|
inside a *non-nearest* edge's carriageway — **worst 1.78 m inside a main on northbridge_real seed 42**,
|
||||||
|
where the nearest edge is an `arcade` at 3.22 m whose `roadWidth` is **0**, so it "clears" by 1.45 m and
|
||||||
|
hides a main whose kerb is 5 m away. `arcade` edges are actively camouflaging: kerb 0 means they win the
|
||||||
|
nearest-edge test and always pass it. **Zero occurrences on synthetic, including the default boot** — the
|
||||||
|
kerb ruling is unaffected. **Cost, measured decision-grade, not estimated:** I built the all-edges variant
|
||||||
|
and diffed the whole corpus — **synthetic 0/4 plans move** (so `0x5f76e76`, `GIG_GOLDEN` and the classic
|
||||||
|
covenant are untouched), **11 of 26 town gig goldens re-pin**, and **poster counts do not change at all**
|
||||||
|
(the R20 cap re-subsamples a smaller candidate pool to the same size). So: one placer edit, one gate edit,
|
||||||
|
11 hash re-pins, no budget change, no visual count change. **Deliberately NOT done this round**: it moves
|
||||||
|
plan output for a reason that is *not* the kerb ruling, in a shared tree, while F is gating the matrix —
|
||||||
|
exactly the scope creep a floor round forbids, and it would muddy the "did the kerb ruling move a golden?"
|
||||||
|
signal, which must stay a clean **no**. **Owner: A. Recommend R38, one small item, self-contained.**
|
||||||
|
|
||||||
## Round 30 (2026-07-18) — THE ROTATION BOUNDARY VERIFY (ledger #6): **HOLDS**
|
## Round 30 (2026-07-18) — THE ROTATION BOUNDARY VERIFY (ledger #6): **HOLDS**
|
||||||
|
|
||||||
### → Fable / F: `day` rides RUNTIME streams only — plan generation cannot see it. Measured, not read.
|
### → Fable / F: `day` rides RUNTIME streams only — plan generation cannot see it. Measured, not read.
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { generatePlan, chunkIndex, lotCorners, obbOverlap, CHUNK } from './plan.
|
|||||||
import { generatePlanOSM, osmTownKeys, validateTownCache, registerTownCache, MIN_TOWN_SHOPS,
|
import { generatePlanOSM, osmTownKeys, validateTownCache, registerTownCache, MIN_TOWN_SHOPS,
|
||||||
medianShopSpacing, MAX_MEDIAN_SPACING_M } from './plan_osm.js';
|
medianShopSpacing, MAX_MEDIAN_SPACING_M } from './plan_osm.js';
|
||||||
import { generatePlanFor, gigKeyFor, POSTER_CLEAR } from './index.js';
|
import { generatePlanFor, gigKeyFor, POSTER_CLEAR } from './index.js';
|
||||||
import { allFacadeSkins, SHOP_TYPES, VENUE_KINDS, genreForVenueKind, roadWidth } from '../core/registry.js';
|
import { allFacadeSkins, SHOP_TYPES, VENUE_KINDS, genreForVenueKind, vergeBand } from '../core/registry.js';
|
||||||
import { xmur3 } from '../core/prng.js';
|
import { xmur3 } from '../core/prng.js';
|
||||||
|
|
||||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||||
@ -218,41 +218,104 @@ function districtInvariants(plan, label) {
|
|||||||
}
|
}
|
||||||
ok(clash === null, `${label}: no band plays two venues on one night` + (clash !== null ? ` (night ${clash})` : ''));
|
ok(clash === null, `${label}: no band plays two venues on one night` + (clash !== null ? ` (night ${clash})` : ''));
|
||||||
|
|
||||||
// ── posters: town-wide, never on the bitumen — with a real FRONTAGE floor (ROUND16 ledger #6) ──
|
// ── posters vs THE CORRIDOR LAW — three arms, the third of which is the control (ROUND37 §0.1) ──
|
||||||
const gigIds = new Set(plan.gigs.map(g => g.gigId));
|
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(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`);
|
ok(plan.posters.every(p => plan.gigs.find(g => g.gigId === p.gigId).night === 0), `${label}: posters advertise tonight's gigs`);
|
||||||
// Two poster classes, two floors. A FRONTAGE poster sits on its venue's +Z street facade (B's canon:
|
//
|
||||||
// buildings.js facade + venue.js door/queue/camera are +Z); ROUND16 pickVenues now PREFERS a band_room/
|
// ROUND37 CORRECTION — THE VACUOUS GATE, NAMED. Until this round this block asked exactly one
|
||||||
// rsl lot whose facade clears every carriageway, so — no more R15 blanket exemption — a frontage poster
|
// question: "is the poster outside `roadWidth/2`?". But A's own placer seats spine posters at
|
||||||
// must clear its nearest kerb by ≥ POSTER_CLEAR. A SPINE poster is free-standing on the verge and keeps
|
// `poleOffset(e)`, which is DERIVED FROM `roadWidth` — so the gate and its subject were the same
|
||||||
// the plain no-bitumen floor (≥ 0, the R12 regression guard). −0.02 absorbs r2 poster-coord rounding vs
|
// function agreeing with itself. It was green for 24 rounds while all 14 gig posters on the default
|
||||||
// pickVenues' un-rounded clearance test (worst observed frontage clearance is ~0.51 m).
|
// boot stood on painted bitumen, because Lane B's ground painted its road quad the full `e.width`
|
||||||
|
// (28 m on a main, kerb nine metres inside it) and nothing in this suite could see that number.
|
||||||
|
// That is precisely the R27 cross-convention lesson recurring (see facadeQuadWorld above): a
|
||||||
|
// self-consistent check over a contested geometry passes under EITHER reading. So this now does what
|
||||||
|
// the R27 gate does — replicate the OTHER lane's maths and compare the two against each other.
|
||||||
|
//
|
||||||
|
// ARM 1 no poster stands on a CARRIAGEWAY — measured through `vergeBand(e)[0]`, the published law
|
||||||
|
// itself, i.e. the same call Lane B's ground now consumes. Gate and renderer cannot drift
|
||||||
|
// apart silently: change the law and both move together.
|
||||||
|
// ARM 2 every SPINE poster stands ON A FOOTPATH — inside `vergeBand(e)` of SOME edge that has one
|
||||||
|
// (`outer > inner`; a `lane` is all carriageway, so its band is degenerate and hosts no pole).
|
||||||
|
// This is the bound the old check never had: "not on the road" also passed for a poster
|
||||||
|
// standing in a paddock. After the kerb ruling it asserts the poster stands on paint B lays.
|
||||||
|
// ARM 3 THE CONTROL. If arms 1–2 pass under BOTH geometries they prove nothing, so count the
|
||||||
|
// posters that WOULD stand on bitumen under the PRE-RULING ground and assert that count is
|
||||||
|
// NOT ZERO. That is the falsifiability control living plan-side, permanently.
|
||||||
|
//
|
||||||
|
// Two poster classes, two floors (unchanged). A FRONTAGE poster sits on its venue's +Z street facade
|
||||||
|
// (B's canon: buildings.js facade + venue.js door/queue/camera are +Z); ROUND16 pickVenues PREFERS a
|
||||||
|
// band_room/rsl lot whose facade clears every carriageway, so a frontage poster must clear its nearest
|
||||||
|
// kerb by ≥ POSTER_CLEAR. A SPINE poster is free-standing on the verge and keeps the plain no-bitumen
|
||||||
|
// floor (≥ 0 — a `lane` has vergeBand [w/2,w/2], so its pole seats exactly ON the kerb and 0 is legal).
|
||||||
|
// −0.02 absorbs r2 poster-coord rounding vs pickVenues' un-rounded clearance test.
|
||||||
|
// Frontage posters are EXEMPT FROM ARM 2 by measurement, not convenience: a frontage poster rides its
|
||||||
|
// venue's facade plane, and `plan_osm.js` sets a real-town lot back at `max(KERB, roadWidth/2+FOOTPATH)`,
|
||||||
|
// so on 18 of 108 gig plans it legitimately stands past every corridor edge — worst 3.98 m
|
||||||
|
// (launceston_real, R37 measurement). SPINE violations over the same corpus: 0/108.
|
||||||
const lotByIdD = new Map(plan.lots.map(l => [l.id, l]));
|
const lotByIdD = new Map(plan.lots.map(l => [l.id, l]));
|
||||||
const onFacade = p => venues.some(v => {
|
const onFacade = p => venues.some(v => {
|
||||||
const lot = lotByIdD.get(v.lot); if (!lot) return false;
|
const lot = lotByIdD.get(v.lot); if (!lot) return false;
|
||||||
const off = lot.d / 2 + 0.06; // gigs.js buildPosters item 1 (FACADE_PROUD)
|
const off = lot.d / 2 + 0.06; // gigs.js buildPosters item 1 (FACADE_PROUD)
|
||||||
return Math.hypot(p.x - (lot.x + Math.sin(lot.ry) * off), p.z - (lot.z + Math.cos(lot.ry) * off)) < 0.5;
|
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;
|
const segs = edgeSegments(plan);
|
||||||
|
let onRoad = null, offFootpath = null;
|
||||||
for (const p of plan.posters) {
|
for (const p of plan.posters) {
|
||||||
let best = Infinity, bestEdge = null;
|
const frontage = onFacade(p);
|
||||||
for (const e of plan.streets.edges) {
|
let best = Infinity, bestEdge = null, onSomeFootpath = false;
|
||||||
const a = nodeById2(plan, e.a), b = nodeById2(plan, e.b);
|
for (const [e, ax, az, bx, bz] of segs) {
|
||||||
if (!a || !b) continue;
|
const [nx, nz] = nearestOnSeg(p.x, p.z, ax, az, bx, bz);
|
||||||
const [nx, nz] = nearestOnSeg(p.x, p.z, a.x, a.z, b.x, b.z);
|
|
||||||
const d = Math.hypot(p.x - nx, p.z - nz);
|
const d = Math.hypot(p.x - nx, p.z - nz);
|
||||||
if (d < best) { best = d; bestEdge = e; }
|
if (d < best) { best = d; bestEdge = e; }
|
||||||
|
const [inner, outer] = vergeBand(e);
|
||||||
|
if (outer > inner && d >= inner - 1e-6 && d <= outer + 1e-6) onSomeFootpath = true;
|
||||||
}
|
}
|
||||||
if (!bestEdge) continue;
|
if (!bestEdge) continue;
|
||||||
const frontage = onFacade(p);
|
const clearance = best - vergeBand(bestEdge)[0]; // ARM 1 — the kerb IS vergeBand's inner edge
|
||||||
const clearance = best - roadWidth(bestEdge) / 2;
|
|
||||||
const floor = frontage ? POSTER_CLEAR - 0.02 : -1e-6;
|
const floor = frontage ? POSTER_CLEAR - 0.02 : -1e-6;
|
||||||
if (clearance < floor) { onRoad = [p.id, bestEdge.id, +clearance.toFixed(2), frontage ? 'frontage' : 'spine']; break; }
|
if (clearance < floor && onRoad === null) onRoad = [p.id, bestEdge.id, +clearance.toFixed(2), frontage ? 'frontage' : 'spine'];
|
||||||
|
if (!frontage && !onSomeFootpath && offFootpath === null) offFootpath = [p.id, bestEdge.id, +best.toFixed(2)];
|
||||||
}
|
}
|
||||||
ok(onRoad === null, `${label}: every poster clears its kerb (frontage ≥ ${POSTER_CLEAR} m, spine ≥ 0)` + (onRoad ? ` (${onRoad[3]} poster ${onRoad[0]} clears edge ${onRoad[1]} by only ${onRoad[2]} m)` : ''));
|
ok(onRoad === null, `${label}: no poster stands on a carriageway — vergeBand inner edge (frontage ≥ ${POSTER_CLEAR} m, spine ≥ 0)` +
|
||||||
|
(onRoad ? ` (${onRoad[3]} poster ${onRoad[0]} clears edge ${onRoad[1]}'s kerb by only ${onRoad[2]} m)` : ''));
|
||||||
|
ok(offFootpath === null, `${label}: every spine poster stands INSIDE some edge's vergeBand (the footpath B paints in to roadWidth/2)` +
|
||||||
|
(offFootpath ? ` (poster ${offFootpath[0]} is ${offFootpath[2]} m from nearest edge ${offFootpath[1]} and inside no verge band)` : ''));
|
||||||
|
const preRuling = preRulingRoadPosters(plan);
|
||||||
|
ok(!plan.posters.length || preRuling > 0,
|
||||||
|
`${label}: CONTROL — the kerb arms DISCRIMINATE: ${preRuling}/${plan.posters.length} poster(s) stand on bitumen under the PRE-RULING ground (?verge=0)`);
|
||||||
}
|
}
|
||||||
const nodeById2 = (plan, id) => plan.streets.nodes.find(n => n.id === id);
|
const nodeById2 = (plan, id) => plan.streets.nodes.find(n => n.id === id);
|
||||||
|
// Every edge resolved once to [edge, ax, az, bx, bz] — the poster arms are O(posters × edges).
|
||||||
|
function edgeSegments(plan) {
|
||||||
|
const nodeById = new Map(plan.streets.nodes.map(n => [n.id, n]));
|
||||||
|
const out = [];
|
||||||
|
for (const e of plan.streets.edges) {
|
||||||
|
const a = nodeById.get(e.a), b = nodeById.get(e.b);
|
||||||
|
if (a && b) out.push([e, a.x, a.z, b.x, b.z]);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
// ROUND37 §0.1 — LANE B'S PRE-RULING GROUND, REPLICATED HERE ON PURPOSE (the R27 cross-lane pattern).
|
||||||
|
// `ground.js` painted its road quad the FULL corridor — `hQuad(cx, cz, dir, perp, roadLen, e.width, 0)`
|
||||||
|
// — i.e. bitumen out to `e.width/2`, with A's kerb at `roadWidth(e)/2` nine metres inside it on a main.
|
||||||
|
// John's R37 ruling moves the paint in to the kerb; Lane B's permanent `?verge=0` flag keeps THIS
|
||||||
|
// geometry in the codebase forever, so the replica is pinned to the FLAG, not to a line number that
|
||||||
|
// will drift. It counts a floor, never an over-count: ground.js overruns each segment by OVERLAP=1.5 m
|
||||||
|
// at both ends and this clamps to the segment. Used as the control arm above and pinned at the default
|
||||||
|
// boot's exactly-14 in §3c.
|
||||||
|
function preRulingRoadPosters(plan) {
|
||||||
|
let n = 0;
|
||||||
|
const segs = edgeSegments(plan);
|
||||||
|
for (const p of plan.posters || []) {
|
||||||
|
for (const [e, ax, az, bx, bz] of segs) {
|
||||||
|
const [nx, nz] = nearestOnSeg(p.x, p.z, ax, az, bx, bz);
|
||||||
|
if (Math.hypot(p.x - nx, p.z - nz) < ((e.width || 0) / 2) - 1e-9) { n++; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
// ── 1. determinism: two runs byte-identical ─────────────────────────────────────────
|
// ── 1. determinism: two runs byte-identical ─────────────────────────────────────────
|
||||||
section('determinism (deep-equal across two runs)');
|
section('determinism (deep-equal across two runs)');
|
||||||
@ -342,6 +405,19 @@ const GIG_GOLDEN = 0xec7a2d39; // ROUND16 re-pin: pickVenues prefers band_room/r
|
|||||||
if (GIG_GOLDEN === 0) console.log(` ⚠ gig golden UNPINNED → set GIG_GOLDEN = 0x${hash.toString(16).padStart(8, '0')}`);
|
if (GIG_GOLDEN === 0) console.log(` ⚠ gig golden UNPINNED → set GIG_GOLDEN = 0x${hash.toString(16).padStart(8, '0')}`);
|
||||||
ok(GIG_GOLDEN !== 0 && hash === (GIG_GOLDEN >>> 0), `gig layer golden 0x${hash.toString(16)} matches pinned 0x${(GIG_GOLDEN >>> 0).toString(16)}`);
|
ok(GIG_GOLDEN !== 0 && hash === (GIG_GOLDEN >>> 0), `gig layer golden 0x${hash.toString(16)} matches pinned 0x${(GIG_GOLDEN >>> 0).toString(16)}`);
|
||||||
}
|
}
|
||||||
|
// ROUND37 §0.1 — THE PRE-RULING COUNT, PINNED ON THE DEFAULT BOOT. The city-patterns audit reported
|
||||||
|
// "all 14 gig posters are standing in the road"; Lane A re-measured it and it is exact — 14 posters on
|
||||||
|
// the default boot (synthetic, golden seed, gigs default-ON since R16), all 14 inside `e.width/2`, and
|
||||||
|
// ZERO inside the ruled kerb `roadWidth/2`. Pinned here, not just asserted `> 0`, because a control that
|
||||||
|
// is allowed to drift toward zero is how a gate goes vacuous in the first place — the thing this round
|
||||||
|
// exists to stop. If a future change moves posters out past `e.width/2`, this fires and the ?verge=0
|
||||||
|
// falsifiability control (Lane B's flag, Lane F's gate leg) has to be re-argued rather than quietly lost.
|
||||||
|
const PRE_RULING_ROAD_POSTERS = 14;
|
||||||
|
{
|
||||||
|
const n = preRulingRoadPosters(generatePlanFor(GOLDEN.seed, 'synthetic', { gigs: true }));
|
||||||
|
ok(n === PRE_RULING_ROAD_POSTERS,
|
||||||
|
`default boot: exactly ${PRE_RULING_ROAD_POSTERS} posters stood on bitumen under the PRE-RULING ground (?verge=0) — measured ${n}`);
|
||||||
|
}
|
||||||
|
|
||||||
// ── 3d. district invariant sweep (ROUND14): 400 synthetic seeds + osm graceful placement ───────────
|
// ── 3d. district invariant sweep (ROUND14): 400 synthetic seeds + osm graceful placement ───────────
|
||||||
// Release-round Lane A gate: the district contract must hold at SCALE, not just the 4 hero seeds. Runs
|
// Release-round Lane A gate: the district contract must hold at SCALE, not just the 4 hero seeds. Runs
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user