Go to file
m3ultra e4436248b0 Add tools/site_audit; retract the p1 claim against C; show LANE BAL
site_audit answers "is this site winnable?" before it ships — the check that
was missing when SPRINT6 shipped a yard whose bed-covering quad pulled 7.4 kN
against a shop that holds 6.5. It enumerates in-band quads, flies the real
storm headless, maps each corner to the cheapest tier that holds it, and
verdicts against the $80 budget. On backyard_01 it independently reproduces
THE LINE: p1,p2,p3,p4 at $65 + $15 spare, matching balance.test to within 2%.

It also caught three of my own bugs, which is the point of building it:

  · it settled on STORM wind frozen at t=0 — the exact anti-pattern
    balance.test documents at 1.94 kN vs 0.40 kN. Now settles on the calm
    day on a running clock, the way main.js does.
  · peakLoad is peak-since-ATTACH, so the settle transient was being
    reported as a storm peak. sail.js gains resetPeaks().
  · its p4 was typed from world.js's postSpecs, missing that posts are RAKED
    8° away from centre — 0.56 m off. The audit now re-derives all four posts
    from live world.js on every run and hard-fails on drift.

That last check is deliberately narrow. Node CANNOT dress: dress() needs
GLTFLoader (bare 'three') and fetch()es .glb over file://. createWorld() still
SUCCEEDS in node — it just returns the GRAYBOX yard, house at x=±5, no branch
anchors. So a headless tool that "reads world.js for the real yard" gets the
fictional x=±5 house that cost two sprints. Reading live code is not reading
truth. Verified in-browser: the dump matches the dressed yard on all 12
anchors. Posts are the only thing dress() never touches, so they're the only
thing worth cross-checking — and that check is what caught p4.

C IS RIGHT ABOUT p1 AND I WAS WRONG, for the third time. My comment claimed
C's 1.08 kN didn't reproduce, that p1 peaked at 1.27 and the line won on TIME
rather than headroom. Re-measured on the dressed yard, same flight:

    shade cloth  p1 0.98 kN  0/4 lost      membrane  p1 1.23 kN  p1 LETS GO

p1 never touches its 1.2 kN rating on cloth — 18% of real headroom. Where 1.27
came from: a loadout where a corner BROKE and dumped its share onto p1 (the
same quad with hardware the budget can't buy reads 2.48). Any p1 number
gathered without checking `lost` measures a cascade, not a fabric.

So the fabric is the decision, not a skin: 0.98 vs 1.23 against a 1.20 rating
is the difference between the $5 carabiner holding the wild night and failing
it. New assert `fabric decides p1` locks that in, so nobody has to trust the
paragraph.

selftest.html rendered ['A'..'E'] while importing BAL too, so the balance
suite ran, counted toward the summary, and had every row silently dropped —
including, had one gone red, the row saying which assert failed. The merge
gate was invisible in its own report. My bug: I added the import, not the
renderer. Now derived from the report.

Selftest: 276 passed, 0 failed, 0 skipped (LANE BAL now visible).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:52:31 +10:00
.claude Merge Sprint 8; the week is live; balance harness stabilized 2026-07-17 14:02:53 +10:00
docs Add hail juice, plant shred, and a way to screenshot the game 2026-07-17 03:03:54 +10:00
prototype Add side-systems to design doc + playable sail-storm prototype 2026-07-16 20:55:31 +10:00
tools Add tools/site_audit; retract the p1 claim against C; show LANE BAL 2026-07-17 14:52:31 +10:00
web/world Add tools/site_audit; retract the p1 claim against C; show LANE BAL 2026-07-17 14:52:31 +10:00
.gitignore Add deterministic Blender yard-asset factory 2026-07-16 21:39:52 +10:00
DESIGN.md Add side-systems to design doc + playable sail-storm prototype 2026-07-16 20:55:31 +10:00
LANE_PROMPTS.md Add Sprint 9 plan and lane prompts: pyrrhic call, $80 win, second site 2026-07-17 14:03:45 +10:00
PLAN3D.md Correct PLAN3D asset inventory; log M0 contract additions 2026-07-16 21:33:42 +10:00
server.py Vendor three.js r175, add stdlib dev server and launch config 2026-07-16 21:33:42 +10:00
SPRINT2.md Add Sprint 2 assembly instructions: wire proven modules into one playable storm 2026-07-16 22:24:35 +10:00
SPRINT3.md Add Sprint 3 plan and lane prompts: close the game loop 2026-07-17 01:11:16 +10:00
SPRINT4.md Add Sprint 4 plan and lane prompts: face and water 2026-07-17 02:03:47 +10:00
SPRINT5.md Add Sprint 5 plan and lane prompts: hail and the broom 2026-07-17 02:44:30 +10:00
SPRINT6.md Add Sprint 6 plan and lane prompts: winnable, then a week of nights 2026-07-17 08:54:02 +10:00
SPRINT7.md Add Sprint 7 plan and lane prompts: one truth, then the week 2026-07-17 09:48:23 +10:00
SPRINT8.md Add Sprint 8 plan and lane prompts: ship the week 2026-07-17 11:57:51 +10:00
SPRINT9.md Add Sprint 9 plan and lane prompts: pyrrhic call, $80 win, second site 2026-07-17 14:03:45 +10:00
THREADS.md Merge Sprint 8; the week is live; balance harness stabilized 2026-07-17 14:02:53 +10:00