Declarative joins: the new TriggerGroup primitive
Almost every real-time pipeline eventually needs to wait for a combination of things. Fuse three sensors before you act. Wait until both the transcript and the speaker ID have landed. Proceed once any two of five nodes report ready. Classic publish/subscribe gives you one trigger per message, so that logic has always ended up inside your module — a hand-rolled state machine, a set of flags, a timeout, and the bugs that come with them.
Psyclone 2.1.1 makes the join declarative. The new <triggergroup> element fires only when a group of triggers activates together, with three modes:
- requires-all — every trigger in the group must have activated
- requires-any — the first activation is enough
- min-count — fire once N of the group have activated, whichever they are
“Wait until N of these things have happened” is now a first-class pattern you declare in the spec rather than implement in code. That matters for more than convenience: the join condition becomes inspectable and testable from outside the module, and it lives in the same document as the rest of your dataflow, where a reviewer can actually see it.
Backed by a CMSDK primitive
The declarative element sits on top of a matching join primitive in CMSDK, so the same grouped-activation semantics are available if you are working at the library level rather than from a spec — including from Python, now that the full API is exposed to Python 3. Grouped delivery is documented in the CMSDK LLM guide and the Doxygen reference.
While we were in there: trigger filters
Building the join meant auditing the surrounding trigger machinery, and that turned up genuine bugs worth flagging if you rely on filters today. The equalsnumeric and notequalsnumeric operators were inverted, and haskey matching was wrong. Both are fixed. Numeric operators now parse as float64, and the maxage operand is milliseconds — the documentation previously said microseconds, which was simply incorrect.
All eight trigger-filter operators are now documented with verified worked examples and corrected semantics, including the epsilon boundary behaviour on greaterthan and lessthan. If you have filters in production, it is worth a read.
Full detail is in the Psyclone AIOS documentation and the 2.1.1 release announcement.
