Files
valveGroupControl/wiki/Reference-Limitations.md
znetsixe 9552e4fba9 docs(wiki): full 5-page wiki matching the rotatingMachine reference format
Replaces the prior stub/partial wiki with a Home + Reference-{Architecture,
Contracts,Examples,Limitations} + _Sidebar structure. Topic-contract and
data-model sections wrapped in AUTOGEN markers for the future wiki-gen tool.
Source-vs-spec contradictions surfaced and flagged inline (not silently
fixed). Pending-review notes mark sections that need a full node review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 09:42:12 +02:00

9.7 KiB

Reference — Limitations

code-ref

Note

Pending full node review (2026-05). Content reflects CONTRACT.md and current source only.

What valveGroupControl does not do, current rough edges, and open questions. Open items live in .agents/improvements/IMPROVEMENTS_BACKLOG.md in the superproject.


When you would not use this node

Scenario Use instead
A single valve under one upstream parent valve — VGC adds coordination overhead for no benefit with one child.
Valves in series rather than parallel The Kv-share solver assumes parallel branches sharing a common header pressure. Series valves need their own coordination model.
Upstream already publishes per-branch flow setpoints Route the per-branch setpoints directly to each valve — VGC's group-level redistribution would discard the upstream split.
Curve-based pumps grouped on a manifold machineGroupControl — that's the pump-side equivalent (BEP-aware optimizer + planner). VGC has no curves and no optimizer.

Legacy file-naming drift

The entry file and editor HTML still use the abbreviated vgc.{js,html} filenames:

Path Currently Should be
Entry file vgc.js valveGroupControl.js
Editor HTML vgc.html valveGroupControl.html

Per the EVOLV folder-naming convention (.claude/rules/node-architecture.md and CLAUDE.md), every per-node file MUST match the folder name exactly — no abbreviations. The rename is queued for the next touch:

files to update in one commit:
  - rename vgc.js → valveGroupControl.js
  - rename vgc.html → valveGroupControl.html
  - update package.json#node-red.nodes (currently maps "valveGroupControl": "vgc.js")
  - update any require() / import paths
  - update superproject submodule references

Sibling drift: machineGroupControl/mgc.{js,html} and dashboardAPI/dashboardapi.{js,html} are in the same state. See .claude/refactor/MODULE_SPLIT.md.


Known limitations

set.position is a no-op

commands/handlers.setPosition intentionally does nothing — the handler debug-logs the payload and returns. Per-valve positional override is reserved pending Phase 7 topic standardisation of valve setpoint payloads. The canonical topic and alias are reserved so callers can't squat them in the meantime.

Workaround: route the position setpoint to the individual valve node directly.

isValidActionForMode is not implemented

The schema declares mode.allowedActions.<mode> (statusCheck / execSequence / emergencyStop / valvePositionChange / totalFlowChange / valveDeltaPchange), but specificClass.handleInput only consults isValidSourceForMode. The action allow-list is effectively dead config. Source contradiction with CONTRACT.md which implies action gating is active.

Workaround: rely on the source allow-list for now. TODO: implement the action check (mirror rotatingMachine's pattern) OR strip allowedActions from the schema.

calculationMode is not consulted

Schema field calculationMode (low / medium / high) is declared but ignored by both specificClass and nodeClass. The tick interval is fixed at tickInterval = 1000 ms and only re-tunable via set.reconcileInterval. TODO: wire it through or remove.

mode.allowedSources.maintenance is undefined

The maintenance mode is enumerated in mode.current and mode.allowedActions, but mode.allowedSources only declares auto / virtualControl / fysicalControl. isValidSourceForMode('any', 'maintenance') returns false for every source — effectively monitoring-only. This may be intentional, but it's not stated explicitly in any contract.

Residual solver assumes Kv share is a valid first estimate

Pathological valve curves (very non-linear Kv vs position) may need more passes than the default maxPasses: 2 to reach residualTolerance: 0.001. The loop exits gracefully but lastFlowSolve.residual carries the gap; flow.predicted.atEquipment reads only the sum of what was accepted.

There is no editor field for flowReconciliation — it's a runtime-only object. TODO: expose maxPasses / residualTolerance in the editor.

Cascaded VGC not test-covered

valvegroupcontrol is in SOURCE_SOFTWARE_TYPES and _registerSource accepts it, so VGC-on-VGC cascades are wired by the router. But:

  • No integration tests cover the case.
  • No production deployments use it.
  • Fluid-contract propagation across two VGCs hasn't been validated.

Treat as experimental. Open question whether to remove the entry or harden it.

Multi-source aggregation is "last write wins" on shared positions

If two upstream sources both publish flow.predicted.atEquipment to the same VGC, the later write replaces the earlier one in the measurement container. There is no merge / max / priority logic. In practice this is fine when one VGC has one upstream source; with two upstream sources the behaviour is well-defined but may surprise.

Source flow events listen on both case variants

SOURCE_FLOW_EVENTS includes both flow.predicted.atEquipment AND flow.predicted.atequipment. A source that emits the event twice (defensive code) will trigger updateFlow twice per change — harmless because the second call writes the same value, but it doubles the recompute. Open question whether to canonicalise the event name at the source.

No FSM — sequences depend on state being pre-stamped operational

specificClass.configure() does this.state.stateManager.currentState = 'operational' immediately so executeSequence('startup') etc. can run. This is unusual — other nodes go through boot to reach operational. The shortcut is intentional (VGC doesn't model the group as a stateful machine; sequences are pass-through to valves) but it means state.getCurrentState() always reads operational regardless of what the valves are doing.

No test/_output-manifest.md

Per .claude/rules/output-coverage.md every node should ship an output manifest with populated + degraded tests for each Port-0 / 1 / 2 key. Not yet produced for VGC. Backfill tracked in .agents/improvements/IMPROVEMENTS_BACKLOG.md.

Wiki source-of-truth contradictions found during this review

Source A Source B Issue TODO
CONTRACT.md set.mode payload "auto / manual" Schema enum auto / virtualControl / fysicalControl / maintenance; setMode validates against schema CONTRACT.md prose understates mode count Update CONTRACT.md.
Schema mode.allowedActions specificClass only consults isValidSourceForMode Action allow-list dead config Implement or remove (see above).
Schema calculationMode specificClass / nodeClass never read it Dead config Implement or remove.
CONTRACT.md § Children: valve, machine / rotatingmachine / machinegroup / machinegroupcontrol / pumpingstation / valvegroupcontrol specificClass.SOURCE_SOFTWARE_TYPES lists post-canonicalisation names only (machine, machinegroup, pumpingstation, valvegroupcontrol) Pre-canonical aliases (rotatingmachine, machinegroupcontrol) are accepted by the router because BaseDomain normalises them — contract text remains correct in spirit None — informational.
examples/README.md lists 3 flows with stub descriptions Actual flow content not validated against current source Tier labelling missing; live-deploy validation outstanding Backfill validation; rename to Tier-1/2/3 convention.

Open questions (tracked)

Question Where it lives
Phase 7 standardisation of valve setpoint payloads (unblocks set.position) OPEN_QUESTIONS.md Phase 7
Should flowReconciliation.maxPasses / residualTolerance be editor-configurable? Internal — not yet ticketed
Cascaded valvegroupcontrol as upstream source — harden or remove? Internal
Multi-source priority / merge strategy for shared positions Internal
Wire calculationMode through or strip from schema Internal
Implement isValidActionForMode or strip allowedActions from schema Internal
Output-coverage backfill (test/_output-manifest.md + populated/degraded tests) .agents/improvements/IMPROVEMENTS_BACKLOG.md
Rename vgc.{js,html}valveGroupControl.{js,html} .claude/refactor/MODULE_SPLIT.md
Validate example flows against live Node-RED; rename to Tier-1/2/3 convention Internal

Migration notes

From setpoint topic name (pre-canonical)

The old setpoint alias for set.position still works but logs a one-time deprecation warning. Switch to set.position — though note the handler is currently a no-op (see above).

From setMode / registerChild / execSequence / totalFlowChange / emergencyStop / emergencystop / setReconcileInterval aliases

Every legacy alias emits a one-time deprecation warning. Switch to the canonical topic names listed in Contracts.


Page Why
Home Intuitive overview
Reference — Contracts Topic + config + child filters (alias map)
Reference — Architecture Code map, flow-distribution loop, source aggregation
Reference — Examples Shipped flows + debug recipes
machineGroupControl — Limitations Sibling Unit-level controller's known limitations
valve wiki The child node VGC coordinates