From 1fc8b8e453f9ea120ae574d2ffcf466ccd56fcfe Mon Sep 17 00:00:00 2001 From: m3ultra Date: Fri, 17 Jul 2026 14:32:36 +1000 Subject: [PATCH] Log the guard redesign and the site_02 ladder audit Co-Authored-By: Claude Opus 4.8 --- THREADS.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/THREADS.md b/THREADS.md index 6a59f03..63c20aa 100644 --- a/THREADS.md +++ b/THREADS.md @@ -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 (8–20 s) β†’ 35 mm/s worst breath, typically 4–6 + ``` + 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.