From 15c39f76bba2b503422fb780e28b41000e04c5c9 Mon Sep 17 00:00:00 2001 From: Rene De Ren Date: Fri, 8 May 2026 18:33:09 +0200 Subject: [PATCH] Bump MGC@69bdf11 + adjust overcapacity test to actually exercise storm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - nodes/machineGroupControl@69bdf11 makes DOWNSTREAM single-writer (handlePressureChange = live aggregate; optimizer target moved to AT_EQUIPMENT). Closes the ps-mgc-flow-contract failure. - test/inflow-overcapacity-stability now starts the basin at maxLevel so PS percControl is immediately 100 % (the actual storm condition) and uses real-time waits between ticks so movementManager intervals fire — the previous setImmediate yield was too fast for moves to progress, making pumps look perma-parked even when behaviour was OK. Park observations dropped from 83 to 3 across the sim window; final ctrl converges to ~88 % across all 3 pumps. All 82 cross-node + node integration tests now pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- nodes/machineGroupControl | 2 +- ...ow-overcapacity-stability.integration.test.js | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/nodes/machineGroupControl b/nodes/machineGroupControl index dc27a56..69bdf11 160000 --- a/nodes/machineGroupControl +++ b/nodes/machineGroupControl @@ -1 +1 @@ -Subproject commit dc27a569d9be6e1d0e1d2c7538c30a6bb794c945 +Subproject commit 69bdf11fc473e197f9c16db39f2749aa2a5928b4 diff --git a/test/inflow-overcapacity-stability.integration.test.js b/test/inflow-overcapacity-stability.integration.test.js index cd39f8b..1dcaf65 100644 --- a/test/inflow-overcapacity-stability.integration.test.js +++ b/test/inflow-overcapacity-stability.integration.test.js @@ -22,7 +22,11 @@ test('inflow ≫ capacity: pumps reach steady high-ctrl, no parking, no thrashin // wall time while still exercising the transient (1 s startup + 2 s // warmup). The race conditions we care about are the same — they're // about ORDER, not absolute duration. - const plant = buildPlant({ initialBasinLevel: 2.6 }); + // Start at maxLevel so PS percControl is immediately 100 % (the + // storm condition). Otherwise the basin needs to fill to maxLevel + // first, which on a 2× capacity inflow takes ~2 minutes — longer + // than this test's wall time. + const plant = buildPlant({ initialBasinLevel: 3.5 }); const { ps, mgc, pumps, advance, restore } = plant; try { // Pre-start pumps to operational so the test focuses on STEADY-STATE @@ -39,8 +43,14 @@ test('inflow ≫ capacity: pumps reach steady high-ctrl, no parking, no thrashin let abortLogObservations = 0; // Drive the loop: every tick, refresh pressures, set inflow, - // tick PS (which fires _applyMachineGroupLevelControl). + // tick PS (which fires _applyMachineGroupLevelControl). The + // settlePerTickMs wait is REAL wall-clock so movementManager's + // setInterval timers actually fire between handleInputs — without + // it the test runs too fast for moves to progress and pumps look + // permanently parked even when production behaviour is fine. const ticks = SIM_SECONDS; + const settlePerTickMs = 200; + const realSleep = (ms) => new Promise((r) => setTimeout(r, ms)); let lastCtrl = pumps.map(() => 0); let largeJumpTicks = 0; for (let i = 0; i < ticks; i++) { @@ -48,7 +58,7 @@ test('inflow ≫ capacity: pumps reach steady high-ctrl, no parking, no thrashin ps.setManualInflow(Q_IN, Date.now(), 'm3/s'); advance(TICK_MS); ps.tick(); - await new Promise((r) => setImmediate(r)); + await realSleep(settlePerTickMs); const states = pumps.map((p) => p.state.getCurrentState()); const ctrls = pumps.map((p) => Number(p.state.getCurrentPosition?.()) || 0);