Files
measurement/wiki/Reference-Limitations.md
znetsixe 1a16f9c4f1 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:10 +02:00

7.9 KiB

Reference — Limitations

code-ref

Note

What measurement does not do, current rough edges, and open questions. Open items live in .agents/improvements/IMPROVEMENTS_BACKLOG.md in the EVOLV superproject; node-local follow-ups are tracked in the superproject's MEMORY.md and .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.


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