128 lines
8.6 KiB
Markdown
128 lines
8.6 KiB
Markdown
|
|
# Reference — Limitations
|
||
|
|
|
||
|
|

|
||
|
|
|
||
|
|
> [!NOTE]
|
||
|
|
> What `monster` does not do, current rough edges, and open questions. Open items live in `.agents/improvements/IMPROVEMENTS_BACKLOG.md` in the superproject.
|
||
|
|
|
||
|
|
> [!NOTE]
|
||
|
|
> Pending full node review (2026-05). Content reflects `CONTRACT.md` and current source only. Known limitations enumerated in `CONTRACT.md` Section 14 are propagated below; additional issues may surface during the planned audit.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## When you would not use this node
|
||
|
|
|
||
|
|
| Scenario | Use instead |
|
||
|
|
|:---|:---|
|
||
|
|
| Ad-hoc single grab sample | Fire `cmd.start` once and tear it down — monster is overkill for one-off work. A `measurement` child with a one-shot inject is lighter. |
|
||
|
|
| Generic flow totaliser | `measurement` with the right type/variant, or a dedicated integrator function on the upstream parent. |
|
||
|
|
| Multi-constituent analyser (NH4, NO3, COD, TSS, …) | monster only emits **pulse + bucket-volume** events — it does **not** model analyte concentrations. The Home page framing ("multi-parameter biological process monitor") describes the **downstream** consumer of the composite sample, not the monster node's outputs. Pending review whether the framing should change or whether analyte fields should be added to Port 0. |
|
||
|
|
| Time-mode sampling (no flow source) | Not exercised. `constraints.flowmeter = false` exists in the schema but is **not** forwarded in `buildDomainConfig`; the sampling program always runs in flow-proportional mode. |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Known limitations
|
||
|
|
|
||
|
|
### `m3PerPuls` can round to zero
|
||
|
|
|
||
|
|
`_beginRun` computes `m3PerPuls = Math.round(predFlow / targetPuls)`. With low `predFlow` (e.g. an unconfigured `flowMax`, a stale rain forecast, or a very short `samplingtime`) this rounds to 0. The integrator then divides by 0; `temp_pulse` becomes `Infinity`; the first iteration of `_maybeEmitPulse` ramps `sumPuls` up to `absMaxPuls` in one tick and stops. **Symptom: instant bucket fill, then idle.** Workaround: ensure `predFlow ≥ targetPuls` (typical `targetPuls` is 200), e.g. `flowMax ≥ 200 m³` or longer `samplingtime`. Tracked.
|
||
|
|
|
||
|
|
### Default `flowMax = 0` blocks every run
|
||
|
|
|
||
|
|
The schema defaults `nominalFlowMin = 0` and `flowMax = 0`. `validateFlowBounds` requires `min >= 0 && max > 0 && min < max`, so the default config is invalid and the run never starts. The status badge surfaces this as `Config error: nominalFlowMin (0) >= flowMax (0)`. Fix the bounds before deploying. Tracked.
|
||
|
|
|
||
|
|
### `set.rain` is dropped while `running=true`
|
||
|
|
|
||
|
|
`updateRainData` short-circuits when `running` is true — the rain forecast is only consumed between runs. During a long `samplingtime` (e.g. 24 h) the rain forecast goes stale silently. `getRainIndex` does enforce a 2-hour `RAIN_STALE_MS` cap on `avgRain`, but only **outside** a run; during a run the cached `predFlow` is whatever `_beginRun` froze. Open question.
|
||
|
|
|
||
|
|
### `set.mode` and `set.model-prediction` are reserved
|
||
|
|
|
||
|
|
Both handlers delegate to optional methods (`source.setMode()`, `source.setModelPrediction()`) that don't exist on `Monster`. Sending these topics is a no-op. They survive the registry only as forward-compatibility placeholders. Scheduled to either be implemented or removed in a later phase.
|
||
|
|
|
||
|
|
### `constraints.flowmeter` is not wired
|
||
|
|
|
||
|
|
The schema field exists with a `true` default, but `nodeClass.buildDomainConfig` does **not** forward it. The sampling program assumes a flow source unconditionally. Setting `flowmeter=false` in the editor has no runtime effect. Tracked.
|
||
|
|
|
||
|
|
### `subSampleVolume` is hard-coded at 50 mL
|
||
|
|
|
||
|
|
`volume_pulse = 0.05` in `_initSamplingDefaults` is a constant. The schema enforces `min=max=50` so the field is informational only. Bucket-and-target math (`minPuls`, `maxPuls`, `absMaxPuls`, `targetPuls`) all assume 50 mL. Changing this requires a coordinated change across `parameters.js`, the schema, and any consumer that decodes pulse counts back to volume. Tracked.
|
||
|
|
|
||
|
|
### Measured-flow handler does not convert units
|
||
|
|
|
||
|
|
`flowTracker.handleMeasuredFlow` reads `eventData.unit` but only uses it to label the stored measurement — the **value is not converted**. If a measurement child emits in `l/s`, monster stores the raw number and labels it `l/s`, but `getEffectiveFlow` is consumed as if it were m³/h. Wire children that already emit in m³/h, or set `default unit` on the child to `m3/h`. Tracked.
|
||
|
|
|
||
|
|
### Edge test `sampling-guards.edge.test.js` cooldown-guard case fails
|
||
|
|
|
||
|
|
A pre-existing failure documented in `CONTRACT.md` Section 14. The cooldown skip increments `missedSamples` but the assertion expects different timing. Tracked.
|
||
|
|
|
||
|
|
### S88 colour cleanup pending
|
||
|
|
|
||
|
|
The editor node colour in `monster.html` is `#4f8582` (teal). The correct Unit-level S88 colour is `#50a8d9`. The Mermaid diagrams in this wiki already use the correct colour. The editor node tile must be updated separately. Tracked in `.claude/rules/node-red-flow-layout.md` Section 16.
|
||
|
|
|
||
|
|
### No formal FSM
|
||
|
|
|
||
|
|
Unlike `rotatingMachine` (idle → starting → warmingup → operational → …) monster only has the `running` boolean. There is no protected-state guarantee, no abort token, no sequence registry. Cooldown and bounds are the only safety guards. If a future requirement needs e.g. a `pausing` / `paused` state, the sampling program needs to be lifted onto the platform's `state` module. Open question.
|
||
|
|
|
||
|
|
### No multi-parent registration audit
|
||
|
|
|
||
|
|
`childRegistrationUtils.registerChild` runs unconditionally. Whether monster can be safely wired under multiple parents (e.g. one reactor and one settler), and whether teardown ordering is correct, has not been audited. Open question.
|
||
|
|
|
||
|
|
### Multi-constituent reporting absent
|
||
|
|
|
||
|
|
The node's framing in the project memory ("multi-parameter biological process monitor — surrogate for a benchtop analyser") suggests monster reports NH4 / NO3 / COD / TSS / etc. **The current implementation does not.** monster emits volumetric pulse + bucket state only. Lab analyte values are produced by a separate downstream consumer that ingests the physical composite sample collected on the monster's pulses. Either:
|
||
|
|
|
||
|
|
- the framing should be tightened to "composite sampler / sampling-cabinet controller", or
|
||
|
|
- analyte fields (with timestamps and per-pulse correlations) should be added to Port 0.
|
||
|
|
|
||
|
|
Pending decision-gate review.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Open questions (tracked)
|
||
|
|
|
||
|
|
| Question | Where it lives |
|
||
|
|
|:---|:---|
|
||
|
|
| Should `set.rain` updates apply mid-run (best-effort `predFlow` re-compute) or stay run-frozen? | Internal — not yet ticketed |
|
||
|
|
| Implement or remove `set.mode` + `set.model-prediction` placeholders | Internal |
|
||
|
|
| Wire `constraints.flowmeter` and exercise the time-mode path | Internal |
|
||
|
|
| Add unit conversion to `flowTracker.handleMeasuredFlow` | Internal |
|
||
|
|
| Round-to-zero `m3PerPuls` — clamp to ≥ 1 or refuse to start? | Internal |
|
||
|
|
| Multi-parent registration safety audit | Internal |
|
||
|
|
| Add formal FSM (`idle` / `armed` / `running` / `cooldown`)? | Open |
|
||
|
|
| Add analyte / multi-constituent reporting to Port 0, or rephrase the node's framing | Decision-gate — pending |
|
||
|
|
| Restore or remove the dangling `monster-dashboard.flow.json` + `monster-api-dashboard.flow.json` references | Internal |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Migration notes
|
||
|
|
|
||
|
|
### From legacy topic aliases
|
||
|
|
|
||
|
|
The pre-canonical topics (`i_start`, `monsternametijden`, `rain_data`, `input_q`, `setMode`, `model_prediction`) are accepted as aliases and emit a one-time deprecation warning. They are scheduled for removal in Phase 7. Update flows to use the canonical names from [Reference — Contracts](Reference-Contracts#topic-contract):
|
||
|
|
|
||
|
|
| Legacy | Canonical |
|
||
|
|
|:---|:---|
|
||
|
|
| `i_start` | `cmd.start` |
|
||
|
|
| `monsternametijden` | `set.schedule` |
|
||
|
|
| `rain_data` | `set.rain` |
|
||
|
|
| `input_q` | `data.flow` |
|
||
|
|
| `setMode` | `set.mode` |
|
||
|
|
| `model_prediction` | `set.model-prediction` |
|
||
|
|
| `registerChild` | `child.register` |
|
||
|
|
|
||
|
|
### Pre-2026-05-11 invalid-bounds silent skip
|
||
|
|
|
||
|
|
Before 2026-05-11 `nominalFlowMin` / `flowMax` were not declared in `monster.json`'s `constraints` section. `configUtils` stripped them as unknown keys; bounds collapsed to undefined → NaN → invalid, silently blocking every run. Fixed in the schema; ensure your `monster.json` is at the current commit.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Related pages
|
||
|
|
|
||
|
|
| Page | Why |
|
||
|
|
|:---|:---|
|
||
|
|
| [Home](Home) | Intuitive overview |
|
||
|
|
| [Reference — Contracts](Reference-Contracts) | Topic + config + child filters (alias map at the top) |
|
||
|
|
| [Reference — Architecture](Reference-Architecture) | Code map, sampling-program loop, prediction + cooldown pipeline |
|
||
|
|
| [Reference — Examples](Reference-Examples) | Shipped flows + debug recipes |
|
||
|
|
| [EVOLV — Architecture](https://gitea.wbd-rd.nl/RnD/EVOLV/wiki/Architecture) | Platform-wide three-tier pattern |
|