Sidebar swatch now follows function family rather than S88 level, so the
palette is visually identifiable instead of monochromatically blue. Editor-group
rectangles in flow.json still follow S88 — only the registerType color changed.
Full table + rationale: superproject .claude/rules/node-red-flow-layout.md §10.0
and .claude/refactor/OPEN_QUESTIONS.md (2026-05-21 entry).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Was capped at 600 px and horizontally centred. Removing both lets the SVG
expand to the editor column width, which on wider screens stops the
diagram from sitting in a narrow stripe with empty margins.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Editor UI overhaul:
* Pump banner — SVG of a generic centrifugal pump (volute, impeller,
motor stub, suction + discharge pipes) at the top for visual orientation.
* Sequence-timing: side-panel inputs hover-coupled to a circular FSM donut.
Arc angle proportional to phase seconds; idle a small loop slice at the
top, operational the dominant arc at the bottom. Protected phases mark
warm-up / cool-down with text-style shield (VS-15) inheriting arc colour.
Donut height measured at runtime against the side-panel column so the
bounding box lines up with the row stack.
* Movement mode: dropdown replaced with two compact 94x86 icon cards
(Static linear ramp, Dynamic sigmoid).
* Output formats: switched to the shared evolv-icon-picker pattern (now
also auto-applied platform-wide by generalFunctions/menu/iconHelpers).
* CLAUDE.md: Folder & File Layout section per EVOLV convention.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
specificClass._setupCurves now calls assetResolver.resolveAssetMetadata
to derive supplier/type/units from the model id, instead of trusting
denormalized fields on the node config. If the model isn't in the
registry, installs a null-predictor stub and logs a clear "pick a model
from the asset menu" error rather than crashing.
rotatingMachine.html: defaults block trimmed (supplier/category/assetType
were stale copies of registry data).
Tests:
- New test/basic/assetMetadata.basic.test.js covers the registry-resolve
path and the missing-model fallback.
- nodeClass-config / error-paths / nodeClass-routing / factories /
abort-deadlock fixtures updated to the trimmed asset shape.
- 209/209 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- rotatingMachine.html: add default name:{value:""} to the editor
defaults block (standard Node-RED pattern; was missing).
- nodeClass.js: clear node status badge on close — matches the
pattern already in other EVOLV node close handlers.
- specificClass.js: remove the `(x <= 0) ? 0 : ...` guard in the
flow and power prediction methods. The guard was redundant:
predictions only run while the FSM is in an active state
(operational / starting / warmingup / accelerating / decelerating),
none of which produce x=0. Math.max(0, rawFlow) still clamps
negative extrapolation. Net: same behaviour in production, less
dead code.
All 10 basic tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Safety:
- Async input handler: await all handleInput() calls, prevents unhandled rejections
- Fix emergencyStop case mismatch: "emergencyStop" → "emergencystop" matching config
- Implement showCoG() method (was routing to undefined)
- Null guards on 6 methods for missing curve data
- Editor menu polling timeout (5s max)
- Listener cleanup on node close (child measurements + state emitter)
- Tick loop race condition: track startup timeout, clear on close
Prediction accuracy:
- Remove efficiency rounding that destroyed signal in canonical units
- Fix calcEfficiency variant: hydraulic power reads from correct variant
- Guard efficiency calculations against negative/zero values
- Division-by-zero protection in calcRelativeDistanceFromPeak
- Curve data anomaly detection (cross-pressure median-y ratio check)
- calcEfficiencyCurve O(n²) → O(n) with running min
- updateCurve bootstraps predictors when they were null
Tests: 43 new tests (76 total) covering emergency stop, shutdown/maintenance
sequences, efficiency/CoG, movement lifecycle, output format, null guards,
and listener cleanup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>