HardYards/web/world
type-two 4718548c38 Lane B S18 gates 2+3+1: ⚠️ THE VARIABLE IS POROSITY; the clean boundary is DWELL; the knife
One landing, three gates and Lane C's clock finding. (Not split: sail.js,
rigging.js and balance.test.js each carry work for more than one gate and a
per-hunk split would have been fiction.)

GATE 2 — THE VARIABLE IS `porosity`, AND THE LIAR WAS THE GAME.
`rig.setFabric()` has exactly one call site, `RiggingSession.commit(rig)`, and
the shipped commit path never reaches it: the rigging UI's commit() calls
onCommit and main.js's rigSail goes straight to rig.attach(). So
session.commit(rig) runs in TESTS AND BENCHES ONLY, and the sim's rig (built
once at boot as `new SailRig({anchors})`, porosity defaulting to 0) has flown
the waterproof membrane every night of every playtest while the panel, the
SCORE IT card, the HUD row, the invoice and every audit number said shade
cloth. The F key moved the paperwork and never the physics.

    shade cloth 0.30 (what every card promised)  0/4 lost  p2 3.07  p3 1.78
    membrane 0      (what the sim actually flew)  2/4 lost  p2 3.48  p3 3.90

Row two is D's cold play AND the pin's own _playedReference (hp 55.7, p2 then
p3) to the decimal, reproduced in the shipped game. It also retires C's
"benches under-read the real UI by 5-15%, cause unfound": with the fabric held
equal, the bench and the FULL game chain agree to three decimals, two sites,
two storms. Debris hits on the sail: 0 — D's candidate ruled out by
measurement. Fixed on my side: commit() carries the fabric as onCommit's 4th
argument; dev_rigging.html picks it up, which is the shape of the one-line
pickup filed for A's rigSail.

GATE 3 — THE CLEAN BOUNDARY IS THE FUSE, NOT A PERCENTAGE. Same flight, two
corners, identical $15 shackles, same 3.2 kN rating:
    p1  3.528 kN = 10.3% OVER -> HELD  (over for 0.150 s)
    p2  3.493 kN =  9.2% OVER -> BROKE (over for 0.400 s)
p1 peaks HIGHER and survives, so "peak within X% of rating" is wrong at every
X. sail.js never used peak — it burns a 0.4 s overload fuse. OVERLOAD_SECS /
OVERLOAD_RECOVER are exported and priceCandidate replays them per corner per
tier, so the audit and the sim now answer "will it hold" with one arithmetic.
AUDIT.MARGIN stops deciding anything and says why in its own comment.

GATE 1 — THE RIG YOU DIDN'T BUILD, AND THE KNIFE. `_releaseCorner` is now the
one definition of a corner letting go (it was open-coded twice); on top of it:
`failCorner` for a corner that arrived down, `cutAway` for DESIGN.md line 165
emitting A's requested `{t, corners, reason}`, and `session.inherit()` which
adopts somebody else's rig for $0 and keeps it out of the refund — because
week.js pays back half of every intact corner, so counting a stranger's steel
as yours would have the ledger PUNISHING the player for every corner they cut.
Neither a cut nor an inherited corner emits `break`: warranty must not chase a
corner you chose to let go or one you never hung.

LANE C's CLOCK FINDING, fixed. `_substep` samples the wind at `this.t`, which
attach() zeroes — safe only while the caller's clock starts with it, exactly as
attach()'s own comment says. An emergency opens at t=30, so the cloth would fly
the storm's first 60 s under a sky flying its last 60. attach() now takes
{at, wind} (seeded, or genuinely pre-flown so the drape and the pond are real),
seedClock() is the late door, and `clockSkew` makes any future drift readable
instead of silent — measured 90 N vs 655 N for the same rig entering at t=0 vs
t=40, which is the size of what was hiding.

+15 asserts, all node-verified; the two gate-2 pins mutation-checked both ways.
2026-07-25 19:53:06 +10:00
..
data Lane D S17 gate 3.2: THE POOL YARD — authored cold, in the game only by being chosen 2026-07-21 03:53:20 +10:00
js Lane B S18 gates 2+3+1: ⚠️ THE VARIABLE IS POROSITY; the clean boundary is DWELL; the knife 2026-07-25 19:53:06 +10:00
models Lane E S17 gate 3.1: THE CORRODED TIER — mutations restored, tell verified at 20 m, droop pinned to geometry 2026-07-21 01:51:57 +10:00
vendor Vendor three.js r175, add stdlib dev server and launch config 2026-07-16 21:33:42 +10:00
dev_player.html Merge all lanes; add importmap; fix /world/ absolute paths 2026-07-16 22:23:20 +10:00
dev_rigging.html Lane B S18 gates 2+3+1: ⚠️ THE VARIABLE IS POROSITY; the clean boundary is DWELL; the knife 2026-07-25 19:53:06 +10:00
dev_skyfx.html Lane C S13 gate 2.3 + D's sliver: ambient leaves from 30 km/h; hail pool hides at zero 2026-07-18 11:51:26 +10:00
editor.html Sprint 14 integration: merge a/e/c/b (406/0/0), mount B's score + C's wind panels in editor.html 2026-07-18 16:52:36 +10:00
index.html Sprint 14 gate 1 close: round-trip pinned, pool items landed, free-carport fixed 2026-07-18 16:14:34 +10:00
selftest.html Add tools/site_audit; retract the p1 claim against C; show LANE BAL 2026-07-17 14:52:31 +10:00