Files
settler/wiki/Reference-Limitations.md
znetsixe d54cb66105 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

8.4 KiB
Raw Blame History

Reference — Limitations

code-ref

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 712 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.

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 stateChangeF_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 undefinedMath.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:

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.


Page Why
Home Intuitive overview
Reference — Contracts Topic + config + child filters
Reference — Architecture Code map, reactor ↔ settler wiring, mass-balance math
Reference — Examples Shipped flows + the TODO list for production-grade demos
reactor — Limitations The upstream parent — effluent shape contract
EVOLV — output-coverage rule Platform-wide output-coverage requirement