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>
9.7 KiB
Reference — Limitations
Note
Pending full node review (2026-05). Content reflects
CONTRACT.mdand current source only.What
valveGroupControldoes not do, current rough edges, and open questions. Open items live in.agents/improvements/IMPROVEMENTS_BACKLOG.mdin 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.
Related pages
| 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 |