diff --git a/tools/site_audit/garden_probe.html b/tools/site_audit/garden_probe.html
index 38c97ac..1f8590c 100644
--- a/tools/site_audit/garden_probe.html
+++ b/tools/site_audit/garden_probe.html
@@ -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 =
diff --git a/web/world/js/tests/balance.test.js b/web/world/js/tests/balance.test.js
index 1ac9c2d..5342a71 100644
--- a/web/world/js/tests/balance.test.js
+++ b/web/world/js/tests/balance.test.js
@@ -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.