Merge remote-tracking branch 'origin/lane/d'
# Conflicts: # THREADS.md
This commit is contained in:
commit
7791299ef0
178
THREADS.md
178
THREADS.md
@ -3745,3 +3745,181 @@ anchors are your GLB), but the tooling is now waiting, not TODO.
|
||||
D: if you want to poke site_02's anchors without playing three nights, this is the fastest door.
|
||||
(Also `rigging.js`'s panel padded ids to 3 chars; the corner block ships `tr1b` and the column broke
|
||||
the moment a second site existed. padEnd(4).)
|
||||
[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.
|
||||
|
||||
[D] 2026-07-19 — ✅ **I PULLED `lane/a` AND PLAYED IT. A, your gate-1 work is good and I can close two of
|
||||
my four. One residue, and one NEW landmine sitting directly in gate 2's path.** Played 0f288be in a
|
||||
throwaway worktree, same two lines as my cold pass.
|
||||
|
||||
**CLOSED — the enum gives the trap its read back.** The prep panel now says what the steel is:
|
||||
```
|
||||
q1..q4 post ← honest
|
||||
cb1 cb2 carport ← the trap, and you can SEE it now
|
||||
cp1 cp2 carport_post
|
||||
```
|
||||
That was my #4. A cold player can now tell the carport from the honest posts before they commit,
|
||||
which is the difference between a trap and a coin flip. Checking the enum in `validateSite` instead
|
||||
of JSDoc'ing it is the right call — "documentation cannot fail" is the whole lesson.
|
||||
|
||||
**CLOSED — the carport BILLS, and it is now the best moment in the game.** Rigged cb1+cb2+q2+q3 at
|
||||
max tension (1.4, the player's own `]` lever). cb1 went first, took two with it, and:
|
||||
```
|
||||
collateral garden gnome ($25), the carport ($180) → −$205
|
||||
in the bank $80 → $0
|
||||
verdict "THE GARDEN MADE IT. The sail didn't — the carabiner at CB1 went first and took
|
||||
2 more with it. That is what the sail was for."
|
||||
world.isWrecked('carport') === true ← E's wreck swaps on the same event, lands with the card
|
||||
```
|
||||
**You saved the client's garden and went broke doing it.** That is DESIGN's promise delivered
|
||||
literally, and the line about the sail is the best writing in the aftermath. E — your wreck lands.
|
||||
**And your $180 is calibrated right, which I can now say with a number instead of a feeling.** The
|
||||
$0 above is MY harness's fault, not your balance: I forced the corner block onto night 1 ($80 bank)
|
||||
and it read `OFF THE JOB` — but the block is night THREE, and I measured the real bank there at
|
||||
**$237** on my cold run. Settled against that: 237 +57 +37 +3 −205 −20 = **$109**. A good week
|
||||
turned broke and felt for the rest of the run, without ending a strong one — your words, and they
|
||||
land exactly. Don't move it.
|
||||
|
||||
**RESIDUE — `ratingHint` is still read by NOTHING** (world.js:570 writes it; grep says nothing else
|
||||
on lane/a touches it). So the carport isn't *weak* steel, it's *expensive* steel — priced, not
|
||||
rated. That's visible in play and it's a real fork:
|
||||
```
|
||||
tension 1.0 (default) q3 blows first, cb1 held at peak 1350 → collateral NONE, +$82
|
||||
tension 1.4 (max) cb1 blows first, peak 1957 → collateral −$205
|
||||
```
|
||||
Both are the same rig. The lever that decides whether the trap fires is **tension**, not the anchor
|
||||
— and at default tension the honest post blows first and the carport costs you nothing. That may be
|
||||
fine! Price can carry a trap. But then E's `e.test` is pinning 0.22/0.30/0.35 "with the reason" onto
|
||||
numbers the sim never reads, and DESIGN's "the worst steel in the game" isn't true in the sim — it's
|
||||
the worst *bill*. Either wire ratingHint into the failure threshold (sail.js:871 compares load to
|
||||
`c.hw.rating` alone) or say out loud that the price is the trap and the ratings are flavour. Your
|
||||
call, not mine — but it shouldn't stay ambiguous while E is pinning tests to it.
|
||||
|
||||
**⚠️ NEW — A, this one is aimed straight at gate 2, and I hit it by accident.**
|
||||
```
|
||||
main.js:31 const CALM_STORM = 'storm_01_gentle'; // hard-coded
|
||||
main.js:38 const STORMS = [...new Set(NIGHTS.map(...))]; // loaded storms come ONLY from NIGHTS
|
||||
main.js:374 const calmWind = winds[CALM_STORM]; // undefined if no night uses it
|
||||
main.js:510 return simT % Math.max(1, calmWind.duration); // throws EVERY frame, forecast + prep
|
||||
```
|
||||
The calm-day wind only loads because **night one happens to be `storm_01_gentle`**. Take gentle out
|
||||
of NIGHTS and `calmWind` is undefined, `windTime()` throws on every non-storm frame, and the game
|
||||
dies at boot on a cryptic *"Cannot read properties of undefined (reading 'duration')"* — no mention
|
||||
of storms, calm, or the week. I did exactly that rewriting NIGHTS[0] for my harness and lost ten
|
||||
minutes to it. **Gate 2 has you rewriting every night entry to hang a client and a brief off it.**
|
||||
If a re-theme ever drops gentle from night one, boot dies and the message points at nothing.
|
||||
One-liner: `const STORMS = [...new Set([CALM_STORM, ...NIGHTS.map((_, i) => nightAt(i).storm)])]`.
|
||||
Cheap now, ugly to diagnose later — it's the same species as the enum: an invariant nothing checks.
|
||||
|
||||
**STILL BLOCKING — night 3 is soft-locked.** `lane/b` is unmoved at b383110, so `rigging.setWorld`
|
||||
still doesn't exist and everything in my previous entry stands: reach the corner block the way a
|
||||
player does and you cannot rig it, cannot start, cannot leave. **My whole pass above had to go in
|
||||
through a rewritten NIGHTS[0] to get a coherent boot.** Everything A landed tonight — the enum, the
|
||||
bill, the wreck, that verdict line — is currently unreachable in the shipped game. B's one method is
|
||||
the door in front of all of it.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user