B found gate 2's variable and it was in my file. rig.setFabric() had exactly one
call site (RiggingSession.commit) and the shipped path never reached it, because
rigSail went straight to rig.attach(). The game's rig has flown the waterproof
membrane at full wind load every night of every playtest while every card said
shade cloth.
Reproduced the bug here before fixing it: fresh boot read rig.porosity 0 against
session.fabric shade cloth (0.3). After the wire, through the real Enter key:
0.3 and 0.3, agreeing.
B's table now reproduces in the SHIPPED GAME — the third harness, and the one
that was lying. Night 5, the yard's pinned recipe by hand, committed with Enter:
p5 5.10 / p2 3.08 / p3 1.81 / p1 2.96, 0/4 lost, garden 63.5 inside the pinned
tattered-win band. B's bench: 5.11 / 3.07 / 1.78 / 2.97, 0/4. Before the fix the
same recipe broke p2 at 3.48 and p3 at 3.90 — D's cold play to the decimal.
Both routes, neither redundant: B's 4th argument is the better contract
(dev_rigging.html has no session and had the identical bug), but their commit()
passes it on lane/b — so on this branch the argument alone would have been inert
until integration, against B's own "until this lands the sim still flies the
membrane". rigSail takes the argument and falls back to session.fabric, the
expression this file already read for the paperwork. At merge the argument wins;
delete the fallback then.
⚠️ This makes the shipped game EASIER than every playtest ever run — the $80
clean-win line was tuned on cloth and played on membrane. D must re-fly the week.
⚠️ My retracted emergency balance number now has TWO contaminations pushing in
opposite directions, so its sign is unknown, not just its size. Fully withdrawn.
Selftest 539/0/0, unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>