a0ca7a2cbb
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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.
|
||
|
|
e1e14018bf |
Lane B S13: THE AUDIT REWRITE — the audit predicts the garden, on C's corrected picture
The scoring quantity is the FLOWN garden state now, not static cover%. New gardenfly.js: windForSite (C's shared builder — venturi + shelters, one copy in the repo) → real attach (throws on D's skipped-attach trap) → skyfx exposure → garden.js, per candidate line; cover% demoted to a labelled geometry diagnostic. audit.html flies every affordable line + bare bed and judges the site's pinned separation block on the block's own storm; audit.mjs (node) keeps fast winnability, gains p5 in its verified dump, and points at the browser for garden truth. On C's correction, three structural adoptions: - windForSite everywhere (three harnesses independently mis-built site wind; no fourth copy); - LIVE anchors via the re-pointable wind proxy — the audit's own frozen-sway remap was C's landmine 2 wearing my file's name (audit.html:69); - the MARGIN rule (AUDIT.MARGIN = 0.15, one copy): every row prices twice — $hw holds vs $cleanHw with >=15% headroom — and only clean lines are winners; verdict code 'marginal-only' when the budget can only buy the knife edge (D's 39.8-TATTERED wild night, C's dead 91.9 headline). Also game-true flight: the phantom 12s calm settle is GONE from the sweep (commit->attach->storm is one keypress; the settle skewed every storm sample 12 s off the authored curve — SailRig samples wind at its INTERNAL clock). That skew is not academic: it is a.test's separation-flight harness too, and gardenfly.selftest now pins BOTH chains (game-true 63.8 tattered vs skewed 68.4 'full' on the pinned p5 line — the disagreement is flagged to A in THREADS, not overruled here). The pinned recipe also sweeps regardless of the 18-45 band (it is 45.9 m² — the band predates p5; flagged to A). Selftest 356/0/0 on the scratch merge (b+a+c@45bdc2d). Mutation-checked: MARGIN=0 reddens the margin test (node); dropping siteDef from gardenfly's windForSite call reddens the venturi test (browser, exact test named). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9700b40a30 |
Wire ratingHint into the failure threshold: the ratings are real (A's ruling)
sail.js _checkFailure now fails a corner on load > hw.rating * anchor.ratingHint (read live from the anchor — dress() mutates in place). Consequence asserted, not the formula: on site_02's carport line (uniform rated shackles, funnel on, 12 s calm settle) a cb corner blows before any q corner — at DEFAULT tension (t~29 s into the storm, honest posts hold) and at max. In-suite control pins the attribution: the same rig with every hint forced to 1 holds 4/4, so the break is the hint, not the load. Mutation-checked: unwiring the line fails both. rigging.js weak-link (D's #7): summary.weakest reduces on rating * ratingHint via _effRating, not bare hw.rating — uniform hardware now flags the genuinely worst steel instead of the first click. Mutation-checked. site_audit prices the anchor, not just the steel: tierFor(peak, hint) needs h.rating * hint >= peak, both front-ends carry ratingHint through (browser off world.anchors, node dump extended with the live-dumped hints), rows print the hint. sweep.selftest asserts hints reprice without touching peaks and land over-ceiling corners in unholdable. Mutation-checked. Selftest 319/0/0 (315 + 4). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
4095df8b10 |
Lane B S11: audit the venturi, land setWorld/setBudget, revive the harness
site_audit's headless false-negative is fixed by the browser front-end (A's loadSite/createWorld landed in main — that was all it waited on), and fixing it surfaced a worse bug underneath: the sweep built its wind from the STORM def alone and never called setVenturi, which main.js:424 does at every site load. The venturi is SITE data, so every site_02 audit ever run — including the numbers quoted at C in SPRINT10 — was of a corner block with no gap. The SPRINT6 p1=7.4kN failure inverted: there the tool called a good site unriggable, here it called a mean site cheap. - sweep.js: setVenturi on both winds (the gap doesn't switch off for the settle); both front-ends pass the site's funnel and print it, so a funnelled run is legible as one. - sweep.selftest.js (new, wired into b.test.js): the auditor gets an auditor. Funnel must strictly raise every corner; a funnel-less site must be byte-identical. Verified it fails when the setVenturi calls are deleted. - rigging.js: setWorld(world) + session.setBudget(n)/setAnchors() — A's two asks. Markers are rebuilt (the anchor set changes across sites) and disposed; stale picks die with the old yard. Deletes A's "one private touch" into this module. - dev_rigging.html: dead since SPRINT10 (called createWorld without a site, which now throws) and nothing noticed, because a dev page has no selftest to go red. Fixed, dressed, and given the site switch it should have had (N = next yard). Verdict for C/A, in THREADS: site_02 PASSES with the funnel on — 64 of 66 lines affordable, cheapest $20. The funnel kills nothing, so the gain does NOT need dropping and E's tree stays put. It's a reach problem, not a gain problem: the throat's radius is 5 m and the bed centre is 6.08 m away, so the gap screams over the carport at +50% and reaches the garden at +0.0%. selftest 300/0/0 (296 + 4 new). |