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>
7.9 KiB
Reference — Limitations
Note
What
measurementdoes not do, current rough edges, and open questions. Open items live in.agents/improvements/IMPROVEMENTS_BACKLOG.mdin the EVOLV superproject; node-local follow-ups are tracked in the superproject'sMEMORY.mdand.claude/refactor/OPEN_QUESTIONS.md.Pending full node review (2026-05).
When you would not use this node
| Scenario | Use instead |
|---|---|
| Fusing signals from multiple sensors into one virtual measurement | This node is per-channel only. Aggregate at the parent (e.g. rotatingMachine already combines upstream + downstream into a differential). |
| Producing a control output / actuating something | This is read-only signal conditioning. Use rotatingMachine, valve, or another equipment-level node. |
| Threshold-trip alarms / latched state | There is no comparator / latch output. Build alarm logic on top of the emitted reading at the parent or in a dashboard rule. |
| A "passive" measurement that should not register with a parent | Registration is automatic at startup — not currently opt-out. TODO: confirm whether a "no-parent" mode exists; if not, leave the parent input unwired. |
Known limitations
Asset type must match the parent's filter exactly
Parents subscribe to events by exact string match on <asset.type>.measured.<position>. A measurement configured as flow-electromagnetic will not be picked up by a parent that filters on flow. The fix is mechanical — set asset.type to the bare type the parent expects.
This is documented in the superproject MEMORY.md under "Key Integration Gotchas":
Measurement
assetType: "flow"required (not "flow-electromagnetic") for pumpingStation/monster.
Position labels lowercase only in the event name
The event name emits <type>.measured.<position> with position lowercased (upstream, downstream, atequipment). The positionVsParent field in the child.register payload, however, is sent as configured (preserves case). If a parent indexes children by the register-payload position string, mixed-case there will not match the lowercase position in subsequent events. Document the convention in any new parent that joins measurement.
Legacy source.emitter
source.emitter fires 'mAbs' on the analog inputValue setter alongside the canonical measurements.emitter path. It is kept for the editor status badge during the refactor window and is slated for removal in Phase 7. New consumers must use measurements.emitter.
Digital mode — notifyOutputChanged() not explicitly called
Measurement.handleDigitalPayload collects a per-key summary but does not directly call notifyOutputChanged(). The analog inputValue setter does. TODO: confirm whether digital-mode Port 0 emissions rely on the next tick() or a follow-up notify path inside BaseNodeAdapter. Until verified, treat digital-mode Port 0 latency as "up to one tick" (1000 ms).
Digital mode — per-channel scaling / smoothing fall back to the analog block
When a config.channels[i] entry omits a per-channel scaling, smoothing, outlierDetection, or interpolation, the missing fields fall back to the node-level config — not to a sensible per-type default. Setting smoothing.smoothMethod = 'kalman' at the node level applies that to every digital channel that does not override it. Operators should set every block per channel in production digital flows.
data.measurement accepts numeric strings — not arrays / NaN
The analog handler parses with Number(p) and rejects NaN. Empty / whitespace strings are skipped silently. Arrays are not accepted in either mode and log a warn in digital mode.
Simulator does not respect outlier detection
Simulator.step() writes directly into m.inputValue. The downstream Channel.update does run outlier detection if enabled — but the simulator's random walk is well-behaved enough that this is effectively a no-op. Don't expect the outlier path to be exercised by the simulator alone.
cmd.calibrate requires ≥ 2 stored values
Calibrator.isStable() returns {isStable:false} when storedValues.length < 2. The legacy Measurement.isStable() wrapper returns a bare false in that case. A fresh calibration call before any data has arrived is silently rejected.
Calibration baseline depends on scaling.enabled
When scaling.enabled is true, the calibration baseline is scaling.inputMin. When disabled, it is scaling.absMin. Toggling scaling.enabled after calibrating shifts the meaning of the captured offset; recalibrate after any scaling-toggle.
Smoothing buffer not cleared on config change
Changing smoothing.smoothMethod or smoothing.smoothWindow at runtime does not clear storedValues. A previously-mean-smoothed buffer can produce a stale first sample after switching to lowPass until the window churns. The conservative workaround is to redeploy.
outlierDetection.enabled mirrored only into analogChannel
toggleOutlierDetection() propagates the new boolean to this.analogChannel.outlierDetection.enabled only. In digital mode the per-channel Channel.outlierDetection.enabled is not updated by the toggle. TODO: digital-mode parity for set.outlier-detection.
Min/max counters never reset
totalMinValue / totalMaxValue / totalMinSmooth / totalMaxSmooth are monotonic over the node's lifetime. There is no explicit reset command. The smooth-min/max additionally have a "first-write" rule that snaps both to the first value — before that, both read 0, which can mislead downstream chart axes.
Open questions (tracked)
| Question | Where it lives |
|---|---|
Should digital-mode notifyOutputChanged() fire on every accepted update? |
Internal — pending P9 review |
Drop the legacy source.emitter 'mAbs' event |
Phase 7 removal |
Replace legacy examples/{basic,integration,edge}.flow.json with Tier-1/2/3 visual-first flows |
Superproject MEMORY.md "TODO: Example Flows" |
Add data.clear-min-max / data.reset topic for the rolling counters |
Internal |
Add per-channel set.outlier-detection for digital mode |
Internal |
| Auto-recalibration heuristics (currently operator-triggered only) | Internal |
Per-channel smoothing window-clear on config change |
Internal |
Migration notes
From pre-refactor flat config
Older flows used assetType / supplier / category at the top level of the editor config. nodeClass.buildDomainConfig reshapes the editor's flat uiConfig into the nested domain config slice (scaling, smoothing, simulation, calibration, mode, channels), so legacy flows continue to deploy. The migration is best-effort — re-saving each measurement node in the editor regenerates the canonical shape.
From analog-only
Adding config.mode.current was additive. Flows that omit it default to analog and behave exactly as before. To switch to digital: set the editor's "Input Mode" to digital and define config.channels.
From legacy alias topics
simulator, outlierDetection, calibrate, measurement continue to work; each emits a one-time deprecation warning on first fire. Prefer the canonical set.simulator / set.outlier-detection / cmd.calibrate / data.measurement for new flows.
Related pages
| Page | Why |
|---|---|
| Home | Intuitive overview |
| Reference — Contracts | Topic + config + child registration (alias map at the end) |
| Reference — Architecture | Code map + per-Channel pipeline + lifecycle |
| Reference — Examples | Shipped flows + debug recipes |
| rotatingMachine — Limitations | Where the most common consumer's caveats overlap |