---
name: coo-dispatch
description: Routes a classified Inbox REQ to its execution target — direct exec, Hermes Kanban task, or Claude Code CLI subprocess. Called by coo-inbox-poll after coo-classify.
agent: hermes-coo
type: programmatic
context_files:
  - HQ-Vault/_System/COO/state.json
  - HQ-Vault/_System/COO/dispatch-log.ndjson
---

# coo-dispatch skill

## Purpose

Takes a classified REQ + execution intent and routes it to the right runner. Captures task ID / session ID / output reference. Updates `state.json.active_dispatches`. Appends to `dispatch-log.ndjson`.

## Input

```yaml
req_id: REQ-2026-05-26-1130-fix-scraper
classification:
  complexity: heavy
  safety_class: ok
  route: cc-cli:claude-code-rr
  lane: rr
  confidence: 0.85
body: {full REQ body}
```

## Routes

### `direct`

Execute inline within current Hermes session. Capture stdout, return.

Use cases: read-only queries, status checks, file appends, draft emails to Gmail Drafts.

Implementation: just run the tools needed inside the current Hermes agent loop.

### `kanban:{lane}`

Create a Hermes Kanban task on the lane's board. Assignee = `hermes-{lane}` (or `default` for lfcs lane). Hermes dispatcher picks up the task in next 60s tick and spawns the assigned profile in a separate OS process.

Implementation:

```bash
hermes --profile coo kanban create \
  --board {lane} \
  --assignee hermes-{lane} \
  --title "REQ-{id}: {short title}" \
  --body "{full REQ body + classification + return contract}" \
  --priority {derived from deadline}
```

Capture task ID. Add to `state.json.active_dispatches`:

```json
{
  "req_id": "REQ-2026-05-26-1130-fix-scraper",
  "route": "kanban:rr",
  "task_id": "t_abc123def",
  "assignee": "hermes-rr",
  "created_at": "2026-05-26T11:30:15+10:00",
  "expected_complete_by": "2026-05-26T12:00:00+10:00"
}
```

Poll the task status every minute (subsequent `coo-inbox-poll` ticks). When status → `done` or `failed`, update Inbox REQ Result block + remove from active_dispatches.

### `cc-cli:{agent-name}`

Spawn a Claude Code session via SSH (or local if on laptop) with the REQ as a scoped prompt. Heavy tasks (code refactors, multi-file edits, complex investigations) that exceed what a single Hermes session can do.

Implementation:

```bash
# Local CC on laptop:
claude -p "{REQ body + classification + return contract}" \
  --output-format json \
  --max-budget-usd 2.00 \
  --max-turns 30 \
  --append-system-prompt "You are {agent-name}. Follow lane discipline per HQ-Vault/_System/CLAUDE.md."

# Or remote CC via SSH on opsman-01 / laptop:
ssh mclou@laptop-cd8df7fs "cd /relevant/repo && claude -p '...'"
```

Capture session ID + path to stdout JSON. Add to `state.json.active_dispatches` with `task_id: cc-{session-id}`.

CC subprocess writes its result to a known location (e.g. `_System/COO/cc-results/{session-id}.md`). Hermes-COO reads this on next tick.

### `greylist-confirm`

Send Telegram message to Rocky:

```
GREYLIST CONFIRM
REQ: {id}
Action: {what would be done}
Risk: {1-line summary}
Reply Y to proceed, N to decline, or wait 5 min for auto-decline.
```

Wait up to 5 min for reply. If `Y` → proceed via the underlying route. If `N` or timeout → close REQ with `Closed: declined-by-{rocky|timeout}`.

### `escalate`

Append to `Outbox.md` under `## Decisions needed` with all context. Send Telegram heads-up:

```
ESCALATION
REQ: {id}
Why: {blocked class or low confidence}
See: Outbox.md "Decisions needed" section
```

Do not auto-act. Wait for Rocky to either approve via new REQ or close via vault edit.

## State tracking

After every dispatch, write to `dispatch-log.ndjson`:

```json
{"ts":"2026-05-26T11:30:15+10:00","agent":"hermes-coo","action":"dispatch","target":"REQ-2026-05-26-1130-fix-scraper","result":"ok","notes":"route=cc-cli:claude-code-rr, task_id=cc-abc123, expected_30min"}
```

Update `state.json.active_dispatches[]` — append new, remove completed.

On Hermes-COO restart: read `state.json.active_dispatches[]`, re-check status of each (poll Kanban, check CC result files). Resume tracking.

## Failure modes

- **Kanban dispatch fails** (assignee profile not running) — retry once with `hermes profile start {assignee}`, then escalate.
- **CC subprocess times out** — kill, log, escalate REQ to Rocky with stdout-so-far.
- **CC subprocess exceeds budget** — same.
- **`state.json` lock contention** — wait 1s, retry. After 5 retries, log warn + proceed (last-writer-wins acceptable here).
- **`dispatch-log.ndjson` write fails** — continue, log fail-warn to stderr (not fatal).

## What good looks like

REQ enters Inbox → classified in <2s → dispatched in <5s → tracking entry visible in `state.json` → completion within expected window → Result block appended → Rocky never had to think about it (unless escalated).
