# Reference — Limitations ![code-ref](https://img.shields.io/badge/code--ref-8c2b2c0-blue) > [!NOTE] > What `valve` does not do, current rough edges, and open questions. Open items live in `.agents/improvements/IMPROVEMENTS_BACKLOG.md` in the superproject. > > Pending full node review (2026-05). Content reflects `CONTRACT.md` and current source only. --- ## When you would not use this node | Scenario | Use instead | |:---|:---| | A fixed-restriction orifice (no actuator, no curve) | Model the deltaP externally; valve assumes a position-controlled Kv lookup. | | A non-return / check valve (no motorised actuation) | Don't use valve — no FSM-driven position control is exposed for this case. | | A pump or compressor (rotating equipment on a Q–H curve) | `rotatingMachine` — it loads a flow / power curve and predicts the operating point. | | A throttling device with no known Kv curve | Without `asset.valveCurve` or a registry-resolved model, the predictor stays empty and deltaP recomputes return null. There is no fallback hydraulic model. | | A grouped valve manifold | `valveGroupControl` — instantiate this as a child. | --- ## Known limitations ### Gas-choke detection is a hard cap `hydraulicModel.js` `_calculateGasDeltaP` caps the effective deltaP at `gasChokedRatioLimit * P2_abs` once the raw deltaP exceeds that threshold. The result is a discontinuous step in deltaP — chart traces show a sharp ceiling rather than a smooth choked-flow transition. The `isChoked` flag in `hydraulicDiagnostics` lets consumers detect the regime. Tracked. ### Single-source pressure for the deltaP recompute `MeasurementRouter` looks for `pressure.measured.downstream` (preferred) or `pressure.predicted.downstream` to feed the gas-flow formula. There is no fallback if both are missing — the hydraulic model returns `null` and `delta_predicted_pressure` simply doesn't get written. The liquid-flow path doesn't need downstream pressure. Tracked. ### Multi-parent registration Allowed but not exercised in production tests. valve overrides `BaseDomain.registerChild` with `FluidCompatibility.registerChild`, which records upstream sources and aggregates `serviceType`. Teardown ordering (parent gone first vs valve gone first) is not test-covered. Open question. ### `flowController.handleInput` only gates by source, not action The schema's `mode.allowedActions` is defined but `flowController.handleInput` only enforces `isValidSourceForMode`. A `cmd.shutdown` from a source allowed for the current mode will fire regardless of whether the schema lists `execSequence` in `allowedActions[mode]`. This differs from `rotatingMachine`, which gates both. TODO: confirm whether this is intentional (valve's reduced operational set) or a backlog item. ### `execSequence` legacy umbrella The `execSequence` topic (with `payload.action = 'startup' | 'shutdown' | 'emergencystop'`) is kept alive for legacy flows. The handler demuxes to the canonical topic; the deprecation warning fires once per session. Scheduled for removal in Phase 7. Use `cmd.startup` / `cmd.shutdown` / `cmd.estop` instead. ### `data.flow` payloads don't clear stale values If a flow source stops emitting, the last-known value persists in MeasurementContainer. There is no TTL and no explicit clear topic. Workaround: send `value: 0` explicitly. The deltaP recompute then writes 0 (or `null` if it short-circuits on `flow === 0`). Tracked. ### Editor cosmetics don't reflect `asset` derivation The editor form may still expose supplier / category / type fields even though `_rejectLegacyAssetFields` rejects them on save. Re-saving an old flow surfaces the legacy-fields error until each valve is re-opened and the model re-picked. Cosmetic; the registry is the source of truth. ### No `entermaintenance` / `exitmaintenance` sequences out of the box `valve.json` ships `startup` / `shutdown` / `emergencystop` / `boot` sequences only. `maintenance` is reachable via `set.mode = maintenance`, but there is no canned state-transition sequence for entering / leaving. `rotatingMachine` defines these in its own config — valve does not. TODO: confirm intentional. ### Position residue handling depends on shared state machine The residue handler that lets a mid-decel `set.position` re-engage cleanly lives in `generalFunctions/src/state/state.js` `moveTo`. valve inherits the behaviour but the integration test coverage is thin. The sequence-abort token mechanism (`rotatingMachine`, 2026-05-15) may or may not apply to valve's shutdown ramp; TODO: confirm from `FlowController.executeSequence` behaviour when a new `set.position` arrives during the pre-shutdown ramp-to-zero. --- ## Open questions (tracked) | Question | Where it lives | |:---|:---| | Gate `mode.allowedActions` in `flowController.handleInput` for parity with `rotatingMachine`? | Internal | | Add `entermaintenance` / `exitmaintenance` sequences to `valve.json`? | Internal | | Multi-parent teardown ordering | Internal | | Add an explicit `data.clear-flow` topic for stale flow cleanup | Internal | | Smooth choked-flow transition instead of a hard cap | `hydraulicModel.js` | | Does the sequence-abort token mechanism (rotatingMachine, 2026-05-15) apply to valve's pre-shutdown ramp? | Internal — flagged in [Architecture](Reference-Architecture#fsm) | | Phase 7 removal of `execSequence` umbrella + legacy aliases | Internal | | `calculationMode` (`low` / `medium` / `high`) — does the dispatch path consult it? | `valve.json` schema vs source | --- ## Migration notes ### From pre-AssetResolver Old flows saved with `supplier`, `category`, or `assetType` fields will throw on deploy: ``` valve: legacy asset field(s) [supplier, category] are saved on this node. After the AssetResolver refactor these are derived from the model id. Open the node in the editor, re-select the model, and save to migrate. ``` The fix is mechanical: open each valve node, re-pick the model from the asset menu, save. No data is lost — the registry has the same supplier / category / type the old flow carried. ### From inline `valveCurve` only valve still supports `asset.valveCurve` as a fully inline curve fallback when no `asset.model` is set. The predictor logs which `(densityKey, diameterKey)` lane of the dataset it selected. If you migrate from inline-only to a registry-resolved model, the curve may pick a slightly different lane and your operating-point predictions will shift — review on the dashboard before declaring done. ### From `setpoint` topic name (pre-canonical) The old topic without a `set.` prefix has been retired. Use `set.position` (alias `execMovement`) for position setpoints. --- ## Related pages | Page | Why | |:---|:---| | [Home](Home) | Intuitive overview | | [Reference — Contracts](Reference-Contracts) | Topic + config + child filters | | [Reference — Architecture](Reference-Architecture) | Code map, FSM, hydraulic-model pipeline | | [Reference — Examples](Reference-Examples) | Shipped flows + debug recipes | | [valveGroupControl — Limitations](https://gitea.wbd-rd.nl/RnD/valveGroupControl/wiki/Reference-Limitations) | Where the parent's aggregator sits |