Lane B R39 (Fable's ruling): THE SIGN — +sin lands; the fourth instance of the -Z/+Z confusion

index.html:428 (Lane D's patronage door points, since R8) and :500 (doorOf, the R32 cluster-pose
spawn) computed the shop front as (-sin ry, -cos ry) — the BACK of the building. buildings.js:410,
:583-597 put the facade, the door and the doorRect at local +Z; dbg.js:53 says so in words;
minimap.js has always drawn its front tick there. Two characters, both sites.

THE PATRONAGE DOOR POINT, on the footpath (registry.js's own roadWidth/vergeBand split, outside the
carriageway, outside every lot):
  synthetic     0/493 -> 427/493     median 26.22 m -> 9.40 m from the centreline
  katoomba_real  0/72  ->  67/72     19.10 -> 3.90
  fitzroy_real  0/139 -> 139/139     19.10 -> 3.90
  bowral_real    0/30  ->  28/30     21.10 -> 5.90
Not one door point in the corpus was on a footpath. Lane D's peds ducked into the back fence.

THE SPAWN, booted code both sides (:8702 the fog commit, :8701 the fix, nothing monkey-patched):
  synthetic  (25.5,-17.9) 3 shops within 25 m, 0 in front, 0 discovered
          -> (6.1,-19.8)  4 within 25 m, 4 in front, 4 discovered
  katoomba   (-219.0,-471.3) 3/0/0  ->  (-200.0,-474.4) 4/4/4
And in the picture (docs/shots/laneB_r39/sign-*): katoomba's shipped boot opens STANDING IN A
PADDOCK FACING THE BLANK BACK WALL OF A BUILDING — the R31 playtest's own complaint, the one R32 was
written to fix and, because of the sign, never did.

NO GOLDEN MOVES: SPAWN and the patronage points are runtime pose, computed in the shell from a plan
it never writes. Lane A selfcheck either side: fingerprint 0x5f76e76 -> 0x5f76e76, 157,647/157,647.
?classic=1 never enters the branch and keeps the frozen (-96, 9) pose.

-> LANE F: the R32 cluster-pose spawn gate and the R35 first-five-minutes smoke both photograph this
pose and need re-baselining. The falsifiable arm that needs no picture: at spawn, the count of shops
within 25 m that are IN FRONT of the player must be > 0 (0 on 4/4 towns before, 4 on 4/4 after).

THE LINEAGE, written down as Fable asked — this is the FOURTH instance of the same confusion:
R13 RY_FLIP (the band 180 deg off) · R15 the venue poster on the back wall (15.9 m from the facade,
0.07 m from the back) · R27 every real-town shopfront facing the paddock (dot = -1.000 on 35/35 and
72/72 lots; CITY_SPEC:71 says -Z, :335 says +Z) · R39 these two. Every time the rig/pose convention
is local -Z and the visible front is local +Z, and every time it was caught by a PICTURE or by a
consumer with a different convention — never by a metric. A heading has no falsifiable arm inside
the file that computes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-08-03 21:17:48 +10:00
parent 12eb571357
commit a982f3ce67
11 changed files with 92 additions and 21 deletions

View File

@ -77,10 +77,20 @@ Measured live, both towns, fresh boot then a 900 m walk through the real rAF loo
| | synthetic | katoomba_real | | | synthetic | katoomba_real |
|---|---|---| |---|---|---|
| fresh boot | 0/493 shops · 1/22 segs · frame **240 m** · lot **20.97×41.16 px** | 0/72 shops · 0/993 segs · frame **240 m** · lot **29.4×39.2 px** | | fresh boot | 4/493 shops · 1/22 segs · frame **240 m** · lot **20.97×41.16 px** | 4/72 shops · 1/993 segs · frame **240 m** · lot **29.4×39.2 px** |
| after 900 m | 113/493 shops · 7 segs · frame 515 m · **9.77×19.18 px** | 34/72 shops · 18 segs · frame 965 m · **7.31×9.75 px** | | after 900 m | 113/493 shops · 7 segs · frame 515 m · **9.77×19.18 px** | 34/72 shops · 18 segs · frame 965 m · **7.31×9.75 px** |
| the shipped map | — · frame 965 m · 5.22×10.24 px | — · frame **4,984 m** · **1.42×1.89 px** | | the shipped map | — · frame 965 m · 5.22×10.24 px | — · frame **4,984 m** · **1.42×1.89 px** |
*(Fresh boot reads 4 shops rather than 0 because the `+sin` fix below landed: you now start standing in
front of four shopfronts instead of behind them. **On katoomba that fresh-boot map draws 3,478 pixels
of shop colour — against HEAD's ZERO for the entire town.** Four shops you can read beat seventy-two
you cannot see.)*
**One harness assertion of mine is wrong and F should not inherit it:** `r39_verify.py`'s fog arm
asserts *more shop-colour pixels after the walk*, which only holds at a fixed zoom — after 900 m on
katoomba the frame has grown to 965 m, so 34 shops draw 1,902 px where 4 drew 3,478. The honest
assertion is the **shop count** (4 → 34, already checked separately), or px-per-known-shop.
**The frame is the shops you have stood in front of, plus where you are standing — NOT the streets you **The frame is the shops you have stood in front of, plus where you are standing — NOT the streets you
have walked**, and that was a real correction to my own first cut. An edge is drawn as the whole have walked**, and that was a real correction to my own first cut. An edge is drawn as the whole
node-to-node line, and the synthetic's main street is one ~400 m edge, so stepping onto it at spawn node-to-node line, and the synthetic's main street is one ~400 m edge, so stepping onto it at spawn
@ -115,7 +125,25 @@ synthetic, 40.3% katoomba, 43.4% bowral, 43.5% fitzroy** — and on a shopper's
refuses **02**, which is exactly the shape you want: free where a shopper stands, decisive behind the refuses **02**, which is exactly the shape you want: free where a shopper stands, decisive behind the
buildings. buildings.
### THE SIGN WAS WRONG AND IT IS THE SHELL'S, NOT MINE — a finding, held, not fixed ### THE SIGN WAS WRONG — the FOURTH instance of the Z/+Z confusion *(Fable ruled: landed, `1b7fa5f`)*
**The lineage, because the next lane to touch a heading should find it.** Every time, the rule is the
same: **the rig/pose convention is local Z, the visible front is local +Z**, and every time it
survived because *the thing checking it shared a convention with the thing that was wrong.*
| round | where | what it did | how it was caught |
|---|---|---|---|
| **R13** | Lane C's pose `ry` vs Lane D's rig | the band played 180° off; settled with `RY_FLIP = π` (`ROUND13_INSTRUCTIONS:26-28`) | another lane's mesh looked wrong |
| **R15** | `buildPosters` item 1, `lot + (sin, cos)·d/2` | the venue's own frontage poster on the **back wall** — measured **15.9 m from the street facade, 0.07 m from the back** | a screenshot of the pub |
| **R27** | real-town shopfronts | **dot = 1.000 exactly** on 35/35 redhill and 72/72 katoomba lots — every real shop had faced the paddock since v1. `CITY_SPEC:71` says the facade is Z, `CITY_SPEC:335` says +Z; the two generators each implemented one half (`ROUND27_INSTRUCTIONS:169` already named it *"the same Z/+Z species as R13's RY_FLIP and R15's posters"*) | standing on Musgrave Road and looking |
| **R39** | `index.html:428` patronage door points · `:500` the R32 spawn | Lane D's peds ducked into the back fence and **every non-classic boot since R32 opened behind the shop row** | the fog: my probe copied the shell's sign and read 4 shops known / 1,231 in-radius rejections |
Four instances, four rounds apart, and each one was found by a *picture* or by a consumer with a
different convention — never by a metric. That is the entry worth keeping: **a heading has no
falsifiable arm inside the file that computes it.** If you write one, check it against
`buildings.js`'s `toWorld` and take the screenshot.
### The R39 instance, measured
My first cut copied `index.html`'s own front-normal and the walk read **4 shops known and 1,231 My first cut copied `index.html`'s own front-normal and the walk read **4 shops known and 1,231
in-radius rejections** on the synthetic — the fog hiding the town from a player standing in front of it. in-radius rejections** on the synthetic — the fog hiding the town from a player standing in front of it.
The geometry says the shell is wrong: The geometry says the shell is wrong:
@ -123,25 +151,50 @@ The geometry says the shell is wrong:
- `buildings.js:410-416, :583-597` build the facade, the door and the `doorRect` at local **+Z** — - `buildings.js:410-416, :583-597` build the facade, the door and the `doorRect` at local **+Z** —
`lot + (sin ry, cos ry)·d/2`. `minimap.js`'s front-edge tick has always been drawn at local +Z. `lot + (sin ry, cos ry)·d/2`. `minimap.js`'s front-edge tick has always been drawn at local +Z.
`dbg.js:53` says it in words: *"Front normal = local +Z rotated by lot.ry"*, `fx = Math.sin(ry)`. `dbg.js:53` says it in words: *"Front normal = local +Z rotated by lot.ry"*, `fx = Math.sin(ry)`.
- `index.html:384` (Lane D's patronage door points) and `index.html:450` (`doorOf`, the R32 cluster-pose - `index.html:428` (Lane D's patronage door points, since R8) and `index.html:500` (`doorOf`, the R32
spawn) use **`(sin ry, cos ry)`** — the back of the building. cluster-pose spawn) used **`(sin ry, cos ry)`** — the back of the building. **Both now `+sin/+cos`.**
- Measured against each lot's **own `frontEdge`**: the +sin point is **0.00 m** from the kerb on the - Measured against each lot's **own `frontEdge`**: the +sin point is **0.00 m** from the kerb on the
synthetic and 1.50 m on katoomba (i.e. on the kerb line, where a facade belongs); the sin point is synthetic and 1.50 m on katoomba (i.e. on the kerb line, where a facade belongs); the sin point is
**15.25 m / 12.50 m** the wrong side of it. **493 of 493 and 72 of 72 shops agree.** **15.25 m / 12.50 m** the wrong side of it. **493 of 493 and 72 of 72 shops agree.**
- The consequence, measured at the shipped spawn on four towns: **0 of the 13 shops within 25 m are in
front of you.** At the corrected spawn: **all of them are** (synthetic 4/4, katoomba 4/4, bowral 4/4,
fitzroy 1/1). R32's own comment says the spawn stands *"ON the footpath door-line"*; the code stands
in the back lane, and the fresh-boot fog map is the picture of it — one street, its yards, no shops.
- **And in a picture, live, both towns** (`spawn-*-SHIPPED.png` vs `spawn-*-FRONT-NORMAL.png`): the
shipped spawn stands on a footpath facing an empty plaza and a retaining wall with **not one shopfront
in frame**, and the fog reports **0 shops known after 2.5 s of standing there**; recompute the same
pose with `+sin` and the player is **under a shop awning with the sign at their shoulder**, **4 shops
known**. Same on katoomba_real: 0 → 4.
**I did not fix it.** It is a two-character change in my own file, but it moves the default boot's **THE PATRONAGE DOOR POINT — is it on the footpath?** (in the verge band per `registry.js`'s own
opening pose for every gate and screenshot in the project, mid-round, with three lanes in the tree and `roadWidth`/`vergeBand` split, outside the carriageway, outside every lot):
Lane F gating at the close. The patch is `+Math.sin` / `+Math.cos` at `index.html:384-385` and `:450`.
**Fable's call.** | town | shipped | **fixed** | median distance from the street centreline |
|---|---|---|---|
| synthetic | **0 / 493** | **427 / 493** | 26.22 m → **9.40 m** (carriageway edge 5 m, facade 14 m) |
| katoomba_real | **0 / 72** | **67 / 72** | 19.10 m → **3.90 m** |
| fitzroy_real | **0 / 139** | **139 / 139** | 19.10 m → **3.90 m** |
| bowral_real | **0 / 30** | **28 / 30** | 21.10 m → **5.90 m** |
Not one door point in the corpus was on a footpath. Lane D's peds have been ducking into the back
fence since R8. (The residue — 31 synthetic / 5 katoomba / 2 bowral — are corner lots whose front
point lands inside a *neighbouring* lot; that class is pre-existing and **14 fewer** than before.)
**THE SPAWN — booted code on both sides**, `:8702` serving the fog commit, `:8701` the fix, nothing
monkey-patched:
| | shipped | fixed |
|---|---|---|
| synthetic | (25.5, 17.9) · 3 shops within 25 m, **0 in front**, **0 discovered** | (6.1, 19.8) · 4 within 25 m, **4 in front**, **4 discovered** |
| katoomba_real | (219.0, 471.3) · 3 within 25 m, **0 in front**, **0 discovered** | (200.0, 474.4) · 4 within 25 m, **4 in front**, **4 discovered** |
**And the picture, which is the whole argument** (`docs/shots/laneB_r39/sign-*`): the shipped katoomba
boot opens **standing in a paddock facing the blank back wall of a building** — which is the R31
playtest's own complaint, *"faced dirt and building-backs"*, the complaint R32 was written to fix and,
because of the sign, never did. The fixed boot opens on the footpath under the awnings with the
shopfronts and their signage running away down Katoomba Street.
**NO GOLDEN MOVES, plainly: `SPAWN` and the patronage points are RUNTIME POSE, computed in the shell
from a plan it never writes to.** Lane A's selfcheck run either side of the change:
**fingerprint `0x5f76e76``0x5f76e76`**, 157,647/157,647 checks. `?classic=1` is untouched by
construction — it never enters the branch and keeps the frozen (96, 9, looking east) pose forever.
**→ LANE F, two gates photograph this pose and need re-baselining:** the **R32 cluster-pose spawn**
gate and the **R35 first-five-minutes** smoke. Both are correct to move — the pose they baselined is
the defect. The falsifiable arm to gate on instead, which needs no picture: at the spawn, **the count
of shops within 25 m that are in front of the player must be > 0** (it was 0 on 4 of 4 towns before,
4 of 4 after), and it goes red the moment the sign flips back.
### The save shape, and its bound ### The save shape, and its bound
`known` — OPTIONAL, absent until something is learned, so a save that predates R39 stays valid forever `known` — OPTIONAL, absent until something is learned, so a save that predates R39 stays valid forever

View File

@ -13,5 +13,11 @@ both sides. Every number behind these pictures is in `docs/LANES/LANE_B_NOTES.md
| `fog-01-before-katoomba_real.png` | **R39, fresh boot** — the 240 m frame, a shop lot at 29.4×39.2 px | | `fog-01-before-katoomba_real.png` | **R39, fresh boot** — the 240 m frame, a shop lot at 29.4×39.2 px |
| `fog-02-after-katoomba_real.png` | **R39, after 900 m** — 34 shops on **Katoomba Street**, with **Edwards Street** running off it (Lane A's address layer) | | `fog-02-after-katoomba_real.png` | **R39, after 900 m** — 34 shops on **Katoomba Street**, with **Edwards Street** running off it (Lane A's address layer) |
| `map-classic.png` | `?classic=1` — the pre-R39 map, hash-identical to HEAD's | | `map-classic.png` | `?classic=1` — the pre-R39 map, hash-identical to HEAD's |
| `spawn-*-SHIPPED.png` | the default boot's spawn pose today: a footpath facing a plaza, **not one shopfront in frame**, 0 shops discovered | | `sign-*-BEFORE.png` | the default boot's spawn **as shipped since R32**: synthetic — a footpath facing a plaza with not one shopfront in frame; katoomba — **standing in a paddock facing the blank back wall of a building**. 3 shops within 25 m, **0 of them in front of you**, 0 discovered |
| `spawn-*-FRONT-NORMAL.png` | the same pose recomputed with the front normal `buildings.js`/`dbg.js`/`minimap.js` all use: **under the awning, sign at your shoulder**, 4 shops discovered | | `sign-*-AFTER.png` | the same code with the front normal corrected (`+sin`): **on the footpath under the awnings, signage down the strip**, 4 shops within 25 m, **4 in front**, 4 discovered |
The `sign-*` pair is **booted code on both sides** — two port-isolated no-store servers, `:8702`
serving the fog commit (old sign) and `:8701` the fix. Nothing is monkey-patched.
Katoomba's BEFORE is the R31 playtest's own complaint, verbatim — *"faced dirt and building-backs"*
which R32 was written to fix and, because of the sign, never did.

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 691 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 KiB

View File

@ -422,10 +422,16 @@ if (!rosterV1) {
} }
// [Lane F R8 — Lane D patronage] shop door points per chunk (facade normal → the street), fed once to the // [Lane F R8 — Lane D patronage] shop door points per chunk (facade normal → the street), fed once to the
// sim so streamed peds can duck into open shops they pass. Computed from the plan (sim stays graph-only). // sim so streamed peds can duck into open shops they pass. Computed from the plan (sim stays graph-only).
// [Lane B R39 — THE SIGN, fixed] This read `(-sin ry, -cos ry)` since R8 and that is the BACK of the
// building. `buildShopfront` puts the facade, the door and the doorRect at local +Z (buildings.js:410-416,
// :583-597 — `toWorld(lot,0,0,d/2)` = `lot + (sin ry, cos ry)·d/2`); dbg.js:53 says it in words; minimap.js
// has always drawn its front-edge tick there. Measured against each lot's OWN frontEdge: the +sin point is
// 0.00 m from the kerb on the synthetic and 1.50 m on katoomba_real, the sin point is 15.25 m / 12.50 m
// the wrong side, and the front wins on 493/493 and 72/72 shops. Peds were ducking into the back fence.
const shopsByChunk = new Map(); const shopsByChunk = new Map();
for (const s of plan.shops) { for (const s of plan.shops) {
const l = plan.lots.find((x) => x.id === s.lot); if (!l) continue; const l = plan.lots.find((x) => x.id === s.lot); if (!l) continue;
const ry = l.ry || 0, fx = -Math.sin(ry), fz = -Math.cos(ry); const ry = l.ry || 0, fx = Math.sin(ry), fz = Math.cos(ry);
const x = l.x + fx * (l.d / 2 + 0.6), z = l.z + fz * (l.d / 2 + 0.6); const x = l.x + fx * (l.d / 2 + 0.6), z = l.z + fz * (l.d / 2 + 0.6);
const k = citizens.chunkKeyAt(x, z); const k = citizens.chunkKeyAt(x, z);
if (!shopsByChunk.has(k)) shopsByChunk.set(k, []); if (!shopsByChunk.has(k)) shopsByChunk.set(k, []);
@ -484,6 +490,12 @@ const queueCountOf = (id) => { const q = venueQueues && venueQueues.get(id); ret
// (a point every shop already computes for patronage — known walkable), looking down the strip toward // (a point every shop already computes for patronage — known walkable), looking down the strip toward
// the cluster's heart. Deterministic (pure plan math, no draws — no stream moves), and ?classic=1 // the cluster's heart. Deterministic (pure plan math, no draws — no stream moves), and ?classic=1
// keeps the frozen pose forever (the covenant is a POSE here, not just a plan). // keeps the frozen pose forever (the covenant is a POSE here, not just a plan).
// [Lane B R39 — THE SIGN, fixed] R32's comment above is exactly right and the code below contradicted
// it: `-Math.sin(ry)` put the "footpath door-line" 15 m THROUGH the building, so every non-classic boot
// since R32 has opened standing behind the shop row. Measured at the shipped pose on four towns, **0 of
// the 13 shops within 25 m were in front of the player**; with the sign the geometry actually uses, all
// of them are (synthetic 4/4, katoomba 4/4, bowral 4/4, fitzroy 1/1). Runtime pose only — SPAWN never
// touches the plan, so no golden moves and `?classic=1` keeps the frozen (-96, 9) pose regardless.
let SPAWN = { x: -96, z: 9, yaw: -Math.PI / 2 }; let SPAWN = { x: -96, z: 9, yaw: -Math.PI / 2 };
if (!CLASSIC && plan.shops && plan.shops.length >= 2) { if (!CLASSIC && plan.shops && plan.shops.length >= 2) {
// main-street shop doors only (block kind — both generators stamp it); every-door fallback // main-street shop doors only (block kind — both generators stamp it); every-door fallback
@ -491,7 +503,7 @@ if (!CLASSIC && plan.shops && plan.shops.length >= 2) {
const doorOf = (s) => { const doorOf = (s) => {
const l = plan.lots.find((x) => x.id === s.lot); if (!l) return null; const l = plan.lots.find((x) => x.id === s.lot); if (!l) return null;
const ry = l.ry || 0; const ry = l.ry || 0;
return { x: l.x - Math.sin(ry) * (l.d / 2 + 2.6), z: l.z - Math.cos(ry) * (l.d / 2 + 2.6), block: l.block }; return { x: l.x + Math.sin(ry) * (l.d / 2 + 2.6), z: l.z + Math.cos(ry) * (l.d / 2 + 2.6), block: l.block };
}; };
let doors = plan.shops.map(doorOf).filter(Boolean); let doors = plan.shops.map(doorOf).filter(Boolean);
const ms = doors.filter((d) => msBlocks.has(d.block)); const ms = doors.filter((d) => msBlocks.has(d.block));