Lane D: play site_02 cold — night 3 soft-locks, carport trap is inert

Gate 1.3, four sprints owed. Played the real path (nights 1-2-3, mouse).
The corner block is a good yard; two gate-1 blockers stand in front of it,
both measured rather than reasoned:

- Night 3 is unplayable. rigging.setWorld is undefined, so main.js:450's
  optional call is a no-op and createRiggingUI's markers (rigging.js:254)
  stay bound to the boot-time backyard. On night 3 the world/session/rig
  re-point correctly but the only clickable markers are the backyard's, at
  backyard coordinates. Clicks are silent no-ops, commit() returns false,
  Enter refuses: you cannot rig, cannot start, cannot leave night 3. The
  selftest never opens that door, which is why 296/0/0 and unplayable are
  both true.

- The carport trap has no teeth. anchor.ratingHint and anchor.collateral are
  written by world.js:556-557 and read by nothing; sail.js:871 fails corners
  on hardware rating alone, and scoreRun() only ever bills the gnome. 46 m2
  hung off the carport through the funnel pays +$82 at garden 83%.

Also: boot({site}) is overwritten by showTonight() (inverse desync), the
'post' enum makes the carport unreadable pre-rig, the venturi measures 1.5-1.8x
at the throat after the change (works as shipped, don't drop the gain), and
the site is winnable off honest anchors at 98%.

THREADS-only; no code touched on lane/d this sprint.
This commit is contained in:
type-two 2026-07-17 17:25:09 +10:00
parent b38311021c
commit c0ad587321

View File

@ -3228,3 +3228,112 @@ anchors are your GLB), but the tooling is now waiting, not TODO.
· D's cold playthrough of site_02 — unblocked at last;
· A decides the carport collateral number and the Anchor.type enum widening D flagged;
· gate 3 (John plays the week) — FOUR sprints standing.
[D] 2026-07-19 — 🎮 **I PLAYED site_02 COLD (§gate 1.3, four sprints owed). The yard is good. Night 3 is
NOT PLAYABLE, and the carport trap is inert data.** Two of those are gate-1 blockers, both with
receipts. Played the real path — nights 1→2→3 on `index.html`, mouse, no shortcuts.
**1. BLOCKER — night 3 SOFT-LOCKS. Lane B, your `setWorld` ask IS the sprint.** Reaching the corner
block the way a player does, prep opens with **last night's sail still hanging in the new yard**
(tension labels P4/H2/H3 live over the carport, a `T2B BLOWN` marker) while the HUD says "pick 4
more corner(s)". The anchor panel lists `h1 h2 h3 t1..t2b p1..p4` — the BACKYARD's twelve — in a
yard that has none of them. The data layer is fine: `world`/`rigging.session`/`rig.anchors` all
re-point to `tr1,tr1b,q1..q4,cb1,cb2,cp1,cp2` correctly. It's the UI that doesn't:
**`typeof rigging.setWorld === 'undefined'`**, so main.js:450's `rigging.setWorld?.(world)` is a
silent no-op, and `createRiggingUI` snapshots `world.anchors` into markers at line 254 — at BOOT,
off backyard_01, once. Measured, not inferred: scene-traversing every `userData.anchorId` on night
3 returns exactly the backyard's twelve, at backyard coordinates (h2 at z=9.95, the old house
line); site_02's ten have **no markers at all**. So:
```
click a ring dead-centre → no error, no ticker, no corner. summary.corners === []
rigging.commit() → false → the Enter handler (main.js:788) returns early
⇒ you cannot rig, cannot start the storm, cannot leave night 3. The week ends there.
```
Nothing is thrown and nothing is logged — it is the quietest possible failure. **This is why the
selftest can say 296/0/0 while the game is unplayable: no test drives a site change through the
rigging UI.** An assert that cannot fail is decoration; so is a green suite that never opens the
door it shipped. `setWorld(world)` — rebuild markers + pickTargets, dispose the old — unblocks it.
**2. Lane A — `boot({site})` is dead, and it fails INVERSELY.** main.js:456 promises "opts.site lets
a debug boot jump straight to a site". It doesn't: :458 loads opts.site, then `showTonight()` at
:691 immediately re-runs `loadSiteInto(week.site)` = backyard_01 and overwrites it — but the
markers were built in between, off site_02. Result is bug 1 mirrored: **markers site_02, world
backyard**, from the first frame. Verified both directions. Either honour opts.site in the week or
delete the hook — right now it's a documented lie, and it's the hook anyone debugging a site
reaches for first.
**3. THE CARPORT TRAP DOES NOT EXIST YET — its data is read by nothing.** This is the one I'd want
ruled on before gate 2 eats the sprint. Two dead fields:
```
anchor.ratingHint world.js:556 writes it → NOTHING reads it. sail.js:871 fails a corner on
`c.load > c.hw.rating` — HARDWARE only.
anchor.collateral world.js:557 writes it → NOTHING reads it. scoreRun() main.js:610-613 only
ever pushes the gnome, on a blanket lost>=2.
```
So beam 0.22 / post 0.30 / fascia 0.35 / tree 1.0 are **inert**: every anchor in the game is exactly
as strong as the carabiner you hang off it. I played the exact line DESIGN warns about — 46 m²
across `cb1+cb2` in the early buster, straight through the funnel:
```
carport line cb1 cb2 q2 q3 → garden 83% 3/4 collateral NONE +$82 "THE GARDEN MADE IT"
honest line q1 q2 q3 q4 → garden 98% 3/4 collateral NONE
```
DESIGN promises "tie 25 m² to it in a southerly and you take the carport, and it lands on whatever's
under it." I tied 46 m² to it and **got paid**. The carport held; `q3` blew — cb1 was carrying 948 N
next to q3's 952 N and the sim has no reason to prefer one. The trap is currently a ~15 HP geometry
penalty (the carport is in the west corner, the bed is centre, so it drags coverage off the bed) —
directionally right, but not a trap. It reads *fine*, not buggy; it just doesn't bite.
**Lane A: the $180 ruling is bigger than SPRINT11 thinks — "change the constant, not the asset"
assumes a constant and a consumer, and there is neither.** It needs wiring: which anchor blew →
that anchor's collateral. **One landmine when you do:** `q1..q4` are built from site JSON, not GLB
nodes, so world.js:556 never runs for them and their `ratingHint` is **undefined** — the honest
posts carry no strength data at all. Wire anchor strength naively and the anchors that should be
the *strongest* read `undefined`. Default before you multiply.
**4. And the enum is why the trap can't even tempt (my SPRINT10 flag, now with a play consequence).**
Pre-rig the panel shows only `type`. The site JSON types all four carport anchors `'post'`, so a
cold player reads **eight identical "post" rows**`q1..q4` and `cb1/cb2/cp1/cp2` are
indistinguishable, and the carport's rating never surfaces at any point before or after rigging.
"Four free anchors that look free" isn't temptation if it looks *identical to the honest steel*
it's a coin flip, and a coin flip you can't lose (see 3). Widening to `'carport'` gives the trap its
only pre-rig read. This is the same bug shape as the ladder one I landed: a rule keyed on a type
string a new site doesn't fit.
**5. Lane C — good news, the venturi WORKS at the shipped numbers, and I measured it in the storm.**
axis 2.1 / gain 1.5, throat (6,0), sampling `wind.speedAt` through the change:
```
t=4..17.5 (before) throat/east 0.95 1.08 ← calm, indistinguishable from the rest of the yard
t=19..40 (after) throat/east 1.08 → 1.79 ← throat peaks 19.7 m/s vs 11.0 east
```
That is exactly the personality the site asks for: **calm until the southerly comes through, then it
screams**, and the throat sits on the carport (x=7) — the funnel howls precisely where the bad
steel is. That's a lovely piece of design and it's already live. Your 1.08 measurement and this
aren't in conflict — the ratio is throat-vs-east, not the bare venturi factor. **Don't drop the gain
on my account**: B, the site is winnable off honest anchors (q1..q4 → **98%**), so the funnel isn't
killing the $80 line, and E doesn't need to move the tree.
**6. The ladder trip — the site's stated thesis — did not fire in either run, and can't reliably.**
`needsLadder` is live and correct (cb1/cb2 y=2.29 > the 2.20 reach, `work: 'bracket'` → ladder;
q-posts are `work: 'cloth'` at y≈4.0 → you pull the cloth corner down, no ladder, which is the rule
doing its job). But the trip only happens when a **cb** corner blows, and nothing makes cb likelier
to blow than q — that's bug 3. Fix the collateral/rating wiring and the thesis fires by itself.
**7. Small one, Lane B:** `<- weak link` is arbitrary when the hardware is uniform. rigging.js:205
reduces with a strict `<`, so ties keep the first pick — it flagged `cb1` only because I clicked cb1
first. It happened to point at the genuinely worst anchor, by luck.
**Method, so anyone can re-run it:** the shipped code cannot give you a coherent cold boot on
site_02 (bug 1 breaks the night-3 path, bug 2 breaks `opts.site`), so I rewrote `NIGHTS[0]` to
`{storm:'storm_03b_earlybuster', site:'site_02_corner_block'}` before `boot()` in a scratch copy of
index.html — then :458, `createRiggingUI` and :691 all agree and :691's rebuild no-ops, which is the
same path the four backyard nights already take. Harness deleted; **nothing of mine is on lane/d
this sprint but this entry.** Also note for anyone playtesting from a headless/hidden tab: rAF is
throttled dead, so `SHADES.step(dt)`/`.render()` are the only honest drive — and the phase change
into prep needs one frame before the markers accept clicks (that's the harness, not the game).
**Verdict as the playtester: the corner block is a GOOD yard and I want it in the game.** It reads
instantly — two streets, the carport squatting in the west corner, the bed exposed in the middle,
the gum tree as the one honest high anchor. The blurb does real work. The 18s change (vs night 2's
30s) genuinely lands as "looks like night 2 and isn't". None of that is the problem. The problem is
that **the yard's whole argument — that the free anchors cost you — is currently unenforced**, and
that you can't reach the yard at all without B's `setWorld`. Both are small, sharp fixes. Neither is
a design question.