Lane B S13: kill the marked fake — garden model comes from A's garden.js everywhere

garden_probe.html drops its TEMPORARY COPY of HAIL_WEIGHT/RAIN_WEIGHT/
GARDEN_DRAIN and flies main.js's own createGarden (imported from garden.js),
so the probe's hp/state/damage-split are the model's, not a re-derivation.
balance.test.js's local GARDEN_DRAIN/W_HAIL/W_RAIN copy re-points at the
garden.js exports (A's flag on balance.test.js:38) — a future retune now
moves this suite the day it lands instead of drifting silently.

Selftest 351/0/0 on the scratch merge (b+a+c) — the constants are identical,
so no number moved; the SOURCE moved.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-18 13:02:56 +10:00
parent 666b378740
commit 25eefccc69
2 changed files with 15 additions and 24 deletions

View File

@ -8,10 +8,10 @@
gardenHailExposure, stepped exactly the way main.js:931-941 steps it) for a
set of rig lines, and prints predicted garden HP beside the audit's cover%.
It is a PROBE, not the fix: the garden drain weights are private to main.js, so
the constants below are a temporary copy, marked and asked-about in THREADS.
The moment A exports the garden model this page imports it and the copy dies.
Nothing ships against a duplicated constant — that is how this repo gets bitten.
SPRINT13: the garden model is A's js/garden.js now (the export this page's
first version asked for), so the probe flies the SAME createGarden main.js
flies — the temporary constant copy died the day the export landed, per the
fake → ask → landed → delete-the-fake protocol.
Browser-only by necessity: skyfx needs `document` (verified — node throws
"document is not defined"), so garden prediction can never live in audit.mjs.
@ -48,13 +48,9 @@ import { createWind } from '../../web/world/js/weather.js';
import { createSkyFx } from '../../web/world/js/skyfx.js';
import { SailRig } from '../../web/world/js/sail.js';
import { HARDWARE, FIXED_DT } from '../../web/world/js/contracts.js';
import { createGarden } from '../../web/world/js/garden.js';
import { AUDIT, auditSweep } from './sweep.js';
// ⚠️ TEMPORARY COPY — main.js's garden model is module-private (HAIL_WEIGHT,
// RAIN_WEIGHT, GARDEN_DRAIN, createGarden). Asked A to export it in THREADS;
// this dies the moment it lands. Do not let this page outlive the ask.
const HAIL_WEIGHT = 5.0, RAIN_WEIGHT = 0.25, GARDEN_DRAIN = 0.9;
const q = new URLSearchParams(location.search);
const siteName = q.get('site') || 'site_02_corner_block';
const stormName = q.get('storm') || 'storm_03b_earlybuster';
@ -102,26 +98,19 @@ async function run() {
.attach(ids, Array(4).fill(hwTier), 1.0);
}
const sky = createSkyFx({ wind, night: true });
let hp = 100, byHail = 0, byRain = 0;
// THE model, not a copy: main.js's own createGarden, imported from garden.js.
const garden = createGarden({ setPlants() {} });
const n = Math.round(stormDef.duration / FIXED_DT);
for (let i = 0; i < n; i++) {
const t = i * FIXED_DT;
if (rig) rig.step(FIXED_DT, wind, t);
sky.step(FIXED_DT, t, { sail: rig });
const rainExp = sky.gardenExposure(bed, t);
const hailExp = sky.gardenHailExposure(bed, t);
const dHail = HAIL_WEIGHT * hailExp * GARDEN_DRAIN * FIXED_DT;
const dRain = RAIN_WEIGHT * rainExp * GARDEN_DRAIN * FIXED_DT;
const total = Math.min(hp, dHail + dRain);
if (total > 0) {
const fh = dHail / (dHail + dRain);
byHail += total * fh; byRain += total * (1 - fh);
hp -= total;
}
garden.step(FIXED_DT, sky.gardenHailExposure(bed, t), sky.gardenExposure(bed, t));
}
const cornersLost = rig ? rig.corners.filter((c) => c.failed).length : 4;
return { hp: +hp.toFixed(1), byHail: +byHail.toFixed(1), byRain: +byRain.toFixed(1), cornersLost };
return { hp: +garden.hp.toFixed(1), state: garden.state,
byHail: +garden.damage.hail.toFixed(1), byRain: +garden.damage.rain.toFixed(1), cornersLost };
}
el('sub').textContent =

View File

@ -28,6 +28,11 @@ import { SailRig } from '../sail.js';
import { createSkyFx } from '../skyfx.js';
import { createWind, loadStorm } from '../weather.js';
import { HARDWARE, FIXED_DT, START_BUDGET } from '../contracts.js';
// SPRINT13: the garden weights come from garden.js — the SAME module main.js
// flies — not from a local copy. The old `const GARDEN_DRAIN = 0.9 // main.js`
// here was the drift A's export exists to kill: a retune would have landed in
// the game and left this suite green against last sprint's numbers.
import { GARDEN_DRAIN, HAIL_WEIGHT as W_HAIL, RAIN_WEIGHT as W_RAIN } from '../garden.js';
const [CARABINER, SHACKLE, RATED] = HARDWARE;
@ -35,9 +40,6 @@ const [CARABINER, SHACKLE, RATED] = HARDWARE;
const WIN = (hp, lost) => hp >= 50 && lost < 2;
/** main.js's CALM_STORM — what wind.use() hands the rig outside a storm, and so what settles it. */
const CALM_STORM = 'storm_01_gentle';
const GARDEN_DRAIN = 0.9; // main.js
const W_HAIL = 5.0; // main.js, decision 13 — integration weights
const W_RAIN = 0.25;
/**
* The yard is READ FROM world.js, never copied.