From 6bf94f4c8a1ff182b00e07afa334a77b4dbefacf Mon Sep 17 00:00:00 2001 From: znetsixe Date: Mon, 11 May 2026 17:29:23 +0200 Subject: [PATCH] Wave B1: bump submodule pointers + 5 OPEN_QUESTIONS resolved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generalFunctions f117546 → B2.3 fireAndWait + P11.1 possibilities + P11.2 commandRegistry.units + monster schema measurement e6e212a → B1.3 isStable threshold monster 2aa7f88 → B1.4 cooldown-guard root-cause fix machineGroupControl 0e8cab5 → B2.3 fireAndWait migration OPEN_QUESTIONS marked RESOLVED in the decisions table: isStable tautology, monster cooldown-guard, LatestWinsGate fireAndWait Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/refactor/OPEN_QUESTIONS.md | 62 ++++++++++++++++++++++++------ nodes/generalFunctions | 2 +- nodes/machineGroupControl | 2 +- nodes/measurement | 2 +- nodes/monster | 2 +- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/.claude/refactor/OPEN_QUESTIONS.md b/.claude/refactor/OPEN_QUESTIONS.md index a47ff46..9e4d2a7 100644 --- a/.claude/refactor/OPEN_QUESTIONS.md +++ b/.claude/refactor/OPEN_QUESTIONS.md @@ -13,7 +13,7 @@ decision during refactor work writes it here rather than guessing. | Ramp foot for run-zone curve (control/levelBased) | `inflowLevel` (current). startLevel is the 0% minimum, not the curve foot. | | `overfillLevel` vs `highVolumeSafetyLevel` | **`highVolumeSafetyLevel` canonical**; drop the legacy alias. | | measurement `isStable` tautology | Fix now with a config-driven absolute threshold (`stabilityThreshold` in scaling-units). Add to schema + editor UI. | -| monster cooldown-guard pre-existing fail | Debug + fix the sampling-pulse logic. | +| monster cooldown-guard pre-existing fail | **RESOLVED 2026-05-11** — root cause was missing `nominalFlowMin`/`flowMax`/`maxRainRef`/`minSampleIntervalSec` in `monster.json`, stripped by `configUtils.initConfig` before reaching the domain. Added the four keys to the schema. | | pumpingStation plain child dicts | Migrate to `declareChildGetter`; rewrite affected tests. | | VGC custom `registerChild` overload | Adopt ChildRouter; rewrite disambiguation tests. | | MGC inline dispatch gate vs LatestWinsGate | Extend LatestWinsGate with `fireAndWait(value)` returning the per-fire settlement promise. Migrate MGC. | @@ -240,7 +240,26 @@ Tracked; not blocking the refactor. --- -## 2026-05-10 — measurement `isStable` tautology (pre-existing bug) +## 2026-05-10 — measurement `isStable` tautology (pre-existing bug) — RESOLVED + +**Resolution (2026-05-11):** Replaced the tautological `stdDev < stdDev*2` +check with a config-driven absolute threshold. New schema field +`calibration.stabilityThreshold` (number, ≥ 0, default `0.01` in +scaling-units) added to `generalFunctions/src/configs/measurement.json` so +all callers see it. `Calibrator.isStable()` now returns `true` when +`stdDev === 0` or `stdDev <= threshold`, falling back to the default when +the config slot is missing or non-numeric. The two BUG-PRESERVED calibrator +tests were rewritten — high-variance buffers now correctly report unstable +under the default and only flip to stable when an explicit relaxed +threshold is supplied. Added edge tests for the relaxed-threshold path, +constant-buffer-with-zero-threshold path, just-above-threshold path, and +missing-config fallback. `nodeClass.buildDomainConfig` and +`measurement.html` (defaults + form field + oneditsave) propagate the UI +value through to the domain. 100/100 measurement tests pass; 70/70 +generalFunctions basic tests pass. + +### Original entry below +## 2026-05-10 — measurement `isStable` tautology (pre-existing bug) (history) **Context:** P3.4. The existing `isStable` in `measurement/src/specificClass.js` does: @@ -470,27 +489,48 @@ asserting against the resulting `node._sent` / `node._statuses`. --- -## 2026-05-10 — monster schema strips command-line constraint keys +## 2026-05-10 — monster schema strips command-line constraint keys — RESOLVED 2026-05-11 **Context:** P6.3. The monster JSON schema in `generalFunctions/src/configs/monster.json` defines `samplingtime`, `minVolume`, `maxWeight` and others under `constraints`, but NOT `nominalFlowMin`, `flowMax`, `maxRainRef`, `minSampleIntervalSec`. `configUtils.initConfig` strips these unknown keys with a `Unknown key … Removing it.` warning. The legacy code read them anyway — `Number.isFinite(undefined)` returns false, so guards naturally route into invalid-bounds territory and tests pass via the undefined cascade. -**Default chosen:** Preserved — refactor reads the same stripped fields the same way. The schema warning is harmless but noisy in test output. - -**Decision needed by:** Phase 7 (topic-name standardisation) — add the four missing constraint keys to the schema, OR move them into a `samplingControl` section. Either fix removes the warning and lets the values actually pass through. +**Resolution (2026-05-11, B1.4):** Added the four missing fields (`nominalFlowMin`, `flowMax`, `maxRainRef`, `minSampleIntervalSec`) to the `constraints` section of `generalFunctions/src/configs/monster.json` with sensible defaults (0/0/10/60). The unknown-key warning disappears and user-supplied values now propagate through validation to the domain, restoring the documented sampling behaviour. --- -## 2026-05-10 — monster sampling-guards cooldown test fails on development (pre-existing) +## 2026-05-10 — monster sampling-guards cooldown test fails on development (pre-existing) — RESOLVED 2026-05-11 **Context:** P6.3 baseline run. `test/edge/sampling-guards.edge.test.js` "cooldown guard blocks pulses when flow implies oversampling" already fails on `development` BEFORE the refactor (`assert.ok(monster.sumPuls > 0)` — sumPuls stays at 0 across 80 ticks). The legacy in-file equivalent in `test/monster.test.js` (Mocha-style wrapper, not picked up by `node:test`) appears to have passed in an earlier era. -**Default chosen:** Refactor preserves behaviour byte-for-byte — same failure remains, same line. Not a refactor regression. - -**Decision needed by:** Phase 10 (test-suite refactor) — fix the test OR debug the underlying behaviour (likely the interaction between `_beginRun` resetting state inside the same `sampling_program` call that the integrator then runs, leaving the first second's m3PerTick stranded). +**Resolution (2026-05-11, B1.4):** Root cause was the schema-stripping issue documented immediately above — `nominalFlowMin`/`flowMax`/`minSampleIntervalSec` were stripped by `configUtils.initConfig` before reaching the domain, so `validateFlowBounds` saw NaN/NaN and routed every `i_start` into the invalid-bounds early return, which prevented `_beginRun` from ever firing. With the four constraint keys now declared in `monster.json`, the test config propagates intact: `_beginRun` runs, the m3PerTick integrator accumulates ~0.056 m3/tick, `temp_pulse` crosses 1 at tick ~18, the first pulse fires, subsequent pulses are correctly blocked by the 60 s cooldown, and `sumPuls > 0` / `missedSamples > 0` / `bucketVol > 0` / `getSampleCooldownMs() > 0` all hold. Added a guard-site comment in `parameters/parameters.js#validateFlowBounds` pointing back at the schema contract. All 10/10 monster tests green. --- -## 2026-05-10 — MGC handleInput retained inline latest-wins (not DemandDispatcher) +## 2026-05-10 — MGC handleInput retained inline latest-wins (not DemandDispatcher) — RESOLVED + +**Resolution (2026-05-11):** Extended `LatestWinsGate` with +`fireAndWait(value)` that returns a per-fire settlement promise. A +parked call superseded by a later fire resolves with the frozen +sentinel `LatestWinsGate.SUPERSEDED = { superseded: true }` (not a +reject) so callers branch on a value without try/catch. Dispatch +errors still resolve the promise (with `undefined`) and surface via +`gate.lastError`. + +MGC's `handleInput` now delegates to `DemandDispatcher.fireAndWait`; +the inline `_dispatchInFlight` + `_delayedCall` block is gone. +`turnOffAllMachines` calls `cancelPending()` on the dispatcher +instead of zeroing `_delayedCall`. `LatestWinsGate.js` 75 → 116 lines +(under the 150 cap). MGC `specificClass.js` net −14 lines. + +The `turnoff-deadlock` test that pinned `_delayedCall` was rewritten +to assert against the parked `fireAndWait` resolving as superseded. +Other awaiting tests (`ncog-distribution`, `idle-startup-deadlock`, +`demand-cycle-walkthrough`) needed no change since `fireAndWait` +preserves the "await waits for the call's dispatch" shape for +non-superseded calls. All 77/77 MGC tests pass; 12/12 LatestWinsGate +basic tests pass. + +### Original entry below +## 2026-05-10 — MGC handleInput retained inline latest-wins (not DemandDispatcher) (history) **Context:** Wave 1 added `src/dispatch/demandDispatcher.js` wrapping `LatestWinsGate`. Tests (`turnoff-deadlock`, `idle-startup-deadlock`, diff --git a/nodes/generalFunctions b/nodes/generalFunctions index f117546..5ea968e 160000 --- a/nodes/generalFunctions +++ b/nodes/generalFunctions @@ -1 +1 @@ -Subproject commit f11754635beae5e405d424fe4977976981e4e56d +Subproject commit 5ea968eabc97271ab13ca58e1b19ad4f7de5eb6d diff --git a/nodes/machineGroupControl b/nodes/machineGroupControl index 0e8cab5..31324ae 160000 --- a/nodes/machineGroupControl +++ b/nodes/machineGroupControl @@ -1 +1 @@ -Subproject commit 0e8cab5d3fdf6241a0497d13a285c655a0cbdc27 +Subproject commit 31324ae82d5cd3c2ace37c0afb637d02cdbfedb4 diff --git a/nodes/measurement b/nodes/measurement index e6e212a..497f05d 160000 --- a/nodes/measurement +++ b/nodes/measurement @@ -1 +1 @@ -Subproject commit e6e212a504ca36fdb361e99784943de9254fdf92 +Subproject commit 497f05d92c6bb18182baf0457c67d8a53afc2e9b diff --git a/nodes/monster b/nodes/monster index 2aa7f88..0038a8c 160000 --- a/nodes/monster +++ b/nodes/monster @@ -1 +1 @@ -Subproject commit 2aa7f88f03e4a5392bbb75e136fc753bb85fc021 +Subproject commit 0038a8c2c2d6c0f4987f2438cc59404b75bea33f