CMLabs · Psyclone AIOS

# 2. System Messages

The CTRL_* control-message family that keeps a Psyclone system alive: what each message does, who sends and consumes it, and what is honestly implemented.

## How system messaging works

System control messages are ordinary DataMessages whose type lives in reserved type-subtype ranges: 10001–10004 (low-level), 10200–10306 plus 10297–10299 (PsyAPI control), 10998/10999 (intersystem), and the `CTRL_NODE_*` family used by the multi-node protocol. Human-readable names for these types are registered at startup. Three built-in types/contexts are also registered when a node configures: `PsyControl`, `Psyclone.Ready` (which doubles as the default context) and `Psyclone.Shutdown`.

Note. Every component gets an implicit DefaultComponentTrigger subscribed to `CTRL_SYSTEM_READY` — this is why components wake up when the system starts, even without an explicit `Psyclone.Ready` trigger.

## Control-message catalogue

Status: Shipped = sender and consumer wired · Stub = declared/parsed only.

Message | ID | Purpose | Sender → Consumer | Status
--- | --- | --- | --- | ---
`CTRL_TEST` | 10001 | Test type | test code | Shipped
`CTRL_LOGPRINT` | 10002 | Forward a log line from an external process/space to node logging | PsySpace → Node | Shipped
`CTRL_PING` / `CTRL_PING_REPLY` | 10003/10004 | Liveness ping between nodes and consoles | Node → Networking | Shipped
`CTRL_SYSTEM_READY` | 10200 | “System is up” broadcast; the type behind every DefaultComponentTrigger and the `Psyclone.Ready` default context | Node → all components | Shipped
`CTRL_PROCESS_INITIALISE` | 10201 | Initialise an external process/space | PsySpace → space runtime | Shipped
`CTRL_PROCESS_GREETING` | 10202 | Process announces itself after connecting | PsySpace → Node | Shipped
`CTRL_PROCESS_SHUTDOWN` | 10203 | Ask a process/space to shut down | PsySpace/Node → Node | Shipped
`CTRL_CONTEXT_CHANGE` | 10297 | Context switch notification; `<trigger context="X">` compiles to this type; PsyProbe can inject one from the UI | Node/PsyProbe/cranks → SubscriptionEngine | Shipped
`CTRL_SYSTEM_SHUTDOWN` | 10298 | Whole-system shutdown; sent to all nodes and queued to every process | Node shutdown/terminate → all nodes/processes | Shipped
`CTRL_SYSTEM_SHUTTINGDOWN` | 10299 | “Shutdown in progress” notification | declared and type-registered; no live sender found | Stub
`CTRL_TRIGGER` | 10300 | Wraps a fired trigger delivered to a crank or space | Node → PsySpace/Networking | Shipped
`CTRL_QUERY` / `CTRL_QUERY_REPLY` | 10301/10302 | On-demand query round-trip (`<query>` / API query) | crank API ↔ catalog/whiteboard | Shipped
`CTRL_PULLCOMPONENTDATA` | 10303 | Space pulls component data/parameters from its node | PsySpace → Node | Shipped
`CTRL_CREATECUSTOMPAGE` | 10304 | Ask PsyProbe to create a custom page/tab | API → PsyProbe | Shipped
`CTRL_ADDSUBSCRIPTION` | 10305 | Runtime subscription add from an API client (XML identical to module spec) | PsyAPI → Node | Shipped
`CTRL_RETRIEVESYSTEMIDS` | 10306 | Client retrieves type/context/component ID maps | API client → Node | Shipped
`CTRL_INTERSYSTEM_QUERY` / `_REPLY` | 10998/10999 | Query between separate Psyclone systems (InterSystemManager) | PsyAPI/InterSystemManager ↔ remote Node | Shipped

## Node-to-node sync messages (CTRL_NODE_*)

A second family of control messages is internal to the multi-node protocol: join and handshake, time synchronisation, ID/component/subscription sync with SUCCESS/FAILED replies, status and performance maps, cross-node context activation, signals and remote queries. The family: `WELCOME`, `JOIN`, `TIMESYNC(_REPLY)`, `NODEMAP(_REQUEST)`, `STATUSMAP`, `PERFSYNC`, `SYNC_REQ/REPLY`, `CONFIG(_SUCCESS/_FAILED)`, `SYNC_ID / CONFIRM_ID / CANCEL_ID (+_SUCCESS/_FAILED)`, `CONTEXT_ACTIVE`, `SIGNAL`, `QUERY(_SUCCESS/_FAILED)`, `SYNC_COMPONENT(±)`, `SYNC_SUBSCRIPTION(±)` and `CTRL_PSYPROBE_CREATECUSTOMPAGE(±)`. Shipped as a family — multi-node networking is working core functionality. Notably, `CTRL_NODE_CONTEXT_ACTIVE` propagates context activation across nodes, so context handling (including simultaneous multiple contexts) works system-wide.

Operators rarely interact with these directly, but they appear in Network/Sync topic logs at higher verbose levels — useful when diagnosing node join or sync failures (see Distributed Admin).

## Context-related triggers

Syntax | Behaviour | Status
--- | --- | ---
`<trigger context="X">` | Fires when context X is activated (type forced to `CTRL_CONTEXT_CHANGE`) | Shipped
`<post context="X">` | Posting changes the active context | Shipped
`<context name="X">...</context>` | Scopes a component's triggers/posts to that context | Shipped
PsyProbe UI context injection | Operators can switch contexts from PsyProbe | Shipped
`<trigger system="context...">` | Alternative attribute syntax (see below) | Roadmap

## system= triggers Stub

The newer spec documentation describes a generic system-event trigger syntax: `<trigger system="context">`, `system="context:context2"`, `system="key"` and `system="key:value"`. None of these are handled by the current code — there is no parsing of a `system` attribute anywhere in the trigger path, so they are documentation-only. The implemented equivalent for context events is `<trigger context="X">`, which internally becomes a `CTRL_CONTEXT_CHANGE` subscription. There is currently no mechanism for the generic `system="key:value"` event form.

Warning. If a spec you inherit uses `system=` trigger attributes, they are silently ignored. Convert context cases to `context="..."` triggers; other cases have no working substitute yet.

## Detecting control messages in your own code

Custom catalogs must recognise query control messages to serve replies:

    if (inMsg->getType() == PsyAPI::CTRL_QUERY) {
        uint32 id = (uint32)inMsg->getReference();
        // ... build reply ...
        api->queryReply(id, PsyAPI::QUERY_SUCCESS, replyMsg);
    }

    if inMsg.getType() == cmsdk.PsyAPI.CTRL_QUERY:
        id = inMsg.getReference()
        # ... build reply ...
        api.queryReply(id, cmsdk.PsyAPI.QUERY_SUCCESS, replyMsg)

Similarly, out-of-context posting surfaces as `POST_OUTOFCONTEXT (-3)` from `postOutputMessage` — a direct consequence of a `CTRL_CONTEXT_CHANGE` having deactivated the crank's context. See the User Guide chapter on Contexts and Catalogs.

PreviousAdministering Psyclone NextPsyProbe Configuration