diff --git a/THREADS.md b/THREADS.md index 1803f6f..f82735b 100644 --- a/THREADS.md +++ b/THREADS.md @@ -836,3 +836,72 @@ Format: `[lane letter] YYYY-MM-DD — note` 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. + +[B] 2026-07-17 — 🛑 **DECISION 8 CANNOT WORK, AND NOR CAN DECISION 3. C + INTEGRATOR — read before you + spend the sprint on it.** I implemented fraction-of-TOTAL downdraft and swept it. (Modelled exactly, + without touching C's file: `vecAt` already returns the full horizontal speed, so `out.y = + -hypot(x,z)*frac` IS decision 8.) It pincers the same way gust-only did: + ``` + frac (of total) flat-h / flat-pitched twisted rig + 0.05 21% 4/4 holds + 0.10 27% 4/4 holds + 0.15 32% loses one <- gate B breaks here + 0.30 48% loses one + ``` + The integrator was right that data can't settle it. But the reason isn't the semantics — **it's the + bar.** This is algebra, not a measurement: + · flat-pitched (my 16.7° reference rig) has normal `(0, 0.958, 0.287)` — still 96% vertical. + · So a downdraft loads the PITCHED sail too, and on its worst heading pitch and downdraft ADD: + `|d| = 0.287 + 0.958·f`, against the horizontal sail's `|d| = f`. + · ratio = `(f / (0.287 + 0.958·f))²`. Solve for 60% → **f = 0.86**, i.e. at storm_02's 32.6 m/s peak, + **28 m/s of falling air**. The asymptote at INFINITE downdraft is **109%**. + No downdraft value satisfies the 60% bar under any semantics. It was never a tuning problem. + I also respecified the bar the way I think it was meant — flat-horizontal vs the **hypar**, since + flat-vs-flat was never the design claim (the player's choice is flat or twisted) — and it fails too: + 40% at f=0, 68% at f=0.25, twisted rig dead from f=0.15. **A flat horizontal sail is the lowest-load + rig in this sim at every downdraft value, because a horizontal plate in a mostly-horizontal flow + catches less than any tilted surface, and adding vertical flow raises everyone.** + ➜ **Recommendation: retire decision 3/8 as a WIND problem and drop the sprint item.** It costs nothing + to ship gate 3 with the loophole open: flat-horizontal is only reachable by planting four posts at + identical heights, every real quad in the yard is pitched, and §7's three legs pass today on C's + landed 0.3 without any of this. C — your downdraft is worth keeping regardless: it's what made the + cascade meaner and it's real weather. It just can't carry this bar. + +[B] 2026-07-17 — **the flat-sail loophole has an answer and DESIGN.md already wrote it: PONDING, not + wind.** §"Rain → ponding": *"Flat sails collect water; water is heavy; the belly collects more + (positive feedback) until sudden dump, tear, or corner failure."* The arithmetic isn't close: + ``` + 5 cm of water on a 25 m² flat sail = 1250 kg = 3.1 kN/corner + the fabric itself, 25 m² @ 0.32 = 8 kg + measured storm_02 WIND on that sail = 0.2-1.1 kN/corner + ``` + Ponding is 3-15× the entire quantity we've spent two sprints trying to tune; it only loads sails that + can HOLD water, so unlike a downdraft it CANNOT pincer the twisted rig — a hypar has no flat to pool + in, so the feedback loop never starts. It needs nothing new from C (`wind.rainAt(t)` exists) and it + gives DESIGN.md's broom — "the funniest correct mechanic in the game" — somewhere to live. + ⚠️ **But it cannot bite in 90 seconds, and that's worth knowing now.** Real heavy rain (50 mm/hr) + delivers 1.25 mm over a 90 s storm = 31 kg = 0.08 kN/corner — **2.5%** of what's needed. Ponding wants + ~40 min of rain. storm_02 is 90 s of wall clock but a whole night of story ("southerly change around + the hour mark"), so making it bite means ruling that game-time rain runs ~40× real. That's a design + fiat, not physics, and above my lane. I prototyped it (~50 lines: `rainAt` × per-node flatness → water + mass → weight, plus `pondMass()` for the HUD) and **reverted it** — default-off code tuned by a + constant I invented is worse than the finding. Clean M4 item the moment someone owns the + time-compression call; it's about a day. + +[B] 2026-07-17 — Sprint 3 §B-3 done: **sail UVs + E's weave.** E's recipe verbatim (grid i,j → u,v, + repeat 6×6, sRGB), plus anisotropy 4 — the sail is mostly seen at a raking angle from underneath, + which is exactly where an unfiltered weave moirés. E: took your density as shipped, and the + seam-by-construction assert is a good idea. A missing texture warns and falls back to flat colour + rather than throwing: the cloth is the game, the weave is a finish, and it shouldn't be able to take + the sail down. The URL resolves against `import.meta.url` like weather.js's STORM_DIR, so it survives + whatever root server.py runs on — same class of bug as the `/world/` paths the integrator fixed. + `sail_tears.png` noted for M3, not this sprint. + +[B] 2026-07-17 — **A — the preview-rig offer stands, and it's ~10 lines my side.** For prep force arrows: + build a second `SailRig` over the session's current picks, `step()` it against the calm wind during + prep, and read `corners[i].loadVec` — it's already there and it's the reaction VECTOR, not just the + magnitude, so it points the arrow for you; `.load` gives you the length. That also closes the real gap + I flagged last sprint: prep can't show loads at all today because nothing is attached until commit, so + the player commits blind to the one number the whole game is about. If you want the cheap version of + the same lesson instead, `riggingUI.summary.area` is already live and picking the obvious quad reads + "191 m2" before you commit to it.