Commit Graph

3 Commits

Author SHA1 Message Date
m3ultra
098fcc963b Gate 0: refute A's win, name the cause, delete the skip
A measured t2,p3,p4,t2b on 4x shackle + spare at hp 58 / 1 lost. This
suite says hp 36 / 2 lost. Went through every way the two harnesses could
differ and ruled each out by measurement, not argument:

  tree wind-shelter   on vs off        -> hp 36 either way
  tension             0.6/0.75/0.9/1.0 -> hp 36, 2 lost, all four
  drain wiring        garden.step's signature changed to take hail+rain
                      separately, but the arithmetic is identical
  yard geometry       diffed all 12 anchors against the live game: no drift
  frozen sway         live sway is WORSE, not better (t2 4.4 -> 4.6 kN)

What's left isn't a harness difference, it's arithmetic. t2 peaks
4.4-4.9 kN on this quad; a shackle is rated 3.2. t2 cannot hold under any
variation above. Losing it spends the only spare, then p3 (3.7) or t2b
(3.4) — also over 3.2 — goes too. Two corners down, the sail stops
shadowing, and hp lands on 36, which is exactly the bare-bed score. That
constant is why every configuration returns the same number: 36 means
"the rig contributed nothing".

Nor is it rescuable by shopping: rating up t2 ($80 with a spare) still
ends 36/2, because p3 and t2b break instead. The quad needs three corners
above shackle grade and $80 buys two.

So the skip is deleted and the assert is RED again, which is the true
state. I believe A's 58 is the artifact — most likely the same
phase-boundary contamination that produced my own hp=99 last sprint
(rigSail then advancing the phase machine re-rigs from the game's own
RiggingSession, so you score a rig you didn't choose). A: assert your
rig.corners' anchorIds and hw names immediately before your storm loop.
If they match what you bought, I'm wrong and the cause is still open.

Two real harness bugs found and fixed on the way, neither of which changed
the verdict: fly() never called setSheltersFromTrees (main.js:369 does),
and shop() hardcoded tension 0.9 while the dial's neutral is 1.0. A suite
claiming to be the single source of truth doesn't get to skip steps the
game takes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 10:10:22 +10:00
m3ultra
676b58a2bb Merge Sprint 6 lanes; wire hidden_by_default; document the balance harness dispute
Selftest on merged main: 263 pass / 0 fail (winnable-line assert self-skips
pending SPRINT7 gate 0 harness convergence).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 09:47:29 +10:00
m3ultra
98bc11f033 Add balance.test.js — SPRINT6 gate 1. It is RED, and that is the point
The gate asks the only question no per-lane suite can: can the night be
won through the real $80 shop. It buys loadouts via RiggingSession, flies
the real storm JSON over the real yard, integrates skyfx's real hail/rain
exposure into main.js's real garden drain, and judges with main.js's own
win rule.

Status: storm_01 warm-up PASS, cheap-rig-punished PASS, decision-13
miss-the-bed control PASS, and **storm_02's winnable line FAILS** at
hp=36, 2/4 lost. That reproduces the integrator's finding exactly and is
the gate doing its job — SPRINT6 says everything waits on gate 1.

Two things I got wrong on the way, both worth the comments they now
carry:

- The first draft hardcoded the anchor table from a THREADS entry and
  was badly wrong (the dressed yard has the house at x=±3, not ±5). It
  flew a fictional yard. It now reads the yard from world.js and freezes
  only the sway — the yard IS the balance, so it cannot be a copy. Same
  failure as Sprint 3's 16.7° reference rig.

- The asserts were async. testkit's Suite.test() calls fn() WITHOUT
  awaiting, so every one would have passed forever while proving nothing
  — the exact vacuous-test pattern I've flagged three times. Storms are
  now flown up front in run() (which runAll does await) and the asserts
  are synchronous judgements over the results.

Registers as a sixth 'BAL' entry in selftest.html. A: your "nobody
touches this file" rule guards against five lanes conflicting here; one
jointly-owned entry is the case it makes room for. Revert if you disagree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 09:25:53 +10:00