---
name: splitty-run
description: >-
  Execute a splitty pipeline to completion. Use when given a path to a
  pipeline.yaml file (or an existing run-id to resume). Drives the
  orchestration loop: init → loop[next → spawn sub-agents → mark done] →
  finalize. Claude itself is the orchestrator — there is no daemon. Each
  agent step becomes one Task() call.
---

# splitty-run

You are the orchestrator. Your job is to drive a deterministic state machine,
spawning sub-agents step-by-step until the pipeline completes.

The state machine lives entirely on disk. **Do not improvise.** Always ask the
`splitty` CLI what to do next.

## Conventions

- The CLI is `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/splitty.py`.
  Bind a shell alias for readability:
  ```
  SPLITTY="python3 ${CLAUDE_PLUGIN_ROOT}/scripts/splitty.py"
  ```
- The workspace defaults to the current working directory.
  Run state lives in `.splitty/runs/<run-id>/`.
- Sub-agents are dispatched via the `Task` tool with
  `subagent_type: "splitty-filter"` (the substrate agent shipped with this
  plugin) and the prompt obtained from `$SPLITTY prompt <run-id> <stage> <item>`.

## Phase 1 — Init (or resume)

If the user gave you a pipeline path:

```
$SPLITTY validate <path>
$SPLITTY init <path> [--input <input-path>] > .splitty/last-init.json
```

Read `last-init.json` to get the `run_id`. Tell the user: "Initialized run
`<run-id>` with N chunks."

If the user gave you a run-id (resume), skip init and use that id.

## Phase 2 — Orchestration loop

Repeat until `$SPLITTY next <run-id>` returns `"complete": true`:

### Step A — Ask what's next

```
$SPLITTY next <run-id>
```

Output is JSON:

```json
{
  "run_id": "...",
  "complete": false,
  "steps": [
    {
      "stage_id": "extract",
      "item_id": "0001",
      "stage_type": "map",
      "needs_agent": true,
      "mechanical_strategy": null,
      "is_gate": false
    },
    ...
  ]
}
```

If `complete: true`, exit the loop. Otherwise, group `steps` by **kind**:

| Kind                                  | Action                                                                 |
|---------------------------------------|------------------------------------------------------------------------|
| `is_gate: true`                       | Run `$SPLITTY gate <run-id> <stage>` once per gate stage in the batch  |
| `needs_agent: false` and `mechanical_strategy: <s>` | Run `$SPLITTY union <run-id> <stage>` once per terminal stage |
| `needs_agent: true`                   | Spawn one `Task(subagent_type="splitty-filter", ...)` per step         |

### Step B — Mechanical steps first (cheap)

For every gate step in the batch, run the corresponding `$SPLITTY gate` call.
For every mechanical-strategy terminal in the batch, run `$SPLITTY union`.
These do not need sub-agents — they finish synchronously.

### Step C — Agent steps in parallel

For every `needs_agent: true` step:

1. Get the prompt:
   ```
   $SPLITTY prompt <run-id> <stage-id> <item-id>
   ```
   Capture stdout. This is the **complete** prompt — do not modify it.

2. Mark the step as running:
   ```
   $SPLITTY start <run-id> <stage-id> <item-id>
   ```

3. Spawn a sub-agent in **parallel** with the others in this batch by emitting
   one `Task` tool call per step **in the same message**:

   ```
   Task(
     subagent_type="splitty-filter",
     description="<short description: stage_id/item_id>",
     prompt=<the prompt from $SPLITTY prompt>
   )
   ```

   Sub-agents do not return their output to you — they write to the path
   declared inside the prompt. Your job after spawn is to verify the file
   exists and mark the step done.

4. After every spawned Task in the batch returns, mark each step done:
   ```
   $SPLITTY done <run-id> <stage-id> <item-id>
   ```
   `done` will refuse if the output file is missing. If that happens, mark
   the step failed instead:
   ```
   $SPLITTY fail <run-id> <stage-id> <item-id> --reason "no output produced"
   ```
   …and then **stop the run** and report the failure to the user. Do not try
   to plow through.

### Step D — Loop

Go back to Step A.

## Phase 3 — Finalize

When the loop exits with `complete: true`:

```
$SPLITTY finalize <run-id>
```

This copies the terminal stage's output to the configured `destination`.
Print the path to the user, then read the result file with the `Read` tool
and present a 1-3 sentence summary plus the path. Do **not** dump the entire
result into the conversation; the user can open it.

## Parallelism guidelines

- **Within a batch from `next`, run all eligible agent steps in parallel.**
  Concretely: emit all `Task` calls in a single message. The harness handles
  the rest.
- **Across batches, work serially.** A new batch becomes available only after
  the previous stage completes. Do not pre-emptively spawn future stages.
- If the batch is huge (say, 50+ chunks for a `map`), you can still emit
  them all in one message — the harness throttles internally. Do not split
  the batch yourself.

## What to tell the user during the run

After each batch: one short line. Examples:
- `Stage 'classify' (map): spawning 14 sub-agents in parallel.`
- `Stage 'only-relevant' (gate): kept 9, skipped 5.`
- `Stage 'extract' (map): 9 sub-agents complete.`
- `Stage 'catalog' (terminal, custom): synthesizing.`

After finalize: the destination path + 1-3 sentence summary.

## Failure handling

If any step fails to produce its output file:

1. Mark it failed via `$SPLITTY fail`.
2. Stop the loop.
3. Report to the user: which stage, which item, and the path of the input
   chunk so they can inspect it.
4. **Do not retry automatically.** A retry without diagnosis can compound the
   problem. Wait for the user.

## Determinism guarantees

This procedure gives the user deterministic control because:

- The pipeline file is the single source of truth for what stages exist.
- The state file is the single source of truth for what is done.
- The CLI computes `next` from the state file, not from your judgment.
- Sub-agents do exactly one step each; they never branch the pipeline.
- Every leaf is a terminal stage; the run cannot end in an open branch.

Follow the loop. Do not improvise.
