PROCITY/web/js/world
m3ultra 4c2702fc58 Lane B R27 w4: poseForShopFront — and the real towns face the wrong way
The micro-task, done and verified. In doing it I found why F photographed
empty road: it is not the pose.

1. THE DELIVERABLE — DBG.poseForShopFront(sel, dist = 8)
Poses at a NAMED shop's frontage: door centred, sign band + R26 crate mark in
shot, under the verandah. clusterPose() answers "where is the town's HEART",
which is the wrong question for a named shop — Red Hill's heart doesn't contain
Monster Robot, which is exactly how F got three frames of empty road.

Keyed through ONE shop selector: F's R22/R24 resolver lived inside enterShop(),
so I extracted it rather than grow a second key scheme beside it. A selector bug
resolves the wrong shop AND looks like it worked (F's own first cut proved it),
so the id-namespace law now has exactly one home.
  poseForShopFront(31)         → Wholefood Cafe (PLAN id) + ambiguous: "31 is
                                 also the godverseShopId of Silky Oak Furnature"
  poseForShopFront('g:31')     → Silky Oak Furnature (the prefix IS the fence)
  poseForShopFront('g:999999') → {error} — never throws, never guesses
Framing proven by projection, not by eye: doorCentreNdcX = 0.0000 exactly, door
+ sign + mark inside the frustum. Derived from buildings.js, not hardcoded: door
is centred on the lot front (off = 0, unlike poseForShop's off = 1.0); sign band
= min(h,FACADE_H)-0.35 ± 0.25 ⇒ y 2.40-2.90; mark = y 2.45-2.52; camY 2.0 sits
below AWNING_Y 2.95, so a ray rising to a target ≤2.9 can never cross it — the
sign is clear BY GEOMETRY at any distance.

2. CORRECTING MY OWN R27 INTEL — I gave F two wrong numbers. I said the mark
"rides high (y≈3.3)" and the vinyl blocks 4% of it. Both wrong: the mark is at
y 2.45-2.52, and I had scanned y 3.0-3.6 — empty awning air above the sign,
which is why it read ~0. Re-measured: the novelty_record disc (top y 2.50)
reaches INTO the mark band and clips ~15% of the strip from EVERY offset;
moving the camera only changes which 15%. "Shoot head-on" survives, but for the
opposite reason to the one I gave.

3. THE FINDING — every real town's shops face away from their street, since R18.
From Musgrave Road (Monster Robot's own frontEdge 1316) the shop is a blank grey
back wall: no sign, no door, no mark. Measured:
  redhill_godverse  35 shop lots: 0 facing, 35 backwards (dot = -1.000)
  katoomba_real     72 shop lots: 0 facing, 72 backwards (dot = -1.000)
  synthetic         correct — always has been
dot = -1.000 exactly on every lot in both towns: a convention, not a defect.
Katoomba's street_noon — the bookmark the tours have shot for nine rounds — is
46 draws / 19,680 tris of bare road.

Root cause: CITY_SPEC contradicts itself and each generator implements one half.
  CITY_SPEC:71  (lots contract) "World facing = (-sin ry, -cos ry)"  ⇒ -Z facade
  CITY_SPEC:335 (posters, R15)  "the +Z street facade (B's canon)"   ⇒ +Z facade
plan_osm.js:443 obeys the first (its comment: "facade (-Z) faces road").
plan.js, buildings.js, venue.js and the R15 posters obey the second. Synthetic —
the town every golden tests — follows B's canon and looks right, which is exactly
why nine rounds of real-town work never caught it. The epoch's own signature
species: a rule meeting a case written after it.

Proven, then REVERTED: one line in A's plan_osm.js (ry = atan2(-nx,-nz)) flips
katoomba 0/72 → 72/72 facing, and turns poseForShopFront's camera from 26m out in
a paddock into 4m from Musgrave Road — the money shot F specified. Not committed:
it is A's file, it moves every real-town plan (goldens re-pin under amendment
law), and a self-contradicting spec is Fable's to rule on, not mine to pick a
side of.

This also re-reads my R22 diagnosis: I recorded "chunk-buildings 348 tris (0.2%)"
in katoomba's busiest block and credited the instancing work. 348 tris is ~29
boxes — that was not efficiency, it was the buildings being ABSENT from frame. I
read the evidence as a win for five rounds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 15:42:50 +10:00
..
audio.js Lane B (Streetscape) round 14: v3.0 release — alpha-alias retirement + tour audit + queue_night hero (?gigs=1) 2026-07-16 08:43:22 +10:00
buildings.js Lane B R26 (v5.0-beta): the stocked shopfront reads from the footpath 2026-07-17 09:49:54 +10:00
chunks.js Lane B R26 (v5.0-beta): the stocked shopfront reads from the footpath 2026-07-17 09:49:54 +10:00
dbg.js Lane B R27 w4: poseForShopFront — and the real towns face the wrong way 2026-07-17 15:42:50 +10:00
fixture_plan.js Lane B (Streetscape): chunk-streamed walkable town shell 2026-07-14 14:28:47 +10:00
furniture.js Lane B round 17 (v3.2): wind sway SHIPS -- weather-driven gum-tree sway (ledger #5, parked since R7) 2026-07-16 14:30:09 +10:00
gig_state.js Lane F R15 (v3.0): retire the R12 single-venue alias (ledger #2) 2026-07-16 11:14:19 +10:00
ground.js Lane B (Streetscape): chunk-streamed walkable town shell 2026-07-14 14:28:47 +10:00
hud.js Lane B round 21 (v4.0-beta): town selector reads E's towns index (ledger #2, the missed R20 #5) 2026-07-16 20:35:47 +10:00
interior_mode.js Lane F R27 (v5.0): the tier-2 reader — pick-then-omit, and the server killed mid-session 2026-07-17 14:34:42 +10:00
lighting.js Lane B round-8: weather (?weather=1) — seeded rain/overcast/clear, exposes PROCITY.weather for D 2026-07-15 02:34:14 +10:00
minimap.js Lane B (Streetscape): chunk-streamed walkable town shell 2026-07-14 14:28:47 +10:00
planutil.js Lane B (Streetscape): chunk-streamed walkable town shell 2026-07-14 14:28:47 +10:00
player.js Lane B (Streetscape): chunk-streamed walkable town shell 2026-07-14 14:28:47 +10:00
skins.js Lane B (Streetscape): chunk-streamed walkable town shell 2026-07-14 14:28:47 +10:00
tram.js Lane B round 20 (v4.0-beta): the tram ruling — route by shop adjacency + per-town fence (ledger #3/#4) 2026-07-16 19:35:56 +10:00
venue.js Lane B round 16 (v3.1 THE FLIP): town-wide streetlamp pools + default-boot budget re-baseline 2026-07-16 12:21:19 +10:00
weather.js Lane B round 17 (v3.2): wind sway SHIPS -- weather-driven gum-tree sway (ledger #5, parked since R7) 2026-07-16 14:30:09 +10:00
wind.js Lane B round 17 (v3.2): wind sway SHIPS -- weather-driven gum-tree sway (ledger #5, parked since R7) 2026-07-16 14:30:09 +10:00