> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cerulion.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Trigger policies

> The trigger policy SPEC grammar, macro-attribute equivalents, the defaulting matrix, and policy short labels.

A trigger policy decides when a node fires. It can be set on the CLI via `--policy SPEC` (on `node create` and `node modify`) or in source via a `#[cerulion_node(...)]` attribute. Trigger policy lives only on the macro side; graph YAML carries no policy block.

## `--policy SPEC` grammar

Accepted forms:

| SPEC                                  | Behavior                                                   | Rules                                                                                                                         |
| ------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `period_ms=N`                         | Fire every N ms.                                           | N must be a positive integer > 0. Bare `period_ms` (no `=N`) → error "requires a value". `period_ms=0` → error "must be > 0". |
| `sync_window_ms=N`                    | Fire when all trigger inputs arrive within an N-ms window. | Same N rules.                                                                                                                 |
| `external`                            | Fire only when triggered by the host.                      | Case-insensitive keyword.                                                                                                     |
| `data_trigger=NAME` or `trigger=NAME` | Fire when the named input receives a message.              | NAME must be non-empty and match a declared input.                                                                            |
| anything else                         | error                                                      | "unknown policy spec `X`" listing the accepted forms.                                                                         |

<Warning>
  There is no `default` policy keyword — `--policy default` errors with "unknown policy spec". A 100 ms period must be written `--policy period_ms=100`.
</Warning>

<Warning>
  There is no `deadline_ms` policy spec — `--policy deadline_ms=N` errors with "unknown policy spec `deadline_ms`". To watch for late data on a trigger input, use `#[input(trigger, expect_within_ms = N)]` in your node source.
</Warning>

## Macro-attribute equivalents

Each `--policy SPEC` has an equivalent `#[cerulion_node(...)]` attribute. See [Node macro reference](/cerulion/reference/node-macro) for full attribute semantics.

| `--policy SPEC`                      | Macro attribute                               |
| ------------------------------------ | --------------------------------------------- |
| `period_ms=N`                        | `#[cerulion_node(period_ms = N)]`             |
| `sync_window_ms=N`                   | `#[cerulion_node(sync_window_ms = N)]`        |
| `external`                           | `#[cerulion_node(external)]`                  |
| `data_trigger=NAME` / `trigger=NAME` | field marked `#[input(trigger)]` named `NAME` |

The `unbounded_sync`, `tick_within_ms = N`, and `throttle_ms = N` attributes have no `--policy` SPEC equivalent; they are macro-only.

## Defaulting matrix

When `--policy` is omitted, `node create` resolves the policy from the declared inputs (`resolve_create_policy`):

| Inputs declared             | Result                                                                                                                                                                              |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 0 inputs (no `-i`, no `-T`) | Error: source-only nodes must declare a non-data policy explicitly (`--policy period_ms=N` or `--policy external`).                                                                 |
| 1+ inputs via `-i` only     | No node-level policy attr is written (bare `#[cerulion_node]`). The runtime fires on any input arrival and emits a graph-build warning. No silent auto-promotion to `data_trigger`. |
| `-T` set                    | `DataTrigger { input_name: <T's name> }`, regardless of the `-i` count.                                                                                                             |
| Non-data `--policy` + `-T`  | Error (conflict).                                                                                                                                                                   |

<Note>
  The engine convenience wrapper `node_cmd::node_create` (used by tests/TUI scaffolding) supplies `Period { period_ms: 100 }` when called with `policy = None`. The CLI path uses the strict `node_create_with_options`, which enforces the 0-inputs-error rule. The "100 ms default" is a convenience-API behavior, not the CLI default.
</Note>

## Policy short labels

`node list` and `node info` print a short policy label via `format_policy_short`:

| Label             | Policy         |
| ----------------- | -------------- |
| `period <N>ms`    | Period         |
| `sync <N>ms`      | Bounded sync   |
| `sync ∞`          | Unbounded sync |
| `external`        | External       |
| `trigger:<input>` | Data trigger   |
| `-`               | None           |
