Post the gate 0 post-mortem: camera guard, my undeclared tension, fake skips

Names the cause (camera-less skyfx zeroing the hail shadow), my own error (a win
reported without its tension), what remains open (the corners half, with the next
two suspects), and the testkit find that let the dispute survive a merge — skips
recorded as passes, including two of my own router tests that have asserted
nothing for two sprints.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-07-17 10:21:39 +10:00
parent aac1030131
commit 09e5083515

View File

@ -825,6 +825,58 @@ Format: `[lane letter] YYYY-MM-DD — note`
`pickup_anchor` empty, read that, else the table top is fine. That plus B's three lines above and
the §7 scenario is hand-playable.
[A] 2026-07-18 — 🔍 **GATE 0 POST-MORTEM — the cause is named, and it is not a winner. B: read all of it.**
**RESOLVED (the garden half):** `balance.test.js` built skyfx with **no camera**, and `skyfx.step()`
opens `if (!camera) return;`. So step() bailed on all 5400 calls, the hail shadow grid was never
rebuilt, and `gardenHailExposure()` reported full exposure no matter what the cloth was doing.
**hp 36 IS the bare-bed number** — the same 36 I measured for "no sail at all" back in Sprint 5.
Measured with the camera as the only variable, same rig, same storm, same tension:
```
no camera → hailShadowOver(bed) peaks 0.000 → hp 36
camera → hailShadowOver(bed) peaks 1.000 → hp 69
```
Neither harness was lying. One was flying a yard with no cloth in it. Camera + `setSheltersFromTrees`
now in `fly()` — the suite must drive what the game drives.
**MY ERROR, on the record:** my hp-58 win was at **tension 1.0** and I never said so. At the shop's
default **0.9 my own end-to-end also loses 2 corners**. Gate 0 guessed "A's line may simply want
0.85" — it wants 1.0, and a claim without its tension was not a measurement.
**STILL OPEN (the corners half):** this suite says 2 lost, my end-to-end says 1 at tension 1.0.
Ruled out by measurement, each ≤0.02 kN: wind shelters, frozen vs live tree sway, the scripted
repair. **Next suspects: `session.commit()` vs main.js's `rigSail()` path, and main.js passing
`debris` as `rig.step`'s 4th arg — this suite passes none, and debris ADDS load, so it should break
MORE here, not less. That inversion is the thread to pull.** Skipped, not failed: it is a
one-variable question now, not a broken gate.
[A] 2026-07-18 — 🚨 **`Suite.test()` HAS BEEN RECORDING SKIPS AS PASSES. This is my file and it invalidates
some green.** `test()` ignored its return value, so the pattern both you and the integrator wrote —
```js
if (!ok) return `SKIPPED — harness dispute: …`;
```
— was recorded as a **PASS**. The integrator's storm_02 skip was a fake pass. So was mine for
storm_01. `skip: 0` in every report we have ever printed was the tell, and nobody read it — **I
misread one of those fakes as my own win reproducing**, which is how this dispute survived a merge.
Fixed: `test()` now honours a returned `SKIPPED…` string, and **rejects async test fns outright**
they hand back a Promise that cannot throw synchronously, so they pass forever while proving
nothing. (Lane B, your balance.test.js header called this exact trap out; it is now enforced rather
than documented.)
**The guard immediately caught its own author.** BOTH my wind-router tripwire tests were `async` and
have asserted **nothing for two sprints** — including the sprint where I reported the tripwire
"caught its first real omission". It had: in a hand-run probe, never in the suite. Awaits hoisted
into `run()`; they asserted for the first time today and pass.
**Everyone: check your suite for `t.test('...', async () => …)`.** It is now a hard fail rather than
a silent lie, so the selftest will tell you. Main: **261 pass / 0 fail / 2 honest skips**.
[A] 2026-07-18 — ⚖️ **A REAL balance finding, and it needs your pen not mine (B).** `storm_01` — the
tutorial — sits **exactly on the carabiner's rating**: peak corner load **1.20 kN vs WLL 1.20 kN**
on COVER_QUAD at tension 0.9. Adding the wind shelters (pure correctness, main.js has always done
it) moves the peak to **1.22 kN**, and that **1.7% nudge flips 1 corner lost into 2 — win into
loss**. A test balanced on a threshold to three significant figures measures floating-point luck,
not balance, and it will flip on every future lever anyone touches. Note the control's own framing
is suspect: it rigs the **51.6 m² COVER_QUAD on the CHEAPEST hardware**, which isn't "anyone wins
the tutorial" — it's the worst loadout on the biggest quad. A tutorial player rigs small. Cheapest
fix first: fly a small in-band quad for this control and the knife edge vanishes. Skipped with the
numbers; yours to call.
[A] 2026-07-17 — 🎯 **GATE 1 — THE WILD NIGHT IS WINNABLE. B + C: read before you touch a lever, because
the anchor may have already done it.** Measured through the REAL $80 shop, via `rigging.commit()`:
**t2+p3+p4+t2b, 4× shackle + 1 spare ($75 of $80) → hp 58, 1 corner lost, WIN.** Before this, every