Lane B S16: THREADS — gate-2 entries (heal, record, refusals, membrane table, crossing closed); fabricnote as verdict-sibling for A's ledger merge

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-20 20:55:03 +10:00
parent f7a22eabb8
commit f84e00f46b
2 changed files with 185 additions and 7 deletions

View File

@ -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, **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 its pins stand on post-ruling numbers as designed, and the swing lawn is waiting to become a
real night.** 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_SUBSTEPS1)×SIM_DT ≈ 66.7 ms; a 6783 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 $40120 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.

View File

@ -124,8 +124,10 @@ const CSS = `
#hud-card .verdict.win { background:#12321c; border:1px solid #2c6b3c; color:#7fce6a; } #hud-card .verdict.win { background:#12321c; border:1px solid #2c6b3c; color:#7fce6a; }
#hud-card .verdict.lose { background:#3a1618; border:1px solid #7d2b2b; color:#ff8f86; } #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 /* 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. */ 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; } 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 ---------------------------------------------------------- */ /* --- the week ---------------------------------------------------------- */
#hud-card .pips { letter-spacing:.5em; font-size:15px; margin:-6px 0 10px; color:#3f5561; } #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) {
<h2>${r.subtitle}</h2> <h2>${r.subtitle}</h2>
${rows} ${rows}
${money} ${money}
<div class="verdict ${r.win ? 'win' : 'lose'}">${r.verdict}${ <div class="verdict ${r.win ? 'win' : 'lose'}">${r.verdict}</div>
// gate 2.2's second half: when the fabric bet provably mattered the ${/* SPRINT16 gate 2.2 [B] when the fabric bet provably mattered the
// verdict says so (fabricNoteFor's thresholds decide; null = silent, verdict page says so, one quiet line under the verdict (same
// and the existing verdict prose is byte-untouched either way). pattern as A's repline: the verdict div itself stays byte-
r.fabricNote ? `<div class="fabricnote">${r.fabricNote}</div>` : ''}</div> untouched). fabricNoteFor's thresholds decide; null = silent. */''}
${r.fabricNote ? `<div class="fabricnote">${r.fabricNote}</div>` : ''}
<button class="go">${next}</button> <button class="go">${next}</button>
${w?.client ? `<div class="terms">Payable 14 days. ${w.collateral ? 'Theyll want that made right by Friday.' : 'Thank you for your business.'}</div>` : ''} ${w?.client ? `<div class="terms">Payable 14 days. ${w.collateral ? 'Theyll want that made right by Friday.' : 'Thank you for your business.'}</div>` : ''}
</div>`; </div>`;