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>
117 lines
8.4 KiB
Markdown
117 lines
8.4 KiB
Markdown
# Reference — Limitations
|
|
|
|

|
|
|
|
> [!NOTE]
|
|
> Pending full node review (2026-05). What `settler` 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 |
|
|
|:---|:---|
|
|
| Primary sedimentation upstream of biological treatment | The species 7–12 zeroing in the effluent stream is wrong for primary sludge (the soluble / particulate split is different). Model as a separate node. |
|
|
| Generic mass-balance transform | The 13-species ASM3 concentration vector is hard-coded; `Cs[12]` (`X_TS`) is the only species the split is keyed off. Not a fit for arbitrary stream-splitting. |
|
|
| Single-tank SBR with no separation stage | The 3-stream output expects a downstream consumer that routes by `payload.inlet`. A direct reactor → reactor wire is lighter. |
|
|
| A reactor — you want to model biological transformation, not separation | `reactor` (settler is a passive separator, not a biological process). |
|
|
| A return-pump itself — you want to model the pump's behaviour | `rotatingMachine` (settler reads the pump's measured flow but does not control it). |
|
|
|
|
---
|
|
|
|
## Known limitations
|
|
|
|
### Example flows are stub level
|
|
|
|
The three shipped flows (`basic.flow.json`, `integration.flow.json`, `edge.flow.json`) are 4-node skeletons (tab + node + inject + debug). They prove the node loads in Node-RED but do not exercise the reactor → settler → pump chain, do not drive `data.influent` with a valid payload, and do not have a dashboard tier. Production-grade examples are TODO — see [Reference — Examples — TODO](Reference-Examples#todo--production-grade-example-set).
|
|
|
|
### Editor colour drift
|
|
|
|
`settler.html` declares `color: '#e4a363'` (orange). The S88 Unit level requires `#50a8d9` (blue). The placement-rule registry (`.claude/rules/node-red-flow-layout.md` §14) already maps `settler` to the `UN` lane regardless of editor colour, so demos lay out correctly; the cosmetic mismatch is tracked in §16 of the same rule and is on the colour-cleanup list. The wiki diagrams use the correct blue.
|
|
|
|
### Single-reactor upstream slot
|
|
|
|
`this.upstreamReactor` is a single slot. Registering a second `reactor` child with `positionVsParent='upstream'` silently overwrites the first — the listener on the previous reactor's `emitter` is not detached, so it keeps firing into a settler that will pull effluent from the new reactor instead. Tracked.
|
|
|
|
### `X_TS` index is hard-coded
|
|
|
|
The mass balance uses `Cs_in[12]` (the ASM3 `X_TS` lumped solids species) as the surrogate for total suspended solids. Any change to the species ordering in the upstream reactor breaks settler. The coupling is not documented in the schema — it lives only in the `getEffluent` math and the `_updateMeasurement` switch case for `quantity (tss)`. Tracked.
|
|
|
|
### No flow-balance warning
|
|
|
|
When influent solids exceed the target return concentration (`Cs_in[12] > C_TS`), `F_s` is clamped to `F_in` and clarified effluent drops to zero. This is mathematically correct but masks an upstream problem (overloaded reactor, miscalibrated `C_TS` setpoint). The clamp fires silently — no warn, no badge change beyond the eventual `F_in <= 0` idle state. Operator must monitor `F_eff` directly. Tracked.
|
|
|
|
### `quantity (tss)` measurement passes through but doesn't validate
|
|
|
|
`_connectMeasurement` re-emits every measurement type, but `_updateMeasurement` only acts on `quantity (tss)`. Other types log an `error` (`Type '<x>' not recognized for measured update.`) but the re-emit already happened — the parent of settler still sees the value. Whether this is desired (settler acts as telemetry pass-through) or a contract gap is unresolved.
|
|
|
|
> [!NOTE]
|
|
> Pending full node review (2026-05). Open question: should `_connectMeasurement` filter by asset-type at register time and reject non-`quantity (tss)` children, or continue accepting everything as pass-through telemetry?
|
|
|
|
### No output manifest / no degraded-state coverage
|
|
|
|
Per the platform output-coverage rule (`.claude/rules/output-coverage.md`), every node needs a `test/_output-manifest.md` enumerating every Port 0 / 1 / 2 key and a `test/basic/output-*.test.js` exercising each one in both populated **and** degraded states. Settler has neither. The most likely degraded-state crash points:
|
|
|
|
- Port 0 emitted before any reactor `stateChange` — `F_in = 0`, `Cs_in = [0...]`, the three envelopes carry zero flow but valid (zero) `C` arrays. Should not crash a downstream consumer, but un-tested.
|
|
- Port 0 with `returnPump` registered but no flow measurement landed yet — `returnPump.measurements.type('flow').variant('measured').position('atEquipment').getCurrentValue()` returns `undefined` → `Math.min(undefined, F_s) = NaN`. `F_sr` becomes `NaN` → both `inlet=1` and `inlet=2` carry `NaN` flow.
|
|
|
|
Tracked. TODO before trial-readiness: add the manifest, tests, and `null`-flow-measurement handling.
|
|
|
|
### `reactor.getEffluent` shape coupling
|
|
|
|
`_connectReactor` does `Array.isArray(raw) ? raw[0] : raw` to absorb both the older single-envelope shape and the newer 3-stream array shape of `reactor.getEffluent`. The 2026-03-02 fix is the only thing keeping the older shape alive in production. If `reactor.getEffluent` ever returns a 3-stream array and settler should consume `inlet=0` specifically, the current `raw[0]` selector works by accident — it picks the first envelope regardless of inlet number. Open question whether to make the selection inlet-aware.
|
|
|
|
### Stateful telemetry — no decay / no TTL
|
|
|
|
The MeasurementContainer holds the last-known value of every re-emitted measurement forever. If a child stops publishing, the stale value persists on Port 1 indefinitely. There is no TTL, no `data.clear-measurement` topic, and no health flag like `rotatingMachine`'s `predictionQuality`. Open question.
|
|
|
|
---
|
|
|
|
## Open questions (tracked)
|
|
|
|
| Question | Where it lives |
|
|
|:---|:---|
|
|
| Filter `_connectMeasurement` by asset-type at register time? | Internal — not yet ticketed |
|
|
| Multi-reactor upstream support — teardown ordering, listener detach | Internal |
|
|
| Flow-balance warning when `F_s` clamp fires | Internal |
|
|
| Inlet-aware selection in `_connectReactor` shape handling | Internal |
|
|
| Measurement TTL / staleness flag | Internal |
|
|
| Production-grade example flows (Tier 1 / 2 / 3) | `.agents/improvements/IMPROVEMENTS_BACKLOG.md` |
|
|
| Output manifest + degraded-state tests | `.claude/rules/output-coverage.md` (platform-wide rule) |
|
|
| Editor colour cleanup (`#e4a363` → `#50a8d9`) | `.claude/rules/node-red-flow-layout.md` §16 |
|
|
|
|
---
|
|
|
|
## Migration notes
|
|
|
|
> [!NOTE]
|
|
> Pending full node review (2026-05). No structural migrations have been performed on settler since the AssetResolver refactor of rotatingMachine; the notes below document the one historical fix on record.
|
|
|
|
### From pre-2026-03-02 `_connectReactor`
|
|
|
|
Before 2026-03-02 `_connectReactor` assumed `reactor.getEffluent` always returned an array, and indexed `[0]` unconditionally. After the reactor refactor, `getEffluent` returns a single envelope — pre-fix settler would crash with `Cannot read properties of undefined (reading 'payload')`. The fix:
|
|
|
|
```js
|
|
const raw = this.upstreamReactor.getEffluent;
|
|
const effluent = Array.isArray(raw) ? raw[0] : raw;
|
|
```
|
|
|
|
If you maintain a fork of settler from before that date, port this guard.
|
|
|
|
### From topic-aliased payloads
|
|
|
|
Both `influent` and `setInfluent` are accepted as aliases for `data.influent`. A one-time deprecation warning fires the first time each alias is seen. Tracked for removal; use the canonical `data.influent` in new flows.
|
|
|
|
---
|
|
|
|
## Related pages
|
|
|
|
| Page | Why |
|
|
|:---|:---|
|
|
| [Home](Home) | Intuitive overview |
|
|
| [Reference — Contracts](Reference-Contracts) | Topic + config + child filters |
|
|
| [Reference — Architecture](Reference-Architecture) | Code map, reactor ↔ settler wiring, mass-balance math |
|
|
| [Reference — Examples](Reference-Examples) | Shipped flows + the TODO list for production-grade demos |
|
|
| [reactor — Limitations](https://gitea.wbd-rd.nl/RnD/reactor/wiki/Reference-Limitations) | The upstream parent — effluent shape contract |
|
|
| [EVOLV — output-coverage rule](https://gitea.wbd-rd.nl/RnD/EVOLV/src/branch/development/.claude/rules/output-coverage.md) | Platform-wide output-coverage requirement |
|