Two chains built independently — GAME (loadSite -> createWorld -> dress ->
windForSite) and EDITOR (siteClone-shaped object -> buildScoringWorld ->
windForSite) — asserted EXACTLY equal at t=30, speed and vector, at every
probe on both shipped yards. Exactly, not nearly: a tolerance is where the
funnel-off bug hid, and it moved the S13 headline 91.5 -> 39.8.
The mutation checks caught my own probe TWICE before this went green, which is
the only reason it is worth anything:
1. I proposed backyard_01 in THREADS. It declares venturi: [] — no funnel to
lose, so a funnel-off regression could never turn it red.
2. So I moved to site_02 — and its BED is 6.08 m from a radius-5 throat.
Starving that yard of its venturi moved the bed probe by 0.000 m/s.
Both versions passed their equality assert and both were worthless.
Measured sensitivity on site_02/earlybuster at t=30 (funnel on/off, trees
present/hidden):
bed ( 0, 1) 12.452 dV +0.000 dT +0.000 <- blind, not a pin site
throat (-6, 0) 15.910 dV +4.948 dT +0.000 <- funnel tripwire
near tr1 ( 7,-1) 8.593 dV +0.000 dT -4.891 <- shelter tripwire
Mutation-checked: starving the editor clone of its venturi turns the @throat
equality red (plus both funnel asserts), while bed/tree stay green exactly as
the table predicts.
Also recorded as a pin, because it is load-bearing for anyone reading the
score card: the corner block's funnel does NOT reach its garden bed. It is
aimed at the rigging zone (the site JSON says so: q1 is 3.5 m inside the
radius), so on that yard the funnel is a hardware-load story, not a
garden-exposure one.
Selftest 374 passed / 0 failed / 0 skipped (362 baseline + 12).
53 lines
3.1 KiB
JavaScript
53 lines
3.1 KiB
JavaScript
/**
|
|
* Lane B selftests — cloth, corner loads, failure cascade, prep economy.
|
|
*
|
|
* The asserts themselves live next to the code they test, in
|
|
* `js/sail.selftest.js` and `js/rigging.selftest.js`, exported as [name, fn]
|
|
* pairs. This file is only the adapter that hands them to Lane A's Suite.
|
|
*
|
|
* The reason for the indirection: those two modules also run under plain
|
|
* `node web/world/js/sail.selftest.js` — no browser, no server, no renderer,
|
|
* ~6 s — which is how the cloth got proven before M0 landed. Keeping the
|
|
* asserts there means the browser suite and the headless suite can never drift,
|
|
* because they are literally the same array.
|
|
*
|
|
* PLAN3D §5-B asked for three asserts. All three are in there, plus a statics
|
|
* balance that pins the load meter to real newtons:
|
|
* 1. hypar sheds load — scored on WORST CASE over eight wind directions
|
|
* rather than one, because Lane C's storms veer and the player never gets
|
|
* to pick the wind. Per-direction would be a false assert: a flat sail
|
|
* sitting edge-on to the wind genuinely has low drag and beats the hypar
|
|
* from that one angle. Worst-case is what the hardware has to survive.
|
|
* 2. cascade — break a corner at fixed t, a neighbour's load spikes >= 2x.
|
|
* 3. determinism — byte-equal load traces, plus ragged frame dt converging on
|
|
* the fixed-dt trace (Lane A's render loop delivers ragged dt, so the
|
|
* accumulator has to absorb it or none of this applies to the real game).
|
|
*/
|
|
|
|
import { SAIL_TESTS } from '../sail.selftest.js';
|
|
import { RIGGING_TESTS } from '../rigging.selftest.js';
|
|
import { SWEEP_TESTS } from '../../../../tools/site_audit/sweep.selftest.js';
|
|
import { buildGardenflyTests } from '../../../../tools/site_audit/gardenfly.selftest.js';
|
|
import { buildScorecardTests } from '../../../../tools/site_audit/scorecard.selftest.js';
|
|
|
|
/** @param {import('../testkit.js').Suite} t */
|
|
export default async function run(t) {
|
|
for (const [name, fn] of SAIL_TESTS) t.test(name, fn);
|
|
for (const [name, fn] of RIGGING_TESTS) t.test(`rigging: ${name}`, fn);
|
|
// site_audit's own sweep. SPRINT11: the tool was flying site_02 with the
|
|
// venturi switched off — the auditor needed an auditor. See sweep.selftest.js.
|
|
for (const [name, fn] of SWEEP_TESTS) t.test(`site_audit: ${name}`, fn);
|
|
// SPRINT13: the audit's garden engine (gardenfly.js) — browser-only, so the
|
|
// flights run here in the async prelude and the tests assert on the results
|
|
// (Suite.test cannot await; a.test's pinned-separation flight is the
|
|
// precedent). run() is async now — runAll awaits it.
|
|
const gardenflyTests = await buildGardenflyTests();
|
|
for (const [name, fn] of gardenflyTests) t.test(`site_audit: ${name}`, fn);
|
|
// SPRINT14 gate 2.3 (co-owned with C): the editor's scored wind and the
|
|
// game's played wind are the same number, exactly, at one probe and one
|
|
// second. Same async-prelude shape — the two chains are built here and the
|
|
// asserts read the captured measurements.
|
|
const scorecardTests = await buildScorecardTests();
|
|
for (const [name, fn] of scorecardTests) t.test(name, fn);
|
|
}
|