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>
This commit is contained in:
znetsixe
2026-05-10 22:00:34 +02:00
parent c5bb375dd0
commit e058fe9245
13 changed files with 1046 additions and 2291 deletions

View File

@@ -34,22 +34,20 @@ test('setpoint is constrained to safe movement/curve bounds', async () => {
assert.equal(requested[1], max);
});
test('nodeClass _updateNodeStatus returns error status on internal failure', () => {
const inst = Object.create(NodeClass.prototype);
const node = makeNodeStub();
inst.node = node;
inst.source = {
test('source.getStatusBadge returns error status on internal failure', () => {
// Status badge lives on the domain post-refactor. Build a tiny stub
// that throws to verify the error-path returns an error badge.
const errors = [];
const source = {
currentMode: 'auto',
state: {
getCurrentState() {
throw new Error('boom');
},
},
state: { getCurrentState() { throw new Error('boom'); } },
logger: { error: (m) => errors.push(m) },
};
const status = inst._updateNodeStatus();
assert.equal(status.text, 'Status Error');
assert.equal(node._errors.length, 1);
const { buildStatusBadge } = require('../../src/io/output');
const status = buildStatusBadge(source);
assert.match(status.text, /Status Error/);
assert.equal(status.fill, 'red');
assert.equal(errors.length, 1);
});
test('measurement handlers reject incompatible units', () => {