# Mission Best Practices

Lessons and patterns from running missions against real codebases. This guide is opinionated — it captures what works, not every possible configuration.

## Mission Planning

### Size items for one workflow run

Each mission item becomes a single adapter execution. If the item is too large, the workflow run will hit iteration limits or produce sprawling PRs that are hard to review. If it is too small, you pay scheduling and worktree overhead for trivial changes.

Good item size: one issue, one PR, one reviewable unit of work. Think "could a developer finish this in a focused session?"

### Decompose before you launch

Use `--prompt` to get an initial decomposition, then review the plan preview before confirming. Adjust with `aroom mission update` if the plan needs restructuring — it is cheaper to fix the plan than to cancel and restart items mid-flight.

### Order dependencies deliberately

The scheduler launches items only when all upstream dependencies are complete. Put foundation work (schema changes, shared utilities, configuration) at the root of the dependency graph. Independent feature branches can run in parallel once their shared dependency completes.

Anti-pattern: a flat plan with no dependencies where item 3 silently depends on item 1's output. The scheduler cannot enforce implicit ordering — make it explicit.

### Keep item descriptions actionable

The item description becomes the issue body or prompt fed to the workflow runner. Vague descriptions ("handle edge cases") produce vague implementations. Specific descriptions ("add retry with exponential backoff to the HTTP client, max 3 attempts, configurable via `http.max_retries`") produce targeted PRs.

## Adapter Selection

### When to use `noop`

Use the `noop` adapter for items that are tracked but not executed by Anteroom:

- Manual verification steps ("confirm staging deployment works")
- External CI/CD steps tracked for dependency ordering
- Research or design tasks completed outside the mission
- Items you want to reconcile manually after completion

Mark noop items done with `aroom mission reconcile`.

### When to use `workflow`

Use the `workflow` adapter when the item should be executed by a workflow definition — typically a Claude/Codex issue delivery or PR repair flow.

```bash
# Explicit workflow binding
aroom mission create --spec @ns/spec/auth \
  --adapter workflow \
  --workflow-path examples/workflows/local_work_item_router.yaml

# Profile-based binding (auto-selects workflow)
aroom mission create --spec @ns/spec/auth --profile hands-off
```

The router workflow (`local_work_item_router.yaml`) is usually the best default — it inspects live PR state and dispatches to the right lifecycle workflow automatically.

### Non-coding items

Items like documentation, research, and manual verification do not have a workflow shape that fits them today. Current approach:

1. Bind these items to the `noop` adapter
2. Complete them manually
3. Reconcile: `aroom mission reconcile <session> <item> --reason "Docs written and merged"`

Planned: issue [#1259](https://github.com/troylar/anteroom/issues/1259) (lifecycle-aware workflow binding) and [#1260](https://github.com/troylar/anteroom/issues/1260) (first-class non-coding item types) will provide structured support for non-coding items. Until those ship, noop + reconcile is the correct pattern.

## Workflow Shape Selection

Each workflow shape owns a specific lifecycle state. Using the wrong shape wastes cycles or produces confusing results.

| Lifecycle State | Workflow Shape | When to Use |
|---|---|---|
| Fresh issue, no PR | `local_claude_codex_issue_delivery` | New work from scratch — planning, implementation, PR creation, review |
| PR exists, needs fixes | `local_claude_codex_pr_repair` | Review feedback, failing checks, or draft PR needing work |
| PR branch behind main | `local_claude_pr_refresh` | Merge conflicts or stale branch before review can continue |
| PR ready, needs review | `local_codex_pr_review_only` | Branch is clean, just need senior review pass |
| Unknown / let the system decide | `local_work_item_router` | Default entry point — inspects state and routes automatically |

### Anti-patterns

- **Running issue delivery on an existing PR.** Issue delivery re-enters planning and may overwrite existing implementation work. Use PR repair or the router instead.
- **Running PR repair when the branch needs refresh.** Repair assumes a mergeable branch. If the branch is behind main, refresh first.
- **Skipping the router to save time.** The router adds one `inspect-pr` call. The cost of picking the wrong lifecycle workflow is much higher.
- **Rerunning issue delivery after 3 plan review rounds.** The plan loop is capped at 3 rounds intentionally. If the plan is still churning, approve manually or switch to a narrower workflow.

## Concurrency and Lanes

### When to limit concurrency

Limit concurrent items when:

- Items share resources (same repo, same database, same test suite) and parallel execution causes conflicts
- You want to review each PR before the next item starts
- Your CI budget is limited

Use `--profile parallel-review` for parallel lanes with review gates, or set lane limits explicitly in the compiled plan.

### When to parallelize

Parallelize when:

- Items are genuinely independent (different modules, different repos)
- You want throughput over control
- Each item's workflow creates an isolated worktree (the local CLI workflows do this by default)

Use `--profile hands-off` for parallel execution with hold-on-failure escalation.

### Lane isolation

The local CLI workflows create per-issue worktrees automatically, so parallel items do not step on each other's working directories. However, shared resources like databases or external services may still conflict. If parallel items touch the same external state, serialize them with dependencies.

## Monitoring

### Use the right tool for the job

| Command | Purpose |
|---|---|
| `aroom mission status <id>` | Snapshot of items, progress, blockers, lanes |
| `aroom mission why <id>` | Per-item blocker diagnosis — why is this item stuck? |
| `aroom workflow status <run_id>` | Detailed step-level status of a specific workflow run |
| `aroom workflow history <run_id>` | Event timeline for a workflow run |

### Watch for stale items

If an item stays in `active` status for much longer than expected, check whether its child workflow run has a stale heartbeat. The scheduler detects stale heartbeats automatically and emits `item_stale_recovered` events, but you can also inspect manually:

```bash
aroom mission why <session_id>
aroom workflow status <run_id>
```

### Monitor the scheduler

When running missions from the CLI, the scheduler runs in the foreground via `aroom mission scheduler`. Watch its output for launch events, completion events, and errors. Use `--once` for one-shot evaluation in scripts.

## Common Failure Modes and Recovery

### Stale locks

A workflow run may hold a lock after a worker crash. The workflow engine reclaims stale locks when the heartbeat expires. If you need to force it:

```bash
aroom workflow cancel <run_id>
aroom mission retry <item_id>
```

### Failed items

When an item fails, diagnose first:

```bash
aroom mission why <session_id>
aroom workflow status <run_id>
aroom workflow history <run_id>
```

Then choose a recovery path:

- **Retry**: `aroom mission retry <item_id>` — resets to pending for re-launch. Use when the failure was transient (timeout, flaky test, network error).
- **Replace**: `aroom mission replace <item_id>` — cancels the current execution and resets. Use when the execution is stuck or producing wrong results.
- **Reconcile**: `aroom mission reconcile <session_id> <item_id> --reason "Fixed manually"` — marks done without re-running. Use when you fixed the issue outside the mission.

If the item is workflow-backed with a linked issue and the GitHub issue was closed externally, the scheduler reconciles automatically on its next cycle. Check `aroom observe` for `item_reconciled` events before retrying.

### Items completed outside the mission

**Automatic (no operator action):** For workflow-backed items with a linked GitHub issue, the scheduler checks external reality before finalizing a failed item. If the GitHub issue is closed, the item is automatically reconciled to `completed`. When the issue was closed by a merged PR, the PR number is included in the reason string. A merged PR alone does not trigger auto-reconciliation — the issue must be closed. Operators see an `item_reconciled` event in `aroom observe` output with a reason like `"Issue #1180 closed; merged closing PR(s): #1305"` or `"Issue #1180 closed externally"`.

**Manual (`mission reconcile` required):** For noop-adapter items, workflow items without an issue number in their inputs, or external completions not reflected in GitHub (manual deploys, external CI, hotfixes to a different repo), use the manual reconcile command:

```bash
aroom mission reconcile <session_id> <item_id> --reason "PR merged externally"
```

If the item has a live execution, add `--force` to cancel it first.

### Blocked items with no path forward

If an item is blocked on a failed upstream dependency:

1. Fix or reconcile the upstream item
2. The scheduler automatically re-evaluates downstream eligibility on its next cycle

If the dependency itself is wrong, update the plan:

```bash
aroom mission update <session_id> --instruction "Remove dependency from deploy on the caching task"
```

### Plan needs restructuring mid-flight

Use `aroom mission update` to apply structured patches to a running mission. The compiler generates patch operations (add, remove, reorder, change dependencies) and previews them before applying. Use `--force` if operations target active items.

For conversational steering, use `aroom mission talk <session_id>` to discuss the plan with AI and apply changes interactively.
