> ## 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.

# Graph and schema files

> Exact YAML field specifications for graph files and schema files.

Workspaces store graphs in `graphs/<name>.yaml` and schemas in `schemas/<Name>.yaml`. Both are YAML.

## Graph YAML

<Note>
  There is no `policy:` block in graph YAML; trigger policy lives only on the macro side.
</Note>

```yaml theme={null}
name: perception          # required
prefix: robot1            # optional; omitted line => default = hostname without ".local"
nodes:
  - id: camera            # required, unique instance ID
    type: camera          # required, node type = folder name (YAML key is `type`)
    inputs:               # optional
      - name: image       # input port name (matches #[input] field)
        source: camera/image   # "<node_id>/<output_name>"
    outputs:              # optional
      - name: image       # output port name (matches #[output] field)
        schema: sensor_msgs/Image   # optional; "::" auto-normalized to "/"
        max_slice_len: 6291456      # optional usize; runtime resolves if omitted (final fallback 16 MiB)
        history_size: 2             # optional usize, default 0 (volatile; >0 = transient-local replay depth)
```

### Top-level fields (`GraphConfig`)

| Field    | Type                 | Required | Default                   | Meaning                                                           |
| -------- | -------------------- | -------- | ------------------------- | ----------------------------------------------------------------- |
| `name`   | String               | Yes      |                           | Graph name.                                                       |
| `prefix` | String               | No       | hostname without `.local` | Topic prefix. Omitted line resolves to the hostname at load time. |
| `nodes`  | list of node entries | No       | empty                     | Node instances in the graph.                                      |

### Node entry fields (`NodeDef`)

| Field       | YAML key  | Type   | Required | Default | Meaning                                                         |
| ----------- | --------- | ------ | -------- | ------- | --------------------------------------------------------------- |
| `id`        | `id`      | String | Yes      |         | Unique instance ID.                                             |
| `node_type` | `type`    | String | Yes      |         | Node type = folder name. The YAML key is `type` (serde rename). |
| `inputs`    | `inputs`  | list   | No       | empty   | Input bindings.                                                 |
| `outputs`   | `outputs` | list   | No       | empty   | Output ports.                                                   |

### Input fields (`InputDef`)

| Field    | Type   | Required | Meaning                                         |
| -------- | ------ | -------- | ----------------------------------------------- |
| `name`   | String | Yes      | Input port name (matches the `#[input]` field). |
| `source` | String | Yes      | `<node_id>/<output_name>`.                      |

### Output fields (`OutputDef`)

| Field           | Type   | Required | Default                                   | Meaning                                                                                                                                                                                           |
| --------------- | ------ | -------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`          | String | Yes      |                                           | Output port name (matches the `#[output]` field).                                                                                                                                                 |
| `schema`        | String | No       | empty                                     | Schema name (`::` is normalized to `/`). Should match the output type declared in the node's macro. If it doesn't, `cerulion graph run` emits a warning and ignores this field for buffer sizing. |
| `max_slice_len` | usize  | No       | (runtime-resolved; final fallback 16 MiB) | Max slice length. Skipped from output when none.                                                                                                                                                  |
| `history_size`  | usize  | No       | 0                                         | 0 = volatile; > 0 = transient-local replay depth.                                                                                                                                                 |

A reference fixture (`perception` graph with nodes camera/detector/imu/fusion/tracker/diagnostics, topology only) exists at `cerulion_core/fixtures/test_graph.yaml`.

## Schema YAML

`cerulion schema create Reading` writes `schemas/Reading.yaml` with a skeleton:

```yaml theme={null}
schemas:
  Reading:
    description: ""
    fields:
      # Add fields: type name
```

A populated schema the parser accepts:

```yaml theme={null}
schemas:
  Reading:
    description: "A single sensor reading"
    fields:
      float64 value:
      uint64 timestamp:
```

The top-level `schemas:` map holds one entry per schema name; each entry has a `description` string and a `fields:` map keyed by `type name`.

### Schema info hash

`cerulion schema info` reports the schema name, description, field count, and `Hash: 0x<16-hex>`. The hash is the FNV-1a hash of the schema name.
