-
-
Notifications
You must be signed in to change notification settings - Fork 0
Output Messages
This page owns the four-output routing rules and the message envelope. For the full list of event types and which outputs each uses, see Events.
| # | Label | Carries |
|---|---|---|
| 1 | Trigger | Only a genuine untriggered → triggered transition. Nothing else, ever. |
| 2 | Release | Only a genuine triggered → untriggered transition (threshold re-crossed, or quorum lost under the Release policy). Nothing else, ever. |
| 3 | Query | Only query snapshots — requested by a query message, or produced by a Heartbeat tick. Query events appear on no other output. |
| 4 | Events | Everything else, plus a duplicate copy of every Trigger and Release event. The only output where msg.ignored can be true. |
The guarantee to build automations on: outputs 1 and 2 never carry a blocked, suppressed, or ignored message. Anything that didn't truly happen appears only on output 4, tagged.
Every output message is a clone of the message that triggered it, with these properties layered on top:
| Property | Meaning |
|---|---|
msg.consensusEvent |
The event type — see Events |
msg.consensusState |
waiting, untriggered, or triggered — see States
|
msg.aggregate |
Current aggregate value (fraction-true in Boolean mode); null while no data |
msg.aggregation |
The function actually used: mean, median, min, max, trimmedmean, mean(fallback), or fraction
|
msg.quorum |
Whether quorum is currently satisfied (true when quorum is disabled) |
msg.freshCount |
Number of fresh sources |
msg.sourceCount |
Number of known sources (learned + expected) |
msg.sources |
Per-source breakdown: { topic: { value, lastSeen, stale, seen } } (lastSeen ISO 8601 or null) |
msg.disabled |
Current disabled flag |
msg.ignored |
true if the message was received but did not change node state. Always false on outputs 1–3. |
msg.source |
"external" — a live incoming message caused this event; "internal" — the node's own clock did (staleness expiry, heartbeat tick, restore) |
Event-specific extras — releaseReason, rejectedValue,
staleTopic, recoveredTopic, addedTopic, removedTopic,
minorityTopics, triggerSet, releaseSet, staleSet — appear only
on their events, including rejected attempts, so downstream flows
can see exactly what was refused.
- Events with a live cause (readings, commands,
setstale-driven staleness flips) clone their own triggering message — your original payload and topic ride along. - Internally-caused events (staleness expiry, heartbeat ticks, restore-driven events) have no live message, so they clone the most recent accepted reading's message.
Events fire in causal order, and each envelope is a snapshot of the world at the moment that event dispatches — earlier envelopes are never re-stamped with knowledge of the later events they cause. Two visible consequences, both deliberate:
- A
quorumregainedthat enables the first-ever evaluation reportsconsensusState: "waiting"— the silent waiting → untriggered bookkeeping happens after it. - A
sourcestalewhose expiry costs the quorum still showsquorum: true— thequorumlostthat follows immediately is the correction.
With Emit aggregate on change only checked (the default), an
accepted reading event is emitted on output 4 only when it changed
the aggregate. sourceadded and sourcerecovered always emit, and
rejected readings always emit — they are diagnostics, and suppressing
them would reintroduce silent drops.
Getting Started
Reference
Features
Examples
- Examples Basic Numeric Averaging
- Examples Staleness and Quorum
- Examples Boolean Voting
- Examples Runtime Commands
Test Script Coverage
- Overview
- Test Suite 1 — Output routing & envelope shape
- Test Suite 2 — Aggregation functions
- Test Suite 3 — Boolean mode
- Test Suite 4 — Commands
- Test Suite 5 — Threshold set-commands & release-follows-trigger
- Test Suite 6 — Status labels
- Test Suite 7 — Staleness, quorum policies, heartbeat
- Test Suite 8 — Persistence
Support