186 Commits

Author SHA1 Message Date
znetsixe
4a9521154b fix: safety overfill keeps pumps running + minHeightBasedOn=inlet
Some checks failed
CI / lint-and-test (push) Has been cancelled
pumpingStation 5e2ebe4: overfill safety no longer shuts down machine
groups or blocks level control. Pumps keep running during overfill
(sewer can't stop receiving). Only upstream equipment is shut down.

Demo config: minHeightBasedOn=inlet (not outlet). The minimum height
reference for the basin is the inlet pipe elevation — sewage flows
in by gravity and the basin level can't go below the inlet without
the sewer backing up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 14:11:08 +02:00
znetsixe
732b5a3380 fix: realistic sinus + continuous pump control + dead zone elimination
Some checks failed
CI / lint-and-test (push) Has been cancelled
Sinus inflow: 54-270 m³/h (base 0.015 + amplitude 0.06 m³/s), 4 min
period. Peak needs 1-2 pumps, never all 3 = realistic headroom.

PS control: continuous proportional demand when level > stopLevel, not
just when > startLevel && filling. Pumps now ramp down smoothly as
basin drains toward stopLevel instead of staying stuck at last setpoint.

pumpingStation e8dd657: dead zone elimination
build_flow.py: sinus tuned for gradual pump scaling visibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 13:42:55 +02:00
znetsixe
c8f149e204 feat(dashboard): split basin charts by unit + add y-axis labels to all charts
Some checks failed
CI / lint-and-test (push) Has been cancelled
Flow: m³/h, Power: kW, Basin Level: m, Basin Fill: % (0-100 fixed).
Level and fill in separate chart groups with their own gauges.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 13:19:32 +02:00
znetsixe
b693e0b90c fix: graduated pump control + mass balance corrections
Some checks failed
CI / lint-and-test (push) Has been cancelled
Three fixes:

1. PS outflow triple-counted (pumpingStation c62d8bc): MGC registered
   twice + individual pumps registered alongside MGC + dual event
   subscription per child. Now: one registration per aggregation level,
   one event per child. Volume integration tracks correctly.

2. All 3 pumps always on: minFlowLevel was 1.0 m but startLevel was
   2.0 m, so at the moment pumps started the percControl was already
   40% → MGC mapped to 356 m³/h → all 3 pumps. Fixed: minFlowLevel
   = startLevel (2.0 m) so percControl starts at 0% and ramps
   linearly. Now pumps graduate: 1-2 pumps at low level, 3 at high.

3. Generalizable registration rule added as code comments: when a group
   aggregator exists (MGC), subscribe to it, not its children. Pick
   one event name per measurement type per child.

E2E verified: 2/3 pumps active at 56% fill, volume draining correctly,
pump C at 5.2% ctrl delivering 99 m³/h while pump A stays off.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 13:10:32 +02:00
znetsixe
2b0c4e89b1 fix: abort recovery bounce loop broke MGC → pump control
Some checks failed
CI / lint-and-test (push) Has been cancelled
generalFunctions 086e5fe -> 693517c:
  abortCurrentMovement now takes options.returnToOperational (default
  false). Routine MGC demand-update aborts leave pumps in their current
  state. Only shutdown/emergency-stop paths pass returnToOperational:true.

rotatingMachine 510a423 -> 11d196f:
  executeSequence passes returnToOperational:true for shutdown/estop.

Verified E2E: PS fills to startLevel → MGC distributes demand → all 3
pumps at 1.31% ctrl delivering 121 m³/h each → basin draining at
-234 m³/h net. Full fill/drain cycle operational.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 12:11:36 +02:00
znetsixe
faaeb2efd3 fix: realistic basin sizing + boosted sinus inflow for visible fill cycle
Some checks failed
CI / lint-and-test (push) Has been cancelled
Basin was 30 m³ with 72 m³/h average sinus inflow → took 10+ minutes
to reach startLevel, looking static on the dashboard. Boosted sinus to
base=0.02 + amplitude=0.10 m³/s (avg ~252 m³/h, peak ~432 m³/h). Basin
fills from outlet to startLevel in ~3 minutes now.

Also removed initBasinProperties trace from previous debug session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:17:17 +02:00
znetsixe
53b55d81c3 fix: fully configure PS basin + add node-completeness rule
Some checks failed
CI / lint-and-test (push) Has been cancelled
Basin undersized (10m³) for sinus peak (126 m³/h) → overflow → 122%.
Now 30 m³ with 4m height, all PS fields set. New rule: always configure
every field of every node.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:00:27 +02:00
znetsixe
eb97670179 fix(dashboard): use correct basin capacity for fill % + clamp to 0-100
Some checks failed
CI / lint-and-test (push) Has been cancelled
maxVol was hardcoded to 9.33 (overflow volume at 2.8 m height) instead
of 10.0 (basin capacity = basinVolume config). Volumes above 9.33 m³
produced fill > 100% (e.g. 122% at vol=11.4). Fixed to use 10.0 and
clamp to [0, 100].

Patched via nodes-only deploy — basin not reset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:53:41 +02:00
znetsixe
cc4ee670ea fix(dashboard): move basin gauges to trend pages next to basin chart
Some checks failed
CI / lint-and-test (push) Has been cancelled
The tank gauge (basin level) and 270° arc gauge (fill %) now live on
the trend pages alongside the basin metrics chart — not on the control
page. Each trend page (10 min / 1 hour) gets its own pair of gauges.

Layout per trend page Basin group:
  - Chart (width 8): Basin fill % + Level + Net flow series
  - Tank gauge (width 2): 0–3 m with color zones at stop/start levels
  - Arc gauge (width 2): 0–100% fill with red/orange/green zones

Deployed via partial (nodes-only) deploy so the basin wasn't reset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:46:38 +02:00
znetsixe
a51bc46e26 feat(dashboard): add tank gauge for basin level + 270° arc for fill %
Some checks failed
CI / lint-and-test (push) Has been cancelled
Basin Status group on the Control page now has two visual gauges:

1. gauge-tank (vertical tank with fill gradient) for basin level 0–3 m.
   Color zones: red < 0.6 m (below stopLevel) → orange → blue 1.2–2.5 m
   (normal operating range) → orange → red > 2.8 m (overflow zone).

2. gauge-34 (270° arc) for fill percentage 0–100%.
   Color zones: red < 10% → orange → green 30–80% → orange → red > 95%.

Both gauges are fed from the PS dispatcher's numeric outputs (fillPctNum
and levelNum) which also feed the basin trend charts — same data, two
visual forms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:40:43 +02:00
znetsixe
b18c47c07e feat(dashboard): add basin fill gauge, countdown, and basin trend charts
Some checks failed
CI / lint-and-test (push) Has been cancelled
PS control page now shows 7 fields instead of 5:
  - Direction (filling/draining/steady)
  - Basin level (m)
  - Basin volume (m³)
  - Fill level (%)
  - Net flow (m³/h, signed)
  - Time to full/empty (countdown in min or s)
  - Inflow (m³/h)

Two new trend pages per time window (short 10 min / long 1 hour):
  - Basin chart: 3 series (Basin fill %, Basin level m, Net flow m³/h)
    on both Trends 10 min and Trends 1 hour pages.

PS formatter now extracts direction, netFlow, seconds from the delta-
compressed port 0 cache and computes fillPct from vol/maxVol. Dispatcher
sends 10 outputs (7 text + 3 trend numerics to both short+long basin
charts).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:35:44 +02:00
znetsixe
60c8d0ff66 fix: root-cause bogus machineCurve default poisoning spline predictions
Some checks failed
CI / lint-and-test (push) Has been cancelled
generalFunctions 29b78a3 -> 086e5fe:
  Schema default machineCurve.nq had a dummy pressure slice at key "1"
  with fake data. Deep merge injected it alongside real curve data,
  pulling the pressure-dimension spline negative at low pressures.
  Fix: default to empty {nq: {}, np: {}}.

rotatingMachine 26e253d -> 510a423:
  Tests updated for corrected fValues.min (70000 vs old 1).
  Trace instrumentation removed. 91/91 green.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:28:24 +02:00
znetsixe
658915c53e chore: bump rotatingMachine — clamp negative flow/power at ctrl≤0
Some checks failed
CI / lint-and-test (push) Has been cancelled
rotatingMachine: c464b66 -> 26e253d

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 10:07:10 +02:00
znetsixe
0cbd6a4077 wip: sinus-driven pumping station demo + PS levelbased control to MGC
Some checks failed
CI / lint-and-test (push) Has been cancelled
Architecture change: demo is now driven by a sinusoidal inflow into the
pumping station basin, rather than a random demand generator. The basin
fills from the sinus, and PS's levelbased control should start/stop
pumps via MGC when level crosses start/stop thresholds.

Changes:
- Demo Drivers tab: sinus generator (period 120s, base 0.005 + amp 0.03
  m³/s) replaces the random demand. Sends q_in to PS via link channel.
- PS config: levelbased mode, 10 m³ basin, startLevel 1.2 m / stopLevel
  0.6 m. Volume-based safeties on, time-based off.
- MGC scaling = normalized (was absolute) so PS's percent-based level
  control maps correctly.
- Dashboard mode toggle now drives PS mode (levelbased ↔ manual) instead
  of per-pump setMode. Slider sends Qd to PS (only effective in manual).
- PS code (committed separately): _controlLevelBased now calls
  _applyMachineGroupLevelControl + new Qd topic + forwardDemandToChildren.

KNOWN ISSUE: Basin fills correctly (visible on dashboard), but pumps
don't start when level exceeds startLevel. Likely cause: _pickVariant
for 'level' in _controlLevelBased may not be resolving the predicted
level correctly, or the safetyController is interfering despite
time-threshold being 0. Needs source-level tracing of the PS tick →
_safetyController → _controlLogic → _controlLevelBased path with
logging enabled. To be debugged in the next session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 08:42:22 +02:00
znetsixe
bc8138c3dc fix(charts): add all required FlowFuse ui-chart properties + document in rule set
Some checks failed
CI / lint-and-test (push) Has been cancelled
Charts rendered blank because the helper was missing 15+ required
FlowFuse properties. The critical three:
  - interpolation: "linear" (no line drawn without it)
  - yAxisProperty: "payload" + yAxisPropertyType: "msg" (chart didn't
    know which msg field to plot)
  - xAxisPropertyType: "timestamp" (chart didn't know the x source)

Also: width/height must be numbers not strings, colors/textColor/
gridColor arrays must be present, and stackSeries/bins/xAxisFormat/
xAxisFormatType all need explicit values.

Fixed the ui_chart helper to include every property from the working
rotatingMachine/examples/03-Dashboard.json charts. Added the full
required-property template + gotcha list to the flow-layout rule set
(Section 4) so this class of bug is caught by reference on the next
chart build.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 08:04:43 +02:00
znetsixe
06d81169e8 fix(trends): add msg.timestamp to chart data points
Some checks failed
CI / lint-and-test (push) Has been cancelled
FlowFuse ui-chart with xAxisType=time may need an explicit timestamp
on each msg for the time axis to render. Added Date.now() as
msg.timestamp on the per-pump dispatcher flow/power outputs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:59:04 +02:00
znetsixe
82db2953e9 fix(dashboard): resolve [object Object] in ui-text widgets + use dispatcher pattern
Some checks failed
CI / lint-and-test (push) Has been cancelled
FlowFuse ui-text only supports {{msg.payload}} — not nested paths
like {{msg.payload.state}}. Every ui-text was showing [object Object]
because the formatter sent a fat object as msg.payload and the format
template tried to access sub-fields.

Fix: per-pump (and per-MGC, per-PS) "dispatcher" function on the
Dashboard UI tab. The dispatcher receives the fat object via one
link-in, then returns 7-9 plain-string outputs — one per ui-text
widget — each with msg.payload set to the formatted string value.
Outputs 8+9 carry numeric values (flowNum/powerNum) tagged with
msg.topic for the trend charts, wired directly to both short-term
and long-term chart nodes.

Pattern documented as the recommended approach in the rule set:
"FlowFuse ui-text receives plain strings only — use a dispatcher
function to split a fat object into per-widget outputs."

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:54:02 +02:00
znetsixe
d439b048f2 docs: add CLAUDE.md to all 11 node submodules — S88 classification + rule reference
Some checks failed
CI / lint-and-test (push) Has been cancelled
Each node repo now has a CLAUDE.md that declares its S88 hierarchy
level (Control Module / Equipment Module / Unit / Process Cell), the
associated S88 colour, and the placement lane per the superproject's
flow-layout rule set (.claude/rules/node-red-flow-layout.md).

The rule set lives in the superproject only (single source of truth).
Per-node repos reference it. When Claude Code opens a node repo, it
reads the local CLAUDE.md and knows which lane / colour / group to
use when building a multi-node demo or production flow.

Submodule pointer bumps for all 11 nodes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:48:37 +02:00
znetsixe
e280d87e6a fix(dashboard): split trends into 3 pages + fix chart dimensions
Some checks failed
CI / lint-and-test (push) Has been cancelled
Dashboard was a single page — 30+ widgets + tiny charts competing for
space. Trends were invisible or very small (width/height both "0"
meant "inherit from group" which gave near-zero chart area).

Split into 3 dashboard pages:
  1. Control — Process Demand, Station Controls, MGC/Basin status,
     per-pump panels (unchanged, just moved off trend groups)
  2. Trends — 10 min — rolling 10-minute flow + power charts with
     width=12 (full group), height=8 (tall charts), 300 max points
  3. Trends — 1 hour — same layout with 60-minute window, 1800 points

All 3 pages auto-nav via the FlowFuse sidebar. Same data feed: the
per-pump trend_split function now wires to 4 charts (2 outputs × 2
pages) instead of 2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:46:51 +02:00
znetsixe
64944aa9d8 docs(rules): add S88-hierarchical placement rules for Node-RED flows
Some checks failed
CI / lint-and-test (push) Has been cancelled
Sections 10-16 extend the existing flow-layout rule with a deterministic
lane-and-group convention anchored in the S88 hierarchy:

- 8 logical lanes: L0 inputs -> L1 adapters -> L2 CM -> L3 EM -> L4 UN
  -> L5 PC -> L6 formatters -> L7 outputs. 240 px between lanes.
- Lane assignment is by S88 level, not by node name. New nodes inherit
  a lane via a NODE_LEVEL registry, no rule change needed.
- Every parent + its direct children is wrapped in a Node-RED group box
  coloured by the parent's S88 level (Pump A = EM blue, MGC = Unit blue,
  PS = Process Cell blue, ...). Search the parent's name -> group
  highlights.
- Utility clusters (mode broadcast, station-wide commands, demand
  fan-out) use neutral-grey group boxes.
- Dashboard / setup / demo-driver tabs each get a variant of the rule.
- Spacing constants, place() and wrap_in_group() helpers, an 8-step
  verification checklist.

Off-spec colours (settler orange, monster teal, diffuser and
dashboardAPI missing) are flagged in Section 16 as a follow-up cleanup.
The NODE_LEVEL registry already maps those nodes to their semantic S88
level regardless of what the node's own colour currently says.

Rule lives in the superproject only; per-node repos will reference it
from their own CLAUDE.md files (separate commits per submodule).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 17:31:57 +02:00
znetsixe
0d7af6bfff refactor(examples): split pumpingstation demo across 4 concern-based tabs + add layout rule set
Some checks failed
CI / lint-and-test (push) Has been cancelled
The demo was a single 96-node tab with everything wired directly. Now
4 tabs wired only through named link-out / link-in pairs, and a
permanent rule set for future Claude sessions to follow.

Tabs (by concern, not by data flow):

  🏭 Process Plant   only EVOLV nodes (3 pumps + MGC + PS + 6 measurements)
                     + per-node output formatters
  📊 Dashboard UI   only ui-* widgets, button/setpoint wrappers, trend
                     splitters
  🎛️ Demo Drivers   random demand generator + state holder. Removable
                     in production
  ⚙️ Setup & Init   one-shot deploy-time injects (mode, scaling,
                     auto-startup, random-on)

Cross-tab wiring uses a fixed named-channel contract (cmd:demand,
cmd:mode, cmd:setpoint-A, evt:pump-A, etc.) — multiple emitters can
target a single link-in for fan-in, e.g. both the slider and the random
generator feed cmd:demand.

Bug fixes folded in:

1. Trend chart was empty / scrambled. Root cause: the trend-feeder
   function had ONE output that wired to BOTH flow and power charts,
   so each chart received both flow and power msgs and the legend
   garbled. Now: 2 outputs (flow → flow chart, power → power chart),
   one msg per output.

2. Every ui-text and ui-chart fell on the (0, 0) corner of the editor
   canvas. Root cause: the helper functions accepted x/y parameters
   but never assigned them on the returned node dict — Node-RED
   defaulted every widget to (0, 0) and they piled on top of each
   other. The dashboard render was unaffected (it lays out by group/
   order), but the editor was unreadable. Fixed both helpers and added
   a verification step ("no node should be at (0, 0)") to the rule set.

Spacing convention (now codified):
- 6 lanes per tab at x = [120, 380, 640, 900, 1160, 1420]
- 80 px standard row pitch, 30-40 px for tight ui-text stacks
- 200 px gap between sections, with a comment header per section

New rule set: .claude/rules/node-red-flow-layout.md
- Tab boundaries by concern
- Link-channel naming convention (cmd:/evt:/setup: prefixes)
- Spacing constants
- Trend-split chart pattern
- Inject node payload typing pitfall (per-prop v/vt)
- Dashboard widget rules (every ui-* needs x/y!)
- Do/don't checklist
- Link-out/link-in JSON cheat sheet
- 5-step layout verification before declaring a flow done

CLAUDE.md updated to point at the new rule set.

Verified end-to-end on Dockerized Node-RED 2026-04-13: 168 nodes across
4 tabs, all wired via 22 link-out / 19 link-in pairs, no nodes at
(0, 0), pumps reach operational ~5 s after deploy, MGC distributes
random demand, trends populate per pump.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:13:27 +02:00
znetsixe
7aacee6482 feat(examples): pumpingstation-3pumps-dashboard end-to-end demo + bump generalFunctions
Some checks failed
CI / lint-and-test (push) Has been cancelled
New top-level examples/ folder for end-to-end demos that show how multiple
EVOLV nodes work together (complementing the per-node example flows under
nodes/<name>/examples/). Future end-to-end demos will live as siblings.

First demo: pumpingstation-3pumps-dashboard
- 1 pumpingStation (basin model, manual mode for the demo so it observes
  rather than auto-shutting pumps; safety guards disabled — see README)
- 1 machineGroupControl (optimalcontrol mode, absolute scaling)
- 3 rotatingMachine pumps (hidrostal-H05K-S03R curve)
- 6 measurement nodes (per pump: upstream + downstream pressure mbar,
  simulator mode for continuous activity)
- Process demand input via dashboard slider (0-300 m3/h) AND auto random
  generator (3s tick, [40, 240] m3/h) — both feed PS q_in + MGC Qd
- Auto/Manual mode toggle (broadcasts setMode to all 3 pumps)
- Station-wide Start / Stop / Emergency-Stop buttons
- Per-pump setpoint slider, individual buttons, full status text
- Two trend charts (flow per pump, power per pump)
- FlowFuse dashboard at /dashboard/pumping-station-demo

build_flow.py is the source of truth — it generates flow.json
deterministically and is the right place to extend the demo.

Bumps:
  nodes/generalFunctions  43f6906 -> 29b78a3
    Fix: childRegistrationUtils now aliases the production
    softwareType values (rotatingmachine, machinegroupcontrol) to the
    dispatch keys parent nodes check for (machine, machinegroup). Without
    this, MGC <-> rotatingMachine and pumpingStation <-> MGC wiring
    silently never matched in production even though tests passed.
    Demo confirms: MGC reports '3 machine(s) connected'.

Verified end-to-end on Dockerized Node-RED 2026-04-13: pumps reach
operational ~5s after deploy, MGC distributes random demand across them,
basin tracks net flow direction, all dashboard widgets update each second.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:53:47 +02:00
znetsixe
d7d106773e chore: bump generalFunctions submodule — fix asset menu supplier->type->model cascade
Some checks failed
CI / lint-and-test (push) Has been cancelled
generalFunctions: e50be2e -> 43f6906

Fixes the bug where picking a supplier and then a type left the model
dropdown stuck on "Awaiting Type Selection". Affects every node that
uses the shared assetMenu (measurement, rotatingMachine, pumpingStation,
monster, …). The chained dropdowns now use an explicit downward
cascade with no synthetic change-event dispatch, so the parent handler
can no longer wipe a child after the child was populated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:51:02 +02:00
znetsixe
89f3b5ddc4 chore: bump measurement submodule — fix asset menu render (TDZ ReferenceError)
Some checks failed
CI / lint-and-test (push) Has been cancelled
measurement: d6f8af4 -> <new>

Fixes a regression in the previous measurement editor commit where a
const Temporal Dead Zone error in oneditprepare aborted the function
before the asset / logger / position menu init ran. Menus are now
kicked off first, mode logic is guarded with try/catch and null-checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:15:11 +02:00
znetsixe
d0fe4d0583 chore: bump measurement submodule — editor UX fix (mode as top-level switch)
Some checks failed
CI / lint-and-test (push) Has been cancelled
measurement: 495b4cf -> d6f8af4

Makes Input Mode the top-level hierarchy in the editor: analog-only and
digital-only field blocks toggle visibility live based on the dropdown,
legacy nodes default to 'analog', channels JSON gets live validation,
and runtime logs an actionable warning when the payload shape doesn't
match the selected mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:00:44 +02:00
znetsixe
0300a76ae8 docs: measurement trial-ready — digital mode + dispatcher fix + 71 tests
Some checks failed
CI / lint-and-test (push) Has been cancelled
Bumps:
- nodes/generalFunctions  75d16c6 -> e50be2e  (permissive unit check + measurement schema additions)
- nodes/measurement       f7c3dc2 -> 495b4cf  (digital mode + dispatcher fix + 59 new tests + rewritten README + UI)

Wiki:
- wiki/manuals/nodes/measurement.md — new user manual covering analog and
  digital modes, topic reference, smoothing/outlier methods, unit policy,
  and the pre-fix dispatcher bug advisory.
- wiki/sessions/2026-04-13-measurement-digital-mode.md — session note with
  findings, fix scope, test additions, and dual-mode E2E results.
- wiki/index.md — links both pages and adds the missing 2026-04-13
  rotatingMachine session entry that was omitted from the earlier commit.

Status: measurement is now trial-ready in both analog and digital modes.
71/71 unit tests green (was 12), dual-mode E2E on live Dockerized
Node-RED verifies analog regression and a three-channel MQTT-style
payload (temperature/humidity/pressure) dispatching independently with
per-channel smoothing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:46:00 +02:00
znetsixe
a1aa44f6ca docs: rotatingMachine trial-ready — submodule bumps, wiki manual, session note
Some checks failed
CI / lint-and-test (push) Has been cancelled
Bumps:
- nodes/generalFunctions  024db55 -> 75d16c6  (FSM abort recovery + schema sync)
- nodes/rotatingMachine   07af7ce -> 17b8887  (interruptible sequences, dual-curve tests, rewritten README)

Wiki:
- wiki/manuals/nodes/rotatingMachine.md — new user manual covering inputs,
  outputs, state machine, supported curves, and troubleshooting.
- wiki/sessions/2026-04-13-rotatingMachine-trial-ready.md — session note
  with findings, fixes, test additions, and dual-curve E2E results.
- wiki/index.md — link both and bump updated date.

Status: rotatingMachine is now trial-ready. 91/91 unit tests green, live
Docker E2E verifies shutdown/emergency-stop during ramps and prediction
behaviour across both shipped pump curves (hidrostal-H05K-S03R,
hidrostal-C5-D03R-SHN1).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 13:22:10 +02:00
znetsixe
6cf1821161 chore: remove redundant Makefile and .npmignore, fix .dockerignore
Some checks failed
CI / lint-and-test (push) Has been cancelled
- Makefile: all useful targets duplicate package.json scripts, and
  referenced deleted e2e files. Use npm run instead.
- .npmignore: contained only node_modules/ which npm ignores by default.
- .dockerignore: remove stale paths (manuals/, third_party/, AGENTS.md,
  FUNCTIONAL_ISSUES_BACKLOG.md), add wiki/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 20:53:26 +02:00
znetsixe
48f790d123 chore: clean up superproject structure
Some checks failed
CI / lint-and-test (push) Has been cancelled
Move content to correct locations:
- AGENTS.md → .agents/AGENTS.md (with orchestrator reference update)
- third_party/docs/ (8 reference docs) → wiki/concepts/
- manuals/ (12 Node-RED docs) → wiki/manuals/

Delete 23 unreferenced one-off scripts from scripts/ (keeping 5 active).
Delete stale Dockerfile.e2e, docker-compose.e2e.yml, test/e2e/.
Remove empty third_party/ directory.

Root is now: README, CLAUDE.md, LICENSE, package.json, Makefile,
Dockerfile, docker-compose.yml, docker/, scripts/ (5), nodes/, wiki/,
plus dotfiles (.agents, .claude, .gitea).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:01:04 +02:00
znetsixe
bac6c620b1 docs: rewrite README with actual project content
Some checks failed
CI / lint-and-test (push) Has been cancelled
Replace generic Dutch template (with placeholder text) with a proper
README showing: node inventory table, architecture summary, install
instructions, test commands, documentation links, and license.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:25:03 +02:00
znetsixe
7ded2a4415 docs: consolidate scattered documentation into wiki
Some checks failed
CI / lint-and-test (push) Has been cancelled
Move architecture/, docs/ content into wiki/ for a single source of truth:
- architecture/deployment-blueprint.md → wiki/architecture/
- architecture/stack-architecture-review.md → wiki/architecture/
- architecture/wiki-platform-overview.md → wiki/architecture/
- docs/ARCHITECTURE.md → wiki/architecture/node-architecture.md
- docs/API_REFERENCE.md → wiki/concepts/generalfunctions-api.md
- docs/ISSUES.md → wiki/findings/open-issues-2026-03.md

Remove stale files:
- FUNCTIONAL_ISSUES_BACKLOG.md (was just a redirect pointer)
- temp/ (stale cloud env examples)

Fix README.md gitea URL (centraal.wbd-rd.nl → wbd-rd.nl).
Update wiki index with all consolidated pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:08:35 +02:00
znetsixe
6d19038784 docs: initialize project wiki from production hardening session
12 pages covering architecture, findings, and metrics from the
rotatingMachine + machineGroupControl hardening work:

- Overview: node inventory, what works/doesn't, current scale
- Architecture: 3D pump curves, group optimization algorithm
- Findings: BEP-Gravitation proof (0.1% of optimum), NCog behavior,
  curve non-convexity, pump switching stability
- Metrics: test counts, power comparison table, performance numbers
- Knowledge graph: structured YAML with all data points and provenance
- Session log: 2026-04-07 production hardening
- Tools: query.py, search.sh, lint.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 16:36:08 +02:00
znetsixe
fd9d1679cb fix: update submodule refs — production hardening for rotatingMachine and machineGroupControl
rotatingMachine:
- Safety fixes: async input handler, emergencyStop case fix, null guards,
  listener cleanup, tick loop race condition, editor timeout
- Prediction: remove efficiency rounding (was breaking NCog/BEP), fix
  variant reads, curve anomaly detection
- 43 new tests (76 total)

machineGroupControl:
- Critical: fix flowmovement unit mismatch (m³/s sent where m³/h expected,
  pumps never moved from minimum)
- Fix absolute scaling comparison bug, empty Qd block, empty-machines guards
- Add marginal-cost refinement loop: reduces gap to brute-force optimum
  from 2.1% to <0.1%
- 2 new test files with NCog distribution and power comparison tests

generalFunctions:
- Fix 3 anomalous power values in hidrostal-H05K-S03R curve data

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 13:41:22 +02:00
znetsixe
4336002b77 fix: update submodule refs with bug fixes for validateSchema recursion and nodeClass syntax
Some checks failed
CI / lint-and-test (push) Has been cancelled
- generalFunctions: fix infinite recursion in validateSchema when version string is in schema
- rotatingMachine: fix missing closing brace in emergencystop case block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 08:46:34 +02:00
znetsixe
f57343f5e3 Update submodule refs after merge with main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 18:29:31 +02:00
znetsixe
65ceb696ab Merge remote-tracking branch 'origin/main' into dev-rene
# Conflicts:
#	.dockerignore
#	.gitmodules
#	Dockerfile
#	docker-compose.yml
#	nodes/generalFunctions
#	nodes/machineGroupControl
#	nodes/measurement
#	nodes/monster
#	nodes/pumpingStation
#	nodes/reactor
#	nodes/rotatingMachine
#	nodes/settler
#	package-lock.json
#	package.json
2026-03-31 18:29:03 +02:00
root
91a298960c Prepare reactor, diffuser, and settler updates for mainline merge 2026-03-31 14:26:33 +02:00
znetsixe
1c4a3f9685 Add deployment blueprint 2026-03-23 11:54:24 +01:00
znetsixe
9ca32dddfb Extend architecture review with security positioning 2026-03-23 11:35:40 +01:00
znetsixe
75458713be Add architecture review and wiki draft 2026-03-23 11:23:24 +01:00
Rene De Ren
35221fc5dd Sync pushed submodule refs
Some checks failed
CI / lint-and-test (push) Has been cancelled
2026-03-12 16:47:08 +01:00
Rene De Ren
93a5b6a90e Expose output format controls across node editors 2026-03-12 16:39:54 +01:00
Rene De Ren
1d98670706 Validate diffuser through the full stack 2026-03-12 16:32:25 +01:00
Rene De Ren
a432eea7fe Track config-driven output formatting support 2026-03-12 16:13:47 +01:00
Rene De Ren
9cb3657bae Track dashboardapi buildConfig adoption 2026-03-12 16:11:10 +01:00
Rene De Ren
bd9432eebb Validate dashboardapi round-trip through Node-RED 2026-03-12 11:40:37 +01:00
Rene De Ren
c9bacb64c8 Add monster coverage and stack validation 2026-03-12 10:32:09 +01:00
Rene De Ren
e580c93c84 docs: add open issues from codebase scan
Tracked issues for diffuser restoration, ML module relocation,
monster architecture modernization, test code cleanup, and dashboardAPI improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:34:51 +01:00
Rene De Ren
b02306c42f fix: codebase scan — bug fixes, security, logging consistency, monster modernization
- generalFunctions: add missing migrateConfig(), config versioning, formatters module
- rotatingMachine: fix eneableLog typo, correct child registration ID
- machineGroupControl: console.log → structured logger
- settler/reactor: console.log → logger, throw on unknown reactor type
- monster: modernize imports to require('generalFunctions'), remove broken
  TensorFlow code, add childRegistrationUtils, consolidate input handlers
- dashboardAPI: remove hardcoded Grafana bearer token, use logger

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:33:52 +01:00
Rene De Ren
2c76430394 feat: working E2E container stack with Node-RED + InfluxDB + Grafana
- Fix Dockerfile.e2e to install EVOLV properly in Node-RED /data/
- Add measurement node E2E test flow with scaling (4-20mA to 0-5m)
- Add Grafana health check to run-e2e.sh
- Guard pumpingStation demo IIFE with require.main check
- All 10 EVOLV nodes load successfully in containerized Node-RED

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:38:14 +01:00