# Actor Compiler

The actor compiler translates hierarchical YAML-defined GRAPH actors into
LangGraph `StateGraph` node/edge structures that can be executed by the
CleverAgents runtime.

## Compilation Pipeline

1. **Input validation** — The compiler accepts an `ActorConfigSchema` with
   `type=GRAPH` and a populated `route` field.  Non-GRAPH types are rejected
   with `ActorCompilationError`.

2. **Reference validation** — All node IDs referenced in edges, entry, and
   exit points are checked against the declared node set.

3. **Intra-graph cycle detection** — The route's `detect_cycles()` method
   verifies the node graph is acyclic.

4. **Cross-actor subgraph cycle detection** — When an optional
   `actor_resolver` is provided, the compiler follows `SUBGRAPH` node
   references recursively and detects cycles across actor boundaries
   (e.g. actor A → actor B → actor A).

5. **Node mapping** — Each `NodeDefinition` is mapped to a LangGraph
   `NodeConfig` with the appropriate `NodeType` (AGENT, TOOL, CONDITIONAL,
   SUBGRAPH).

6. **Edge mapping** — Each `EdgeDefinition` is mapped to a LangGraph `Edge`.
   Conditional expressions are preserved in `edge.condition`.

7. **LSP binding extraction** — Per-node `lsp_bindings` config entries are
   extracted into `LspBinding` objects and stored in compilation metadata.

8. **Metadata assembly** — The compiler returns a `CompiledActor` containing
   the node map, edge list, entry point, and a `CompilationMetadata` object
   for diagnostics and CLI inspection.

## Node Binding

| Actor Node Type | LangGraph NodeType | Notes |
|---|---|---|
| `agent` | `AGENT` | LLM invocation node |
| `tool` | `TOOL` | Tool execution node |
| `conditional` | `CONDITIONAL` | Routing node |
| `subgraph` | `SUBGRAPH` | Nested actor reference |

LSP bindings are declared per-node in the `config.lsp_bindings` list:

```yaml
nodes:
  - id: coder
    type: agent
    name: Code Writer
    description: Writes Python code
    config:
      agent: coder_agent
      lsp_bindings:
        - lsp_server_name: local/pyright
          languages: [python]
          auto_detect: true
```

## Error Modes

| Error | Class | When |
|---|---|---|
| Non-GRAPH type | `ActorCompilationError` | `config.type != GRAPH` |
| Missing route | `ActorCompilationError` | `config.route is None` |
| Missing node | `MissingNodeError` | Edge references unknown node |
| Invalid entry/exit | `InvalidEntryExitError` | Entry/exit node not in graph |
| Intra-graph cycle | `SubgraphCycleError` | Nodes form a cycle |
| Cross-actor cycle | `SubgraphCycleError` | Subgraph refs form a cycle |

## API Reference

### `compile_actor(config, *, actor_resolver=None) -> CompiledActor`

Compile an `ActorConfigSchema` into a LangGraph-ready bundle.

**Parameters:**
- `config` — The actor configuration (must be `ActorType.GRAPH`).
- `actor_resolver` — Optional callable `(name: str) -> ActorConfigSchema | None`
  for resolving subgraph references.

**Returns:** `CompiledActor` with nodes, edges, and metadata.

### `CompiledActor`

| Field | Type | Description |
|---|---|---|
| `name` | `str` | Actor name |
| `nodes` | `dict[str, NodeConfig]` | LangGraph node configs |
| `edges` | `list[Edge]` | LangGraph edges |
| `entry_point` | `str` | Entry node ID |
| `metadata` | `CompilationMetadata` | Diagnostic metadata |

### `CompilationMetadata`

| Field | Type | Description |
|---|---|---|
| `node_ids` | `list[str]` | All node IDs (sorted) |
| `tool_nodes` | `list[str]` | Tool-type node IDs |
| `lsp_bindings` | `list[LspBinding]` | Per-node LSP bindings |
| `subgraph_refs` | `dict[str, str]` | Subgraph node → actor name |
| `entry_node` | `str` | Entry point node ID |
| `exit_nodes` | `list[str]` | Exit point node IDs |
