--- name: orchestrate description: > Check agent task state and launch container agents for ready tasks. Designed for use with /loop (e.g., /loop 2m /orchestrate) to auto-dispatch work to container agents. user_invocable: true allowed-tools: Read, Write, Edit, Bash(date *), Bash(cat *), Bash(hostname *), Bash(docker *), Bash(jq *), Bash(git *) --- # /orchestrate Skill orchestrate You are the task orchestrator. Check task state, update statuses, and launch container agents for tasks that are ready to run. Each task runs in its own git worktree for isolation. ## Pre-gathered context ### Current date !`date +%Y-%m-%dT%H:%M:%S` ### Hostname !`hostname` ### Task state !`cat .agent-tasks.json 2>/dev/null || echo "NO_TASK_FILE"` ## Instructions If the task state file doesn't exist, say "No .agent-tasks.json found. Run /decompose first." and stop. ### Step 1: Check running containers For each task with `status: "running"`, check if the container is still alive: ```bash docker inspect --format '{{.State.Status}}' 2>/dev/null ``` - If container status is `exited`: get exit code with `docker inspect --format '{{.State.ExitCode}}'` - Exit code 0 → set task status to `completed`, record `completed_at` and `exit_code` - Exit code non-zero → set task status to `failed`, record `exit_code` and capture last 20 lines of logs with `docker logs --tail 20 `, store in `error` - If container not found (removed or wrong host): mark as `failed` with error "Container not found" - If container still running: leave as `running` **On task completion (success or failure):** - Do NOT remove the worktree yet — the user may want to review changes on the branch - For successful tasks, note that `branch` contains the changes ### Step 2: Identify ready tasks A task is **ready** when: - Its status is `pending` - ALL tasks in its `depends_on` list have status `completed` If a dependency has status `failed`, mark the dependent task as `blocked` (it cannot proceed). ### Step 3: Launch ready tasks Respect `max_concurrent` from `.agent-tasks.json`. Count tasks with `status: "running"` — if at the limit, skip launching and wait for the next cycle. For each ready task: #### 3a. Create a git worktree Determine the branch point: - If the task has no dependencies, branch from the current HEAD: `git worktree add .worktrees/ -b agent/` - If the task depends on one completed task, branch from that task's branch: `git worktree add .worktrees/ -b agent/ agent/` - If the task depends on multiple completed tasks, create a merge base first: ```bash git branch agent/-base git checkout agent/-base git merge --no-edit agent/ agent/ ... git checkout - # back to original branch git worktree add .worktrees/ -b agent/ agent/-base ``` Record the `branch` and `worktree` path in the task state. #### 3b. Copy dependency outputs into the worktree For tasks with dependencies, the dependency's output files (listed in `writes`) are likely untracked in git — they exist only in the dependency's worktree. Copy them into the new worktree: ```bash # For each completed dependency: for dep_task_id in ; do # Copy the files that dep_task listed in its "writes" field for file in ; do cp .worktrees//$file .worktrees//$file done done ``` Also copy any untracked files from the main tree that the task needs (listed in `reads`): - Spec files, plan files, etc. that may not be committed - Check with `git status` whether files exist in the worktree; copy from main tree if missing This step is critical — worktrees only contain committed content. Without it, agents cannot read dependency outputs or untracked project files. #### 3c. Launch the container Determine the model to use: - Read the task's `model` field from `.agent-tasks.json` - If `model` is set, use that value (e.g., `claude-opus-4-20250514`, `claude-sonnet-4-20250514`) - If `model` is not set or null, default to `claude-sonnet-4-20250514` ```bash docker run -d \ -e CLAUDE_CODE_OAUTH_TOKEN="" \ -e ENFORCE_SUBSCRIPTION_PRICING=true \ -v :/project \ -w /project \ --entrypoint uid-wrapper.sh \ agent-claude:latest \ claude --print --dangerously-skip-permissions --model "" ``` **Important:** - Use `-d` (detached) so the container runs in the background — do NOT use `--rm` so we can inspect logs after exit - Mount the **worktree path** (not the main project) as `/project` - Capture the container ID from docker run output - The CLAUDE_CODE_OAUTH_TOKEN must be available in the current environment. If not set, read it from `~/dev/claude/secrets/claude/long_lived_oauth_token` (extract the value after `value: `) - If the task's `reads` list references paths outside the project (e.g., `/foundations` for best practices), mount those as additional read-only volumes - Container agents do NOT have web search capability. Do not include "use web search" in task prompts unless web search support has been explicitly configured for the container. After launching, update the task in `.agent-tasks.json`: - Set `status` to `running` - Set `host` to the current hostname - Set `container_id` to the docker container ID (full ID, not short) - Set `started_at` to current ISO timestamp - Set `branch` and `worktree` to the values from step 3a ### Step 4: Report status Print a concise status summary: ``` Agent Tasks — ───────────────────────────── completed task-a: Write payload spec ✓ (branch: agent/task-a) completed task-b: Write entrypoint spec ✓ (branch: agent/task-b) running task-c: Write harness spec (container abc123..., 3m elapsed) pending task-d: Implement resolver (waiting on: task-c) blocked task-e: Integration tests (blocked by failed: task-f) failed task-f: Build images (exit code 1) ───────────────────────────── 3/6 complete | 1 running | 1 pending | 1 blocked Concurrency: 1/3 slots used ``` ### Step 5: Update task state file Write the updated `.agent-tasks.json` with all status changes. ### Step 6: Merge completed branches (when all done) When ALL tasks are resolved (no `pending` or `running` remaining): 1. Print "All tasks resolved." 2. List completed task branches with a summary of what each contains 3. Suggest the user review and merge: `git merge agent/` for each, or `git merge agent/ agent/ ...` for an octopus merge 4. Note that worktrees can be cleaned up with: `git worktree remove .worktrees/` 5. Suggest cancelling the loop if running via `/loop` Do NOT auto-merge — the user should review and decide. ### Automation Notes - This skill is designed to be called repeatedly via `/loop 2m /orchestrate` - Each invocation is stateless — it reads .agent-tasks.json, checks containers, updates, and exits - Keep output concise when called in a loop — just the status table unless something changed - On first run, if `CLAUDE_CODE_OAUTH_TOKEN` is not in the environment, read it once and export it for subsequent runs ### Error Recovery - If a task fails, its dependents are marked `blocked`. The user can: - Fix the issue in the worktree and re-run: set status back to `pending` in .agent-tasks.json - Skip the task: manually mark dependents as `pending` and adjust their branch points - If a worktree creation fails (e.g., branch already exists): `git branch -D agent/` and retry - Stale containers (running > 30 minutes with no output): flag in status report but don't kill automatically