Files
rotatingMachine/src/specificClass.js

426 lines
22 KiB
JavaScript
Raw Normal View History

P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
'use strict';
// rotatingMachine — S88 Equipment Module domain orchestrator.
//
// All heavy lifting lives in concern modules under src/{curves,prediction,
// drift,pressure,state,measurement,flow,display,io,commands}. This file
// stitches them together and preserves the public API the existing test
// suite + sibling nodes (MGC, pumpingStation) depend on.
const { BaseDomain, UnitPolicy, state, nrmse, interpolation, convert, assetResolver } = require('generalFunctions');
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const { loadModelCurve } = require('./curves/curveLoader');
const { normalizeMachineCurve } = require('./curves/curveNormalizer');
const { reverseCurve } = require('./curves/reverseCurve');
const { buildPredictors } = require('./prediction/predictors');
const { buildGroupPredictors } = require('./prediction/groupPredictors');
const pmath = require('./prediction/predictionMath');
const eff = require('./prediction/efficiencyMath');
const DriftAssessor = require('./drift/driftAssessor');
const healthRefresh = require('./drift/healthRefresh');
const VirtualPressureChildren = require('./pressure/virtualChildren');
const PressureInitialization = require('./pressure/pressureInitialization');
const PressureRouter = require('./pressure/pressureRouter');
const { getMeasuredPressure } = require('./pressure/pressureSelector');
const { bindStateEvents, isOperationalState } = require('./state/stateBindings');
const sequence = require('./state/sequenceController');
const MeasurementHandlers = require('./measurement/measurementHandlers');
const { registerMeasurementChild, detachAllListeners } = require('./measurement/childRegistrar');
const FlowController = require('./flow/flowController');
const display = require('./display/workingCurves');
const io = require('./io/output');
class Machine extends BaseDomain {
static name = 'rotatingMachine';
static unitPolicy = UnitPolicy.declare({
canonical: { pressure: 'Pa', atmPressure: 'Pa', flow: 'm3/s', power: 'W', temperature: 'K' },
output: { pressure: 'mbar', flow: 'm3/h', power: 'kW', temperature: 'C', atmPressure: 'Pa' },
curve: { pressure: 'mbar', flow: 'm3/h', power: 'kW', control: '%' },
requireUnitForTypes: ['pressure', 'flow', 'power', 'temperature', 'atmPressure'],
});
// ES6 forbids `this` before super(). Single-threaded JS means stashing
// on the class itself between the caller's args and super() is race-free;
// configure() picks the extras up immediately after.
2025-06-25 17:26:13 +02:00
constructor(machineConfig = {}, stateConfig = {}, errorMetricsConfig = {}) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
Machine._pendingExtras = { stateConfig, errorMetricsConfig };
super(machineConfig);
}
2025-06-25 17:26:13 +02:00
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
configure() {
const extras = Machine._pendingExtras || {};
Machine._pendingExtras = null;
2025-06-25 17:26:13 +02:00
this.interpolation = new interpolation();
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.config = this.configUtils.updateConfig(this.config, {
general: { name: `${this.config.functionality?.softwareType}_${this.config.general.id}` },
2025-06-25 17:26:13 +02:00
});
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this._setupCurves();
this.groupPredictFlow = null; this.groupPredictPower = null; this.groupPredictCtrl = null; this.groupNCog = 0;
this._setupState(extras);
this._setupDrift();
this._setupPressure();
this._setupChildren();
}
_setupCurves() {
this.model = this.config.asset?.model;
// Resolve derived metadata (supplier / type / allowed units) from the asset
// registry. Source of truth lives in generalFunctions/datasets/assetData/.
// If the registry has no entry for this model, assetMetadata is null and
// we'll error out with a clear message below.
this.assetMetadata = this.model
? assetResolver.resolveAssetMetadata('machine', this.model)
: null;
if (!this.model) {
this.logger.error(`rotatingMachine: asset.model is required. Open the node, pick a model from the asset menu, and save.`);
this._installNullPredictors();
return;
}
if (!this.assetMetadata) {
this.logger.error(`rotatingMachine: model '${this.model}' not found in asset registry (datasets/assetData/machine.json). Cannot derive supplier/type/units.`);
this._installNullPredictors();
return;
}
// Validate the chosen deployment unit. Hard check: it must be a recognised
// flow unit (convert() can describe it). Soft check: warn if it isn't in
// the registry's allowed-set for this model — the list is the editor's
// recommended dropdown, not an exhaustive whitelist.
const chosenUnit = this.config.asset?.unit;
if (!chosenUnit) {
this.logger.error(`rotatingMachine: asset.unit is required for model '${this.model}'. Re-save the node from the editor.`);
this._installNullPredictors();
return;
}
try {
const desc = convert().describe(chosenUnit);
if (desc.measure !== 'volumeFlowRate') {
this.logger.error(`rotatingMachine: asset.unit '${chosenUnit}' is not a flow unit (got measure '${desc.measure}').`);
this._installNullPredictors();
return;
}
} catch (_) {
this.logger.error(`rotatingMachine: asset.unit '${chosenUnit}' is not a recognised unit.`);
this._installNullPredictors();
return;
}
const allowedUnits = this.assetMetadata.units || [];
if (allowedUnits.length > 0 && !allowedUnits.includes(chosenUnit)) {
this.logger.warn(
`rotatingMachine: asset.unit '${chosenUnit}' is not in the registry's recommended list ` +
`for model '${this.model}' (allowed: [${allowedUnits.join(', ')}]). Continuing — the unit is a valid flow unit.`,
);
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const { rawCurve, error } = loadModelCurve(this.model);
this.rawCurve = rawCurve;
if (error) { this.logger.error(`${error} in machineConfig. Cannot make predictions.`); this._installNullPredictors(); return; }
try {
this.curve = normalizeMachineCurve(rawCurve, this.unitPolicy, this.logger);
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.config = this.configUtils.updateConfig(this.config, { asset: { ...this.config.asset, machineCurve: this.curve } });
const built = buildPredictors(this.config.asset.machineCurve);
this.predictors = built;
this.predictFlow = built.predictFlow; this.predictPower = built.predictPower; this.predictCtrl = built.predictCtrl;
this.hasCurve = true;
} catch (e) {
this.logger.error(`Curve normalization failed for model '${this.model}': ${e.message}`);
this._installNullPredictors();
}
2025-09-04 17:07:29 +02:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_installNullPredictors() {
this.predictFlow = null; this.predictPower = null; this.predictCtrl = null;
this.predictors = { predictFlow: null, predictPower: null, predictCtrl: null };
this.hasCurve = false;
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_setupState(extras) {
this.state = new state(extras.stateConfig || {}, this.logger);
this.errorMetrics = new nrmse(extras.errorMetricsConfig || {}, this.logger);
this.currentMode = this.config.mode.current;
this.currentEfficiencyCurve = {};
this.cog = 0; this.NCog = 0; this.cogIndex = 0;
this.minEfficiency = 0; this.absDistFromPeak = 0; this.relDistFromPeak = 0;
this._stateUnbind = bindStateEvents({
state: this.state,
onPositionChange: () => this.updatePosition(),
onStateChange: () => this._updateState(),
fix: interruptible shutdown/emergencystop + dual-curve test coverage Runtime: - executeSequence now normalizes sequenceName to lowercase so parent orchestrators that use 'emergencyStop' (capital S) route correctly to the 'emergencystop' sequence key. Closes the "Sequence 'emergencyStop' not defined" warn seen when commands reach the node during accelerating. - When a shutdown or emergencystop sequence is requested while the FSM is in accelerating/decelerating, the active movement is aborted via state.abortCurrentMovement() and the sequence waits (up to 2s) for the FSM to return to 'operational' before proceeding. New helper _waitForOperational listens on the state emitter for the transition. - Single-side pressure warning: fix "acurate" typo and make the message actionable. Tests (+15, now 91/91 passing): - test/integration/interruptible-movement.integration.test.js (+3): shutdown during accelerating -> idle; emergencystop during accelerating -> off; mixed-case sequence-name normalization. - test/integration/curve-prediction.integration.test.js (+12): parametrized across both shipped pump curves (hidrostal-H05K-S03R and hidrostal-C5-D03R-SHN1). Verifies loader integrity, mid-range prediction sanity, flow monotonicity in ctrl, inverse-pressure monotonicity, CoG finiteness, and reverse-predictor round-trip. E2E: - test/e2e/curve-prediction-benchmark.py: live Dockerized Node-RED benchmark that deploys one rotatingMachine per curve and runs a per-pump (pressure x ctrl) sweep inside each curve's envelope. Reports envelope compliance and monotonicity. - test/e2e/README.md documents the benchmark and a known limitation: pressure below the curve's minimum slice extrapolates wildly (defended by upstream measurement-node clamping in production). UX: - rotatingMachine.html: added placeholders and descriptions for Reaction Speed / Startup / Warmup / Shutdown / Cooldown. Expanded the Node-RED help panel with a topic reference, port documentation, state diagram, and prediction rules. Docs: - README.md rewritten (was a single line) with install, quick start, topic/port reference, state machine, predictions, testing, production status. Depends on generalFunctions commit 75d16c6 (state.js abort recovery and rotatingMachine schema additions). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:21:48 +02:00
});
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_setupDrift() {
this.driftProfiles = {
flow: { windowSize: 30, minSamplesForLongTerm: 10, ewmaAlpha: 0.15, alignmentToleranceMs: 2500, strictValidation: true },
power: { windowSize: 30, minSamplesForLongTerm: 10, ewmaAlpha: 0.15, alignmentToleranceMs: 2500, strictValidation: true },
2026-03-11 11:13:26 +01:00
};
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.errorMetrics.registerMetric('flow', this.driftProfiles.flow);
this.errorMetrics.registerMetric('power', this.driftProfiles.power);
this.flowDrift = null; this.powerDrift = null;
this.pressureDrift = { level: 0, flags: ['nominal'], source: null };
this.predictionHealth = { quality: 'invalid', confidence: 0, pressureSource: null, flags: ['not_initialized'] };
this.driftAssessor = new DriftAssessor({
errorMetrics: this.errorMetrics,
measurements: this.measurements,
driftProfiles: this.driftProfiles,
logger: this.logger,
resolveProcessRange: (m, p, q) => this._resolveProcessRangeForMetric(m, p, q),
measurementPositionForMetric: (m) => this._measurementPositionForMetric(m),
});
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_setupPressure() {
this.virtualPressureChildIds = { upstream: 'dashboard-sim-upstream', downstream: 'dashboard-sim-downstream' };
this.realPressureChildIds = { upstream: new Set(), downstream: new Set() };
this.virtualPressureChildren = new VirtualPressureChildren({
logger: this.logger, unitPolicy: this.unitPolicy, parentRef: this,
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
ids: this.virtualPressureChildIds,
}).build();
this.pressureInit = new PressureInitialization({
measurements: this.measurements,
virtualPressureChildIds: this.virtualPressureChildIds,
realPressureChildIds: this.realPressureChildIds,
logger: this.logger,
});
this.pressureRouter = new PressureRouter({
measurements: this.measurements,
virtualPressureChildIds: this.virtualPressureChildIds,
resolveMeasurementUnit: (t, u) => this._resolveMeasurementUnit(t, u),
updatePosition: () => this.updatePosition(),
refreshDrift: () => this._updatePressureDriftStatus(),
refreshHealth: () => this._updatePredictionHealth(),
getPressure: () => this.getMeasuredPressure(),
logger: this.logger,
});
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_setupChildren() {
this.child = this.child || {};
this.childMeasurementListeners = new Map();
this.measurementHandlers = new MeasurementHandlers({ host: this, logger: this.logger });
this.flowController = new FlowController({ host: this, logger: this.logger });
this.registerChild = (child, softwareType) => registerMeasurementChild(this, child, softwareType);
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this._init();
this.registerChild(this.virtualPressureChildren.upstream, 'measurement');
this.registerChild(this.virtualPressureChildren.downstream, 'measurement');
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_init() {
const tu = this.unitPolicy.output.temperature;
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.measurements.type('temperature').variant('measured').position('atEquipment').value(15, Date.now(), tu);
this.measurements.type('atmPressure').variant('measured').position('atEquipment').value(101325, Date.now(), 'Pa');
const fu = this.unitPolicy.canonical.flow;
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const fmin = this.predictFlow ? this.predictFlow.currentFxyYMin : 0;
const fmax = this.predictFlow ? this.predictFlow.currentFxyYMax : 0;
this.measurements.type('flow').variant('predicted').position('max').value(fmax, Date.now(), fu);
this.measurements.type('flow').variant('predicted').position('min').value(fmin, Date.now(), fu);
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
_callMeasurementHandler(measurementType, value, position, context = {}) {
return this.measurementHandlers.dispatch(measurementType, value, position, context);
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── unit helpers ────────────────────────────────────────────────────
isUnitValidForType(type, unit) { return this.measurements?.isUnitCompatible?.(type, unit) === true; }
2026-03-11 11:13:26 +01:00
_resolveMeasurementUnit(type, providedUnit) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const u = typeof providedUnit === 'string' ? providedUnit.trim() : '';
if (!u) throw new Error(`Missing unit for ${type} measurement.`);
if (!this.isUnitValidForType(type, u)) throw new Error(`Unsupported unit '${u}' for ${type} measurement.`);
return u;
}
_convertUnitValue(value, from, to, ctx = 'unit conversion') {
const n = Number(value);
if (!Number.isFinite(n)) throw new Error(`${ctx}: value '${value}' is not finite`);
if (!from || !to || from === to) return n;
return convert(n).from(from).to(to);
}
_measurementPositionForMetric(metricId) { return metricId === 'power' ? 'atEquipment' : 'downstream'; }
_resolveProcessRangeForMetric(metricId, predicted, measured) {
let processMin = NaN; let processMax = NaN;
if (metricId === 'flow') { processMin = Number(this.predictFlow?.currentFxyYMin); processMax = Number(this.predictFlow?.currentFxyYMax); }
else if (metricId === 'power'){ processMin = Number(this.predictPower?.currentFxyYMin); processMax = Number(this.predictPower?.currentFxyYMax); }
2026-03-11 11:13:26 +01:00
if (!Number.isFinite(processMin) || !Number.isFinite(processMax) || processMax <= processMin) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const p = Number(predicted); const m = Number(measured);
const lo = Math.min(p, m); const hi = Math.max(p, m);
processMin = Number.isFinite(lo) ? lo : 0;
processMax = Number.isFinite(hi) && hi > processMin ? hi : processMin + 1;
2026-03-11 11:13:26 +01:00
}
return { processMin, processMax };
}
_updateMetricDrift(metricId, measuredValue, context = {}) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const drift = this.driftAssessor.updateMetricDrift(metricId, measuredValue, context);
if (drift && drift.valid) {
if (metricId === 'flow') this.flowDrift = drift;
if (metricId === 'power') this.powerDrift = drift;
}
return drift;
}
assessDrift(measurement, processMin, processMax) { return this.driftAssessor.assessDrift(measurement, processMin, processMax); }
_applyDriftPenalty(drift, confidence, flags, prefix) { return this.driftAssessor.applyDriftPenalty(drift, confidence, flags, prefix); }
_isOperationalState() { return isOperationalState(this.state); }
// ── pressure ───────────────────────────────────────────────────────
_getPreferredPressureValue(position) { return this.pressureInit.getPreferredValue(position); }
getPressureInitializationStatus() { return this.pressureInit.getStatus(); }
getMeasuredPressure() { return getMeasuredPressure(this); }
_updatePressureDriftStatus() { return healthRefresh.updatePressureDriftStatus(this); }
_updatePredictionHealth() { return healthRefresh.updatePredictionHealth(this); }
// ── measurement updaters (delegate to handlers) ────────────────────
updateMeasuredPressure(value, position, context = {}) { this.pressureRouter.route(position, value, context); }
updateMeasuredFlow(value, position, context = {}) { return this.measurementHandlers.updateMeasuredFlow(value, position, context); }
updateMeasuredPower(value, position, context = {}) { return this.measurementHandlers.updateMeasuredPower(value, position, context); }
updateMeasuredTemperature(value, position, context = {}) { return this.measurementHandlers.updateMeasuredTemperature(value, position, context); }
updateSimulatedMeasurement(type, position, value, context = {}) {
return this.measurementHandlers.updateSimulatedMeasurement(type, position, value, context);
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
handleMeasuredFlow() { return this.measurementHandlers.handleMeasuredFlow(); }
handleMeasuredPower() { return this.measurementHandlers.handleMeasuredPower(); }
2026-03-11 11:13:26 +01:00
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── state-machine driven recompute ─────────────────────────────────
_updateState() {
2026-03-11 11:13:26 +01:00
if (!this._isOperationalState()) {
const fu = this.unitPolicy.canonical.flow;
const pu = this.unitPolicy.canonical.power;
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.measurements.type('flow').variant('predicted').position('downstream').value(0, Date.now(), fu);
this.measurements.type('flow').variant('predicted').position('atEquipment').value(0, Date.now(), fu);
this.measurements.type('power').variant('predicted').position('atEquipment').value(0, Date.now(), pu);
2025-06-25 17:26:13 +02:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this._updatePredictionHealth();
2026-03-11 11:13:26 +01:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
updatePosition() {
if (this._isOperationalState()) {
const x = this.state.getCurrentPosition();
const { cPower, cFlow } = this.calcFlowPower(x);
const efficiency = this.calcEfficiency(cPower, cFlow, 'predicted');
const { cog, minEfficiency } = this.calcCog();
this.calcDistanceBEP(efficiency, cog, minEfficiency);
2025-06-25 17:26:13 +02:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this._updatePredictionHealth();
2025-06-25 17:26:13 +02:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── mode + input dispatch ──────────────────────────────────────────
2025-06-25 17:26:13 +02:00
isValidSourceForMode(source, mode) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const ok = (this.config.mode.allowedSources[mode] || []).has(source);
if (ok) this.logger.debug(`source is allowed proceeding with ${source} for mode ${mode}`);
else this.logger.warn(`${source} is not allowed in mode ${mode}`);
return ok;
2025-06-25 17:26:13 +02:00
}
isValidActionForMode(action, mode) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const ok = (this.config.mode.allowedActions[mode] || []).has(action);
if (ok) this.logger.debug(`Action is allowed proceeding with ${action} for mode ${mode}`);
else this.logger.warn(`${action} is not allowed in mode ${mode}`);
return ok;
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
handleInput(source, action, parameter) { return this.flowController.handle(source, action, parameter); }
abortMovement(reason = 'group override') { if (this.state?.abortCurrentMovement) this.state.abortCurrentMovement(reason); }
2025-06-25 17:26:13 +02:00
setMode(newMode) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const allowed = this.defaultConfig.mode.current.rules.values.map((v) => v.value);
if (!allowed.includes(newMode)) { this.logger.warn(`Invalid mode '${newMode}'. Allowed modes are: ${allowed.join(', ')}`); return; }
2025-06-25 17:26:13 +02:00
this.currentMode = newMode;
this.logger.info(`Mode successfully changed to '${newMode}'.`);
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
updateConfig(newConfig) { this.config = this.configUtils.updateConfig(this.config, newConfig); }
_waitForOperational(t) { return sequence.waitForOperational(this, t); }
executeSequence(name) { return sequence.executeSequence(this, name); }
setpoint(target) { return sequence.setpoint(this, target); }
_resolveSetpointBounds() { return sequence.resolveSetpointBounds(this); }
2025-06-25 17:26:13 +02:00
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── curve-driven prediction (delegates) ────────────────────────────
calcFlow(x) { return pmath.calcFlow(this, x); }
calcPower(x) { return pmath.calcPower(this, x); }
calcCtrl(x) { return pmath.calcCtrl(this, x); }
inputFlowCalcPower(f) { return pmath.inputFlowCalcPower(this, f); }
calcFlowPower(x) { return { cFlow: this.calcFlow(x), cPower: this.calcPower(x) }; }
2025-07-01 15:25:07 +02:00
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── group-scope operating point (MGC) ──────────────────────────────
_ensureGroupPredicts() {
if (!this.hasCurve || !this.predictFlow || !this.predictPower || !this.predictCtrl) return;
if (this.groupPredictFlow && this.groupPredictPower && this.groupPredictCtrl) return;
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const built = buildGroupPredictors(this.predictors);
if (!built) return;
this.groupPredictFlow = built.groupPredictFlow;
this.groupPredictPower = built.groupPredictPower;
this.groupPredictCtrl = built.groupPredictCtrl;
}
setGroupOperatingPoint(downstreamPa, upstreamPa) {
this._ensureGroupPredicts();
if (!this.groupPredictFlow || !this.groupPredictPower) return;
if (!Number.isFinite(downstreamPa) || !Number.isFinite(upstreamPa)) return;
const diff = downstreamPa - upstreamPa;
if (diff <= 0) return;
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.groupPredictFlow.fDimension = diff;
this.groupPredictPower.fDimension = diff;
if (this.groupPredictCtrl) this.groupPredictCtrl.fDimension = diff;
this.groupNCog = this._calcGroupCog();
}
groupCalcPower(flow) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
if (!this.groupPredictFlow || !this.groupPredictPower || !this.groupPredictCtrl) return this.inputFlowCalcPower(flow);
this.groupPredictCtrl.currentX = flow;
const cCtrl = this.groupPredictCtrl.y(flow);
this.groupPredictPower.currentX = cCtrl;
return this.groupPredictPower.y(cCtrl);
}
_calcGroupCog() {
if (!this.groupPredictFlow || !this.groupPredictPower) return 0;
const powerCurve = this.groupPredictPower.currentFxyCurve[this.groupPredictPower.currentF];
const flowCurve = this.groupPredictFlow.currentFxyCurve[this.groupPredictFlow.currentF];
if (!powerCurve?.y?.length || !flowCurve?.y?.length) return 0;
const { peakIndex } = this.calcEfficiencyCurve(powerCurve, flowCurve);
const yMin = this.groupPredictFlow.currentFxyYMin;
const yMax = this.groupPredictFlow.currentFxyYMax;
if (yMax <= yMin) return 0;
return (flowCurve.y[peakIndex] - yMin) / (yMax - yMin);
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
reverseCurve(c) { return reverseCurve(c); }
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── efficiency math (delegates) ────────────────────────────────────
calcCog() { return eff.calcCog(this); }
calcEfficiencyCurve(p, f) { return eff.calcEfficiencyCurve(p, f); }
calcEfficiency(power, flow, variant) { return eff.calcEfficiency(this, power, flow, variant); }
calcDistanceBEP(e, max, min) { return eff.calcDistanceBEP(this, e, max, min); }
calcDistanceFromPeak(e, peak) { return eff.calcDistanceFromPeak(e, peak); }
calcRelativeDistanceFromPeak(e, max, min) { return eff.calcRelativeDistanceFromPeak(this, e, max, min); }
getCurrentCurves() { return eff.getCurrentCurves(this); }
getCompleteCurve() { return eff.getCompleteCurve(this); }
2025-06-25 17:26:13 +02:00
updateCurve(newCurve) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.logger.info('Updating machine curve');
const normalized = normalizeMachineCurve(newCurve, this.unitPolicy, this.logger);
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.config = this.configUtils.updateConfig(this.config, {
asset: { machineCurve: normalized, curveUnits: this.unitPolicy.curve },
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
});
if (!this.predictFlow || !this.predictPower || !this.predictCtrl) {
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
const built = buildPredictors(this.config.asset.machineCurve);
this.predictors = built;
this.predictFlow = built.predictFlow; this.predictPower = built.predictPower; this.predictCtrl = built.predictCtrl;
this.hasCurve = true;
} else {
this.predictFlow.updateCurve(this.config.asset.machineCurve.nq);
this.predictPower.updateCurve(this.config.asset.machineCurve.np);
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
this.predictCtrl.updateCurve(reverseCurve(this.config.asset.machineCurve.nq));
}
2025-06-25 17:26:13 +02:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
showCoG() { return display.showCoG(this); }
showWorkingCurves() { return display.showWorkingCurves(this); }
2025-06-25 17:26:13 +02:00
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
// ── output + status ─────────────────────────────────────────────────
getOutput() { return io.buildOutput(this); }
getStatusBadge() { return io.buildStatusBadge(this); }
2025-06-25 17:26:13 +02:00
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
close() {
this._stateUnbind?.();
detachAllListeners(this);
if (this.state?.emitter) this.state.emitter.removeAllListeners();
super.close?.();
2025-06-25 17:26:13 +02:00
}
P5 wave 2: convert rotatingMachine to BaseDomain + extract helper modules specificClass.js: 1760 → 400 lines. Machine extends BaseDomain. configure() wires curves + predictors + drift + pressure + state bindings + measurement handlers + flow controller. ChildRouter handles pressure/flow/power/temperature measurement events; custom registerChild override preserves the dedup + virtual-vs-real pressure tracking the integration tests pin. Added small host-aware helper modules to fit the 400-line cap: src/prediction/predictionMath.js (calcFlow/Power/Ctrl) src/prediction/efficiencyMath.js (calcCog/EfficiencyCurve/etc.) src/pressure/pressureSelector.js (getMeasuredPressure source preference) src/state/sequenceController.js (executeSequence/setpoint/wait helpers) src/measurement/childRegistrar.js (custom registerChild path) src/drift/healthRefresh.js (drift status update wrappers) src/io/output.js (buildOutput + buildStatusBadge) unitPolicy: live UnitPolicy methods .canonical()/.output()/.curve() bridged to legacy property-path readers via a frozen view object — same pattern as MGC. See OPEN_QUESTIONS.md. nodeClass.js: 433 → 61 lines. Extends BaseNodeAdapter. tickInterval=null (event-driven on state + measurement events). buildDomainConfig stamps the rotatingMachine state + errorMetrics slices on the domain config so configure() builds them from there. 5 tests adjusted (4 nodeClass-config, 1 error-paths) — pre-refactor they pinned private methods (_loadConfig, _setupSpecificClass, _attachInputHandler, _updateNodeStatus) that no longer exist. New versions drive the public BaseNodeAdapter surface or call extracted io/state-machine helpers directly. See OPEN_QUESTIONS.md 2026-05-10 "private nodeClass tests" for the deferred rewrite plan. 196 / 196 tests pass (basic 110 + integration ~80 + edge ~6). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:00:34 +02:00
}
2025-06-25 17:26:13 +02:00
module.exports = Machine;