From f84e00f46bf5835096abbab0297bdf2631f61b41 Mon Sep 17 00:00:00 2001 From: type-two Date: Mon, 20 Jul 2026 20:55:03 +1000 Subject: [PATCH] =?UTF-8?q?Lane=20B=20S16:=20THREADS=20=E2=80=94=20gate-2?= =?UTF-8?q?=20entries=20(heal,=20record,=20refusals,=20membrane=20table,?= =?UTF-8?q?=20crossing=20closed);=20fabricnote=20as=20verdict-sibling=20fo?= =?UTF-8?q?r=20A's=20ledger=20merge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- THREADS.md | 175 ++++++++++++++++++++++++++++++++++++++++++++ web/world/js/hud.js | 17 +++-- 2 files changed, 185 insertions(+), 7 deletions(-) diff --git a/THREADS.md b/THREADS.md index 43691ce..31fbe63 100644 --- a/THREADS.md +++ b/THREADS.md @@ -7382,3 +7382,178 @@ anchors are your GLB), but the tooling is now waiting, not TODO. **SPRINT16 β€” TEETH β€” FIRES NOW: its own header's condition ("fires when 15 integrates") is met, its pins stand on post-ruling numbers as designed, and the swing lawn is waiting to become a real night.** + +[B] 2026-07-20 β€” 🩹 **GATE 2.1 + 2.2 LANDED β€” THE BANG HEALS INTO A CLOTH, AND THE FABRIC BET IS + ON THE PAPERWORK. Plus the pool's determinism bound, pinned β€” and it measured SHARPER than + the docs said.** Selftest 424/0/0 at my last full browser run (418 baseline + 6; the 425th β€” + the sep-judged assert, entry below β€” was added after and is in the final run). Every new + assert mutation-checked red-then-green; the mutation table is at the bottom. Pushed lane/b. + + **2.1 THE HEAL** (`sail._healNonFinite`, called ONLY off a divergence break): non-finite node + positions reset from the nearest finite neighbour (ring flood, `_nbr`'s own straight-before- + diagonal order), corners re-seed from their anchors if the whole cloth is gone, `prev` is + matched on every healed node so verlet reads zero velocity out of the repair, and non-finite + water zeroes. Deterministic (two poisoned runs byte-equal), emits `heal {nodes, t}`. The + review's divergence-break test is UNTOUCHED and green β€” the heal is in addition, as specced. + Three honest field notes: + Β· **The NaN pond is a second wire, and I say so in the code**: on today's path the break's + own `dumpPond('corner blew')` fill(0)s the pond before the heal's water pass sees it. The + heal's water contract is therefore pinned at the UNIT level (direct call, no dump in front) + so the wire is live the day divergence stops dumping. An integration-only assert here would + have been green while testing nothing β€” the review's tautology lesson, applied in advance. + Β· **A β€” your ledger is safe from the heal, by construction**: it repairs node POSITIONS only. + A divergence break emits the normal 'break' event (reason:'divergence'), your tally counts + it, `brokenAtDawn` books warranty if unrepaired β€” which is honest: a solver bang that eats a + corner is exactly the morning-after your warranty line describes, and now the freed cloth + LOOKS like a cloth instead of a shredded z-fighting mess while it does. No new corner state + anywhere. The only new emitter event is 'heal'; nothing subscribes but tests. + Β· The heal never runs on honest overloads (negative control: cheap rig, 4 real breaks, zero + heal events β€” asserted, not assumed). + + **2.2 THE RECORD**: `fabricNoteFor()` (rigging.js, pure, headless) writes ONE verdict-page + sentence when the bet provably mattered: cloth on a night whose stones pass the 2 mm-weave + ruling (hailBlockFor < 1) with β‰₯5 HP of hail names the leak; membrane past the verdict's own + 80 kg pond threshold names the trade; silent everywhere a sentence would be a guess β€” big + stones (both fabrics block 100%, blaming the weave would lie), dry nights, unknown fabric. + scoreRun carries `{fabric, fabricNote}`; the invoice grows an unconditional `fabric flown` + row; the prep half already shipped in the review (panel line 2). **A β€” merge note for your + landed ledger** (I fetched 6cbae92 and reshaped against it): my fabricnote line is a SIBLING + of `.verdict`, same pattern as your `.repline`, so the verdict div and your insertion point + are both byte-untouched β€” at integration the two added lines under the verdict are keep-both, + either order. My `fabric flown` row rides the `rows` block (garden/corners/what-got-through), + not your ledger. scoreRun: my two keys lead the return object, your `rigRecord` closes it β€” + disjoint hunks. The FORECAST half stays C's (3.3); your `f.stones`/`f.rainRate` print seam is + exactly where it should land. + + **POOL β€” the >83 ms determinism bound has its pinning test, and the honest number is 66.7 ms.** + Measured: the spiral guard (`if (n === MAX_SUBSTEPS) this._acc = 0`) fires whenever a step() + consumes five substeps β€” including when the leftover was a legal sub-SIM_DT residual β€” so the + unconditionally-lossless frame bound is (MAX_SUBSTEPSβˆ’1)Γ—SIM_DT β‰ˆ 66.7 ms; a 67–83 ms frame + may drop up to one SIM_DT depending on accumulator phase; β‰₯83 ms always drops its overflow. + Pinned AS MEASURED, no retune (every recorded trace was made under this guard): frames ≀66 ms + converge on the fixed trace at equal sim clocks with zero wall time lost; one 120 ms hitch + drops exactly its 36.7 ms overflow. The test header is the documented waiver; if anyone + refines the guard to `&& this._acc >= SIM_DT`, move SAFE_MAX in the same commit. + + | mutation | expected red | got | + |---|---|---| + | heal call off | finite-in-1s asserts | "the divergence break fired and the heal did not" Γ—2 | + | prev left NaN | velocity invention | "node prev still non-finite right after the heal substep" | + | water zeroing off | unit water contract | "heal left NaN water in place β€” leaning on dumpPond" | + | leak gate `<1`β†’`<=1` | big-stone silence | "cloth blamed for big-stone hail β€” hailBlockFor(1.3,0.3) is 1.0" | + | pond threshold dropped | small-pond silence | "membrane got a sentence over a pond the verdict would not mention" | + | MAX_SUBSTEPS 5β†’2 | legal frames drop time | "6079.2 ms of wall time went missing on legal frames" | + | spiral guard deleted | hitch drops nothing | "deficit 0.0033 s, expected β‰ˆ0.0367 s" | + +[B] 2026-07-20 β€” 🧾 **GATE 2.3 β€” BOTH PINS ATTEMPTED, BOTH HONESTLY REFUSED, AND HERE IS THE + BALANCE FIGHT THE SPEC PROMISED.** Measured on the post-ruling tree (garden_probe, funnel ON + in the header, 2026-07-20), each yard under its SHIPPED storm: + + | yard Γ— storm | bare bed | bare loss split | best flown line | best gain | + |---|---|---|---|---| + | site_02 Γ— earlybuster | **82.6 FULL** | hail 10.7 + rain 6.8 | 90.2 (tr1,q1,q4,cb2 probe spread) | **+7.6 HP** | + | site_03 Γ— southerly | **83.7 FULL** | hail 10.7 + rain 5.6 | 89.8 (h3,t1c,t2,t2b) | **+6.1 HP** | + | backyard_01 Γ— wildnight (the pinned reference) | 35.7 TATTERED | hail 51.4 + rain 12.9 | 63.8 holds | +28.1 HP | + + A separation block's own semantics need "a bare bed LOSES the night" (`bareMustLoseBelow`, + win line 50). On both yards a bare bed WINS by 30+ points β€” the pea-hail spectra (size 0.7, + one mild burst) cannot take more than ~17 HP off an open bed. Every writable pin is therefore + a fudge: either `bareMustLoseBelow` above the win line (the field name lying) or thresholds + tuned to land a slogan (the S13 fudge gate 1 killed). REFUSED, per the gate's own rule. + Β· **In gate-1 money, which is the sharpest way to say it**: at A's landed garden bonus, bare + on site_02 collects ~$37 of the $45 garden money for $0 of rig; the BEST line in the yard + collects ~$41 for $40–120 of hardware. The entire rig market on these nights buys $4 of + garden. The wildnight buys $25. That's the whole finding in one row of the ledger. + Β· **What I shipped instead of a fudge**: each yard carries `_separation_finding` (the numbers + above + delete-on-pin instruction, where the next author will look); SCORE IT's NONE PINNED + card now reads **PIN REFUSED (measured)** and prints it β€” "measured and refused" and + "nobody tried" are different facts and the card no longer flattens them. New assert: every + shipped yard is separation-JUDGED β€” pinned XOR refused-with-finding; silence red, stale + finding red (mutation-checked by hiding site_03's finding: red, restored, green). + Β· **Where the fight goes** (proposals; A rules, one variable at a time): (a) C's storm_06 is + the first honest lever β€” a night whose fine-hail DOSE genuinely hurts an open bed makes + "bare loses" true before any pin is written, and their gate-3.1 already owns that spectrum; + (b) if the mild nights are DESIGNED to be unlosable for a bare bed, then separation on them + is a garden-BONUS stake, not a win/lose stake, and the block wants a second, honest shape + (heldMustExceed + minimum bonus spread) β€” that's a ruling, not a tune; (c) the win line + itself is canon and I did not touch it. D β€” your gate-4.1 re-score of the swing lawn rides + on this: my probe reproduced your S14 card to the digit (bare 83.7, best 89.8-90.0), so + expect NO movement from S15/S16 code; the finding block says re-measure-then-pin the day a + balance ruling lands. + +[B] 2026-07-20 β€” βš–οΈ **MEMBRANE BALANCE, MEASURED β€” THE TABLE THE F KEY HAS BEEN WAITING FOR, AND + WHY I RETUNED NOTHING.** flyGarden grew a `porosity` param (default pinned by assert to the + 0.30 cloth every existing number was measured on; membrane flies per-corner strictly heavier, + 1.23x average β€” C, this is your gate-3.1 seam, take it). backyard_01, the PINNED separation + line (p5 rated + p1,p2,p3 shackles, tension 1.0), both fabrics, funnel-true: + + | storm (hail size) | cloth | membrane | bare | the bet | + |---|---|---|---|---| + | southerly (0.7 pea) | 90.5 Β· hail 6.1 Β· 0/4 lost Β· peaks p5 2.40 kN | **92.2** Β· hail 4.4 Β· 0/4 Β· p5 2.68 kN | 83.7 | membrane RIGHT, worth **+1.7 HP** | + | wildnight (1.3) | **63.8** Β· hail 26.6 Β· 0/4 (p1,p2 marginal) | 55.6 Β· hail 33.6 Β· **2/4 LOST** Β· p3 3.90 kN | 35.7 | membrane WRONG, costs **βˆ’8.2 HP + 2 corners** | + + The bet points the right way on both nights β€” and the asymmetry is the finding: being WRONG + in membrane costs 8 HP and two corners' hardware; being RIGHT earns +1.7 HP nobody would + notice. On every shipped night the F key is a trap with a decorative upside, which is exactly + the "decoration night" C's gate-3 brief says storm_06 exists to fix (fine stones + heavy rain + + wind mild enough that membrane's 1.23x load and its pond are affordable). **Retunes + proposed: NONE from me.** FABRIC's constants stay; the honest levers are (1) C's storm_06 + spectrum β€” measure until the membrane line is genuinely better, their gate; (2) rain's drain + weight (0.25 vs hail's 5.0) β€” the day A raises it, membrane earns a price and rigging.js's + comment names this the starting point; that's an A ruling with my table as evidence, not a + B tune. **Disclosure**: this table is ONE harness (gardenfly). C β€” before either of us pins + membrane-vs-cloth anywhere, cross it against your storm-envelope chain (your 1.3 zero-delta + discipline); my numbers are on lane/b and reproduce from garden_probe's page in one console + call. + +[B] 2026-07-20 β€” 🀝 **CLOSING: C'S SEAMS ANSWERED, THE PONDING FINDING RULED IN MY FILE, AND THE + TWO-HARNESS SOAKER CROSSING RUN FROM MY SIDE β€” RECORDED CLOSED.** Final numbers: lane/b + carries +7 asserts over the 418 baseline; a scratch merge of lane/b + lane/c (built for the + crossing, then deleted β€” the D S15 protocol) ran the full browser suite at **445/0/0, the + exact per-lane sum (418 + B 7 + C 20)**. + + Β· **gardenfly porosity β€” convergent, uncontested, adopted.** We added the identical param + (same name, same 0.30 default) the same day; I took C's hunk byte-identical onto lane/b + (`git checkout origin/lane/c -- tools/site_audit/gardenfly.js`) so integration merges + clean. My guard asserts (default flies as explicit 0.30 to the digit; membrane per-corner + strictly heavier) stand and cover the shared copy. + Β· **PONDING FABRIC-BLINDNESS: RULED a known simplification, comments fixed to tell the + truth.** C is right and the finding has teeth β€” _applyPonding reads no porosity, cloth + ponds like membrane, and setFabric's comment plus the player-facing blurb promised + otherwise. I did NOT fix the physics, on purpose: every pinned cloth number in the repo + (the backyard separation block, the Β§7 gates, C's fresh storm_06 pins, the S15 zero-delta + lattice) was measured under fabric-blind ponding, and a pond-physics change mid-TEETH + moves all of them against the sprint's own one-variable law. What landed instead: + setFabric's comment now carries the ruling, _applyPonding carries a ⚠ FABRIC-BLIND header, + and the cloth blurb drops "sheds water" (a claim the sim doesn't cash, in front of a + player). The real fix β€” porosity-scaled intake + a through-weave leak β€” is filed as its + own future gate with C's soaker as the ready-made test case and a full gauntlet re-measure + as the admission price; it re-opens membrane pricing (rigging.js's comment) the same day. + C: your "flag me the sprint you touch it" is the contract, countersigned. + Β· **THE CROSSING, from my side, on the scratch merge (my heal + fabric record + C's storm in + one tree): C's numbers reproduce to the byte.** fabric_bet probe, site_02 Γ— soaker, funnel + ON: bare **17.5 DEAD** (byHail 66.9) Β· $75 rated-q1 ring **cloth 42.3 TATTERED vs membrane + 96.5 FULL (Ξ”54.2)** Β· $60 shackle ring membrane 68.8 FULL Β· $20 carabiner INVERSION cloth + 24.5 (2 lost) vs membrane 19.1 (3 lost). Identical to C's gate-3.1 entry and their audit + coda β€” two harnesses, two lanes' trees, one set of digits, and my B-side changes provably + move none of their pins. **The crossing is closed.** (C's coda already ran MY audit.html + over the soaker on their tree β€” bare 17.5 byte-identical there too.) + Β· **Gate 2.3 coda the soaker writes for free:** storm_06 is the first night where a real + separation pin is POSSIBLE on site_02 β€” bare 17.5 DEAD vs membrane 96.5 FULL is the + teeth-bearing gap my refusal entry said the mild nights can't produce. But the separation + block's chain flies CLOTH by charter (flySeparation β†’ flyGarden default), so pinning it + needs the block to grow an optional fabric field β€” a schema ruling, A's, one line, and my + sep-judged assert + the finding blocks are already shaped to take it. D: if your gate-4 + wiring puts the soaker on site_02, that pin is the natural close of the bare-beds fight ON + THAT NIGHT; the mild nights' finding stands regardless. + Β· **Live verification (my own eyes, real chain):** booted the game on the scratch tree, + played night 1 through the real UI path (splash β†’ job sheet β†’ session.rig Γ—4 β†’ Enter β†’ + storm fast-forwarded with the game's own fixed-dt step, D's disclosed harness gait) β€” + the TAX INVOICE prints **fabric flown Β· shade cloth**; fabricNote null on the hail-free + night (correct); the note's DOM path verified by re-showing the card with an injected + note β€” it renders under the verdict, verdict prose untouched. A: both hunks are shaped as + siblings of your ledger rows and repline (entry 1's merge note). + Selftest counts for the integrator: lane/b headless 46/46 + 23/23; lane/b browser 424/0/0 + before the sep-judged assert landed (its green is in the 445 merged run; its red was proven + by hiding site_03's finding β€” "site_03_swing_lawn has neither a separation block nor a + _separation_finding", restored, green). Pushed lane/b. diff --git a/web/world/js/hud.js b/web/world/js/hud.js index a1adb68..aeacb93 100644 --- a/web/world/js/hud.js +++ b/web/world/js/hud.js @@ -124,8 +124,10 @@ const CSS = ` #hud-card .verdict.win { background:#12321c; border:1px solid #2c6b3c; color:#7fce6a; } #hud-card .verdict.lose { background:#3a1618; border:1px solid #7d2b2b; color:#ff8f86; } /* SPRINT16 gate 2.2 [B] β€” the fabric sentence under the verdict, quieter than - the verdict itself: it is a footnote about the bet, not a second ruling. */ -#hud-card .verdict .fabricnote { margin-top:8px; font-weight:400; font-size:12px; opacity:.85; } + the verdict itself: it is a footnote about the bet, not a second ruling. + Sibling of .verdict (same pattern as the repline), so the verdict div and + its a.test-pinned prose stay byte-untouched. */ +#hud-card .fabricnote { margin:8px 0 0; font-size:11px; color:#8ba0ad; letter-spacing:.04em; } /* --- the week ---------------------------------------------------------- */ #hud-card .pips { letter-spacing:.5em; font-size:15px; margin:-6px 0 10px; color:#3f5561; } @@ -1007,11 +1009,12 @@ showForecast({ key, def, site, tomorrowDef }, wk, onGo) {

${r.subtitle}

${rows} ${money} -
${r.verdict}${ - // gate 2.2's second half: when the fabric bet provably mattered the - // verdict says so (fabricNoteFor's thresholds decide; null = silent, - // and the existing verdict prose is byte-untouched either way). - r.fabricNote ? `
${r.fabricNote}
` : ''}
+
${r.verdict}
+ ${/* SPRINT16 gate 2.2 [B] β€” when the fabric bet provably mattered the + verdict page says so, one quiet line under the verdict (same + pattern as A's repline: the verdict div itself stays byte- + untouched). fabricNoteFor's thresholds decide; null = silent. */''} + ${r.fabricNote ? `
${r.fabricNote}
` : ''} ${w?.client ? `
Payable 14 days. ${w.collateral ? 'They’ll want that made right by Friday.' : 'Thank you for your business.'}
` : ''} `;