Ops vs. Missions
Spec Kitty has two distinct units of governed work. Confusing them is the single most common source of "why didn't this get tracked/reviewed/merged" confusion for users past their first mission.
The two units of work
An Op is a lightweight, governed ad-hoc invocation started with
spec-kitty dispatch "<request>". It does not create a mission, a spec, a
plan, a work package, a branch, or a worktree. Concretely, spec-kitty dispatch
(src/specify_cli/cli/commands/dispatch.py):
- Routes the request text to an agent profile via
ActionRouter(or uses the profile you pass with--profile). - Loads governance/Charter context for that
(profile, action)pair. - Opens an Op record — a single append-only JSONL file at
kitty-ops/<invocation_id>.jsonl— and writes astartedevent with a fresh ULID invocation ID. - Returns synchronously with that context. It never spawns an LLM call itself; the calling agent does the actual work.
The Op stays open until you close it explicitly:
spec-kitty profile-invocation complete --invocation-id <id> --outcome <done|failed|abandoned>
That command appends a completed event to the same JSONL file (see
src/specify_cli/invocation/executor.py's ProfileInvocationExecutor.invoke() /
complete_invocation()). Unclosed Ops are surfaced by spec-kitty doctor ops and
eventually swept to abandoned. There is no lane, no for_review state, and no
consolidation step — an Op is a single governed unit of work with a start event and an
end event, nothing else.
A Mission is the canonical product term for a full spec-to-consolidate workflow
unit: specify → plan → tasks → implement → review → consolidate (accept, for some
mission types). Starting one (spec-kitty.specify / mission create) creates a
persistent mission directory under kitty-specs/<mission-slug>/ with spec.md,
plan.md, tasks.md, work-package files, and a meta.json carrying a durable
mission_id. Work packages move through the 9-lane status state machine
(planned → claimed → in_progress → for_review → in_review → approved
→ done, with blocked/canceled as side states), each transition is an
append-only event in status.events.jsonl, and spec-kitty implement creates
dedicated git worktrees/branches per work package. A Mission is designed to
survive across many sessions, multiple agents, and a review/consolidation gate; an Op is
designed to be opened and closed inside a single turn of work.
Decision rule
The binding rule is shipped doctrine, not this page:
DIRECTIVE_053 — Choose Op or Mission Before Starting
requires the choice to be made before work starts and re-checked while it runs.
It also requires every Op to be closed. The step-by-step heuristic that applies
the rule is the
op-or-mission-selection tactic.
Activate both in a project with:
spec-kitty charter activate directive 053-choose-op-or-mission-before-starting
spec-kitty charter activate tactic op-or-mission-selection
The table and heuristic below explain that rule. If they ever disagree with the artifacts, the artifacts win.
Use this table to decide before you start:
| If your situation is... | Use |
|---|---|
| A one-off question, review, or piece of advice with no lasting spec/plan/code artifact to track | Op (spec-kitty dispatch) |
| A small fix or task that doesn't need a spec, a review gate, or multi-session tracking | Op (spec-kitty dispatch) |
| You want the governance context (Charter, doctrine) injected once, synchronously, without opening a multi-step workflow | Op (spec-kitty dispatch) |
| The work needs a written spec, an implementation plan, discrete reviewable work packages, or will span more than one sitting | Mission (spec-kitty.specify → plan → tasks → implement → review → consolidate) |
| The work needs to be resumable by name/slug across sessions or by a different agent | Mission |
| The work needs an explicit review/approval gate before it lands | Mission |
A useful heuristic: if you can describe the entire task in one sentence and expect it done in one sitting, it's an Op. If you'd naturally want to write a spec for it, or if "let's continue this tomorrow" makes sense, it's a Mission.
The choice can change while you work. If an Op turns up work that is too large to finish cleanly now, or that needs its own design pass (a spec, an ADR or an operator decision), stop extending the Op. Close it with the outcome of what you actually did, then carry the rest into a Mission or a tracked follow-up. Don't let the Op grow until the work is done.
Ops and Missions are not mutually exclusive: a governed mission action (e.g.
spec-kitty next --agent <name> --mission <slug>) uses the same governed-context
model as dispatch. Both may write under kitty-ops/, but the record kind
differs. dispatch opens a standalone per-invocation Op record — its own
file at kitty-ops/<invocation_id>.jsonl (src/specify_cli/invocation/writer.py
/ executor.py) — that stays open until you explicitly close it with
profile-invocation complete. spec-kitty next never opens one of those. It
instead appends paired started/completed lifecycle records — a
different schema, ProfileInvocationRecord
(src/specify_cli/invocation/lifecycle.py) — to one shared, append-only
kitty-ops/lifecycle.jsonl log; there is no per-invocation file and no
explicit "close" command for it.
Examples
Op — a quick governed question, no mission created:
spec-kitty dispatch "Review this implementation approach for the retry logic" --profile implementer-ivan
# ... agent does the review inline ...
spec-kitty profile-invocation complete --invocation-id 01J... --outcome done
Mission — a full lifecycle reference, spanning multiple commands and sessions:
/spec-kitty.specify # -> kitty-specs/<mission-slug>/spec.md
/spec-kitty.plan # -> plan.md
/spec-kitty.tasks # -> tasks.md + tasks/WP*.md
spec-kitty implement WP01 # creates a lane worktree, work begins
# ... review, approve, repeat per WP ...
spec-kitty consolidate # lane consolidation into local main
For the mechanism behind governed dispatch in more depth, see
Profile Invocation Reference (CLI flags and
trail fields) and
Understanding Governed Profile Invocation
(the (profile, action, governance-context) model). To choose which Mission
type to start, see Mission Types.