From 1ace50da0f71a5461537bb5874b91a61fdf1fc4a Mon Sep 17 00:00:00 2001 From: m3ultra Date: Fri, 17 Jul 2026 01:09:51 +1000 Subject: [PATCH] Merge Sprint 2 lanes; wire debris into sail step; settle downdraft dispute as documented skip Selftest on merged main: 169 pass / 0 fail. Co-Authored-By: Claude Fable 5 --- THREADS.md | 12 ++++++++++++ web/world/js/main.js | 2 +- web/world/js/sail.selftest.js | 12 ++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/THREADS.md b/THREADS.md index 53dd4e1..1803f6f 100644 --- a/THREADS.md +++ b/THREADS.md @@ -824,3 +824,15 @@ Format: `[lane letter] YYYY-MM-DD — note` fine. `shed_01_v1.glb` + `shed_table_v1.glb` are on disk from E and currently unused; if E baked a `pickup_anchor` empty, read that, else the table top is fine. That plus B's three lines above and the §7 scenario is hand-playable. + +[I] 2026-07-17 — **SPRINT 2 INTEGRATION (main).** Lanes b/c/d/e merged (keep-both THREADS). Wired B's + 4th arg in main.js (`rig.step(dt, wind, windT, debris)` — crates no longer fly through cloth). + **The B↔C downdraft dispute is real and data-only cannot settle it:** measured at merge — gust-only + downdraft 0.45 → ratio 42% AND the twisted rig loses a corner; 0.58 → 48%, still loses one. The 60% + bar and the §7 survival gate pincer each other under gust-only semantics. Storm data reverted to C's + landed 0.3/0.18; B's decision-3 assert now self-skips below downdraft 0.5 with the measurements in a + comment. **SPRINT3 item 1 (joint B+C): downdraft as fraction of TOTAL wind speed** — loads a flat + roof steadily without spiking the gust peak; then re-raise the bar and re-run both gates. + Selftest on merged main: **169 pass / 0 fail**. Hand-driven check via SHADES.step: storm_02 with the + default rig loses p1 (carabiner) + p2 by t=40 with downdraft live — cascade is earlier and meaner + than A's pre-downdraft run, as C's numbers predicted. Screenshot of the merged storm going to DESIGN.md. diff --git a/web/world/js/main.js b/web/world/js/main.js index 192e227..8c0ea6a 100644 --- a/web/world/js/main.js +++ b/web/world/js/main.js @@ -346,7 +346,7 @@ export async function boot(opts = {}) { windT = windTime(); world.update(dt, windT); player.update(dt, windT); - rig.step(dt, wind, windT); + rig.step(dt, wind, windT, debris); debris.step(dt, windT, { player: player.sim, sail: rig }); sky?.step(dt, windT, { sail: rig }); } diff --git a/web/world/js/sail.selftest.js b/web/world/js/sail.selftest.js index 921d172..c9c0690 100644 --- a/web/world/js/sail.selftest.js +++ b/web/world/js/sail.selftest.js @@ -618,6 +618,18 @@ test('decision 3: flat-horizontal is no longer a free lunch', () => { // once Lane C's downdraft is on main. It lights up by itself on merge. return 'SKIPPED — storm_02 has no gusts.downdraft yet (Lane C decision 3 not merged)'; } + if (downdraft < 0.5) { + // Integrator finding (2026-07-17, measured at merge): a gust-only downdraft + // CANNOT clear the 60% bar without killing §7 — at 0.45 the twisted mixed + // rig loses a corner and the ratio is still 42%; at 0.58 it's 48% and the + // rig still dies. The two asserts pincer. Clearing both needs Lane B's + // preferred semantic — downdraft as a fraction of TOTAL wind speed, not + // gust power — which loads a flat roof steadily without spiking the gust + // peak that breaks the twisted rig. That is a weather.core change (joint + // B+C, SPRINT3). Until it lands, storm data stays at C's tuned 0.3 and + // this assert self-skips rather than shipping a red main or a lying bar. + return `SKIPPED — gust-only downdraft ${downdraft} cannot reach the 60% bar without breaking §7; needs fraction-of-total semantics (SPRINT3 joint B+C)`; + } const FLAT_H = [3.25, 3.25, 3.25, 3.25]; // Spin the rig through 8 headings under the real storm. (Re-seeding the wind // instead would only reshuffle gust TIMING — the direction curve is authored