Log the guard redesign and the site_02 ladder audit

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-17 14:32:36 +10:00
parent 942709d2e9
commit 1fc8b8e453

View File

@ -2650,3 +2650,61 @@ Format: `[lane letter] YYYY-MM-DD — note`
on the record, A's "1 lost" was a miscount, and C found the REAL winnable line (p1,p2,p3,p4 —
$80 exactly, hp 52, 1 lost) that needs B's porous fabric + C's 0.40 downdraft STACKED. The
pyrrhic-win rule and the fabric+downdraft pairing are SPRINT9's first moves.
[D] 2026-07-18 — 🔧 **GUARD REDESIGNED (§Lane D, with B) — it measures SHAPE now, and I proved it fires.**
Integrator: thank you for demoting it rather than deleting it, but **your stated cause doesn't
hold, and neither did my design.** Both worth recording:
· **The ponding diagnosis is wrong.** Every storm's rain curve starts at `[0, 0]`, so
`storm_02.rainMmPerHour(0)` is **0.0 mm/h** — a held clock rains *nothing*. (Also: your 2 s
windows are shorter than the cloth's breath. A settled rig reads a 32% trend at 2 s and **6%
at 3 s**. The window was the flake, not the water.)
· **The real confound was mine.** The guard measured in the STORM's wind while the rig settled
in CALM — and that calm→storm step is one **the real game also has** (`wind.use(to ===
'storm' ? winds[stormKey] : calmWind)` fires on the phase change). It was never a harness
artifact; the suite was being faithful and my guard was calling it a bug.
· **And fixing the clock isn't enough, because LOAD cannot answer this question at all.** In
calm there is no transient to see — the unsettled rig is *lighter* (0.30 kN vs 0.47 settled)
and the trend test **passes at every settle length from 0 s to 20 s**. A guard that cannot
fail is decoration, which is exactly what StumbleBack and the fake skips were.
So it asks the physical question instead — **has the cloth stopped moving** — and mean node drift
separates ~6× either side, immune to wind and water alike:
```
unsettled (0 s) → 212 mm/s (cover quad) · 208 (miss quad)
settled (820 s) → 35 mm/s worst breath, typically 46
```
Limit **100 mm/s**. **Proved it fails before trusting it to pass** (the habit this repo keeps
earning): sabotaged the settle to 0 s and it fired — *"line entered the storm with the cloth
still drifting 212 mm/s (limit 100)"*. Restored, all five balance asserts green, **275/0/0**.
**Your 600 N floor: blessed as reasoning, not carried as code.** It was the right amendment to a
LOAD design — "the trend only matters at a scale that can move a verdict" is correct and I'd have
kept it. Drift has no units of force to need a floor, and 212-vs-35 isn't a judgement call.
[D] 2026-07-18 — 🪜 **SITE_02 PREP — I audited the ladder against it rather than wait, and there IS a
seam. A/E: one field in the site JSON and I'm done.** site_02 isn't landed so I can't play it cold
yet; this is the half I could do now.
The prompt's hunch was right but the mechanism isn't height. `needsLadder` was spelled
**`type === 'house'`**, and contracts.js types anchors as a **closed enum `'house'|'tree'|'post'`
that a carport doesn't fit.** The failure mode is why it couldn't wait: if `needsLadder` says
false, **`canReach` in interact.js returns `true` UNCONDITIONALLY** — so on site_02 the player
re-rigs a 2.6 m carport bracket standing on the grass, and the ladder mechanic *silently stops
existing*. No error, no red. That's the same disease as StumbleBack's dead threshold, the fake
skips, and the camera-less shadow grid: **a rule keyed on the wrong thing, failing open.**
**A pure height test is NOT the fix** — posts (3.95 m) and tree limbs (5.05 m) are *higher* than
the 2.48 m fascia and need no ladder, because there you work the **cloth** (which has fallen to
where you stand) and here you work the **bracket** (which is on a wall). Height is a coincidence
of that distinction, not the distinction.
So it reads **data first**: `anchor.worksAtBracket` — precisely the pattern `anchor.ratingHint`
already uses from the GLB's `userData.rating_hint` — falling back to `type === 'house'`.
**Nothing on site_01 carries the flag, so it's a no-op there** (asserted both ways).
**Lane A:** when you extract the yard to `data/sites/*.json`, give anchors an optional
`worksAtBracket`. **Lane E:** type the carport however you like — set that flag on its anchors and
the ladder follows the site with zero code change. If you'd rather it were named or shaped
differently, say so now; it's one line and I have no attachment to the spelling.
Also: `ladder.js` is now headless-importable (lazy GLTFLoader, same as broom.js), because
`d.test.js` had been testing **fakeLadder's hand-copied duplicate** of `needsLadder` instead of
the rule itself. A rule the suite re-implements is a rule the suite cannot catch drifting — which
is the whole reason this repo has a balance suite that reads the yard from world.js.
[D] 2026-07-18 — ⏳ **Still owed by me: play site_02 cold** (blocked — A's site-as-data + E's corner
block haven't landed), and the full-week feel pass. Both are queued and neither blocks anyone. My
douse guard is still green, so pond masses haven't moved.