mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
The three mutation gates matched source text that has since moved or been reflowed, so 37 of their 108 reverts reported STALE and could no longer prove anything: - qa-floorhold-mutations (2): the neighbour-floor code moved from src/data/groundFloor.js into src/services/groundFloor.js (ac977bd). - qa-flyroute-mutations (8): src/cameraVerbs.js was reflowed by the formatter (2aca7ae); the anchors now match the formatted lines. - qa-firstrun-mutations (27): the launcher markup, styles and startup moved to src/ui/templates/welcome.html, src/ui/styles/first-run.css and src/app/startupChrome.js; the rail default to panelPositionControls.js and the radio ESC handling to radioBindings.js (a67bc60and follow-ups). The tool-schema pin now edits a tool description, since the context-mode enum it used to edit no longer lives in tools.js. Every revert still reintroduces the same defect. Results: floor-hold 22/22, fly_route 19/19, first-run 67/67 caught, with all source files restored. Co-Authored-By: Claude Opus 5.5 <[email protected]>
164 lines
6.7 KiB
JavaScript
164 lines
6.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Are the fly_route pins actually load-bearing?
|
|
*
|
|
* A pin that is red only when you delete the whole feature proves very little.
|
|
* This reverts each fix INDIVIDUALLY — the smallest edit that reintroduces the
|
|
* original defect — and requires src/routeCinematics.test.mjs to go red for it.
|
|
* Every entry names the defect it restores, so the count is reproducible rather
|
|
* than asserted in a commit message.
|
|
*
|
|
* node scripts/qa-flyroute-mutations.mjs
|
|
*
|
|
* Restores the file on exit, including on failure.
|
|
*/
|
|
import { execFileSync } from 'node:child_process';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const SOURCE = path.join(ROOT, 'src', 'cameraVerbs.js');
|
|
const TESTS = 'src/routeCinematics.test.mjs';
|
|
|
|
/** @type {Array<{defect: string, from: string, to: string}>} */
|
|
const MUTATIONS = [
|
|
{
|
|
defect: 'interrupt leaves the horizon tilted (round-1 behaviour)',
|
|
from: 'const leveled = wasRoute && !tracking ? levelCameraRoll() : false;',
|
|
to: 'const leveled = false;',
|
|
},
|
|
{
|
|
defect: 'completion freezes a bank into the final frame',
|
|
from: 'const appliedBankDeg = state.bankDeg * profile.speed;',
|
|
to: 'const appliedBankDeg = state.bankDeg;',
|
|
},
|
|
{
|
|
defect: 'heading lerps in Cartesian space and cannot cross a U-turn',
|
|
from: ' const turned = Cesium.Matrix3.multiplyByVector(\n rotation,\n state.headingDir,\n _frameDir,\n );',
|
|
to: ' const turned = Cesium.Cartesian3.lerp(state.headingDir, gaze, k, _frameDir);',
|
|
},
|
|
{
|
|
defect: 'the exact-180° bank direction becomes a floating-point coin toss',
|
|
from: ' if (cosTurn <= -1 + ANTIPODAL_EPS && Math.abs(sinLeft) < ANTIPODAL_EPS)\n return Math.PI;',
|
|
to: ' // branch removed',
|
|
},
|
|
{
|
|
defect: 'a cold cell is read as sea level (the 1.3 km underground bug)',
|
|
from: ' state.floorM = Number.isFinite(state.floorM)\n ? state.floorM\n : state.coldSeedFloorM;',
|
|
to: ' state.floorM = carto.height;',
|
|
},
|
|
{
|
|
defect: 'the flight never warms its own corridor',
|
|
from: ' warmRouteCorridor(state, 0, ROUTE_WARM_START_M);',
|
|
to: ' // warm removed',
|
|
},
|
|
{
|
|
defect: 'the dolly races the fire-and-forget warm instead of arming for it',
|
|
from: ' if (\n canAnswer &&\n !state.floorKnown &&\n !state.departed &&\n state.armS < ROUTE_ARM_S\n ) {',
|
|
to: ' if (false) {',
|
|
},
|
|
{
|
|
defect: 'no mesh probe, so a permanently cold DEM is flown blind',
|
|
from: ' if (\n cold.length &&\n !state.meshProbeSpent &&\n typeof state.probeFn === \'function\'\n ) {',
|
|
to: ' if (false) {',
|
|
},
|
|
{
|
|
defect: 'the launch-altitude hold is dropped and the eye descends blind',
|
|
from: ' if (!state.floorKnown && Number.isFinite(state.safeHoldHeightM)) {',
|
|
to: ' if (false) {',
|
|
},
|
|
{
|
|
defect: 'releasing the hold onto late data drops the eye without a limit',
|
|
from: ' if (Number.isFinite(state.appliedHeightM)) {',
|
|
to: ' if (false) {',
|
|
},
|
|
{
|
|
defect: 'a late mid-flight floor is taken whole and snaps the eye',
|
|
from: ' state.floorM = routeFloorHoldM(state.floorM, sampledFloor, step);\n state.floorKnown = true;',
|
|
to: ' state.floorM = sampledFloor;\n state.floorKnown = true;',
|
|
},
|
|
{
|
|
defect: 'the lookahead floor read is dropped (clearance only underfoot)',
|
|
from: ' const warm = [here, ahead].filter((value) => Number.isFinite(value));',
|
|
to: ' const warm = [here].filter((value) => Number.isFinite(value));',
|
|
},
|
|
{
|
|
defect: 'the shaping floor adopts rises instantly and pops at cell edges',
|
|
from: ' if (!Number.isFinite(previousM)) return sampledM;',
|
|
to: ' if (!Number.isFinite(previousM) || sampledM >= previousM) return sampledM;',
|
|
},
|
|
{
|
|
defect: 'the mesh probe fires every arming frame instead of once per route',
|
|
from: ' cold.length &&\n !state.meshProbeSpent &&\n typeof state.probeFn === \'function\'\n ) {\n state.meshProbeSpent = true;',
|
|
to: ' cold.length &&\n typeof state.probeFn === \'function\'\n ) {\n state.meshProbeSpent = true;',
|
|
},
|
|
{
|
|
defect: 'one warm cell resolves a corridor whose other cells are unknown',
|
|
from: ' if (cold.length && !state.meshProbeCoveredCold) return false;',
|
|
to: ' // partial-corridor guard removed',
|
|
},
|
|
{
|
|
defect: 'the probe re-reads cells the cache already answered',
|
|
from: ' const probe = state.probeFn(cold) || {};',
|
|
to: ' const probe = state.probeFn(cells) || {};',
|
|
},
|
|
{
|
|
defect: 'the hard clearance clamp reads the SMOOTHED floor, not the raw sample',
|
|
from: ' (Number.isFinite(sampledFloor) ? sampledFloor : state.floorM) +\n ROUTE_MIN_CLEARANCE_M,',
|
|
to: ' state.floorM + ROUTE_MIN_CLEARANCE_M,',
|
|
},
|
|
{
|
|
defect: 'levelling also RE-FRAMES the camera (destination passed with the HPR)',
|
|
from: ' cam.setView({\n orientation: { heading: cam.heading, pitch: cam.pitch, roll: 0 },\n });',
|
|
to: ' cam.setView({\n destination: Cesium.Cartesian3.fromDegrees(0, 0, 5000),\n orientation: { heading: cam.heading, pitch: cam.pitch, roll: 0 },\n });',
|
|
},
|
|
{
|
|
defect: 'the OS reduced-motion preference is never consulted',
|
|
from: ' reducedMotion: prefersReducedMotion(),',
|
|
to: ' reducedMotion: false,',
|
|
},
|
|
];
|
|
|
|
const original = fs.readFileSync(SOURCE, 'utf8');
|
|
let caught = 0;
|
|
const missed = [];
|
|
|
|
process.on('exit', () => fs.writeFileSync(SOURCE, original));
|
|
|
|
console.log(`\nfly_route pin strength — ${MUTATIONS.length} individual reverts\n`);
|
|
for (const { defect, from, to } of MUTATIONS) {
|
|
if (!original.includes(from)) {
|
|
missed.push(`${defect} (ANCHOR MISSING — the mutation no longer applies)`);
|
|
console.log(` \x1b[31mSTALE\x1b[0m ${defect}`);
|
|
continue;
|
|
}
|
|
fs.writeFileSync(SOURCE, original.replace(from, to));
|
|
let red = false;
|
|
let by = '';
|
|
try {
|
|
execFileSync('node', ['--test', TESTS], { cwd: ROOT, encoding: 'utf8', stdio: 'pipe' });
|
|
} catch (error) {
|
|
red = true;
|
|
const failed = String(error.stdout || '').split('\n')
|
|
.filter((line) => line.trim().startsWith('✖') && line.includes('('))
|
|
.map((line) => line.trim().slice(2).split(' (')[0]);
|
|
by = [...new Set(failed)].slice(0, 2).join('; ');
|
|
}
|
|
if (red) {
|
|
caught += 1;
|
|
console.log(` \x1b[32mRED \x1b[0m ${defect}\n caught by: ${by}`);
|
|
} else {
|
|
missed.push(defect);
|
|
console.log(` \x1b[31mGREEN\x1b[0m ${defect} <-- no pin covers this`);
|
|
}
|
|
}
|
|
fs.writeFileSync(SOURCE, original);
|
|
|
|
console.log(`\n ${caught}/${MUTATIONS.length} defects caught by the pins`);
|
|
if (missed.length) {
|
|
console.log('\n uncovered:');
|
|
for (const item of missed) console.log(` - ${item}`);
|
|
}
|
|
process.exitCode = missed.length ? 1 : 0;
|