Missions
High-altitude workflows: decompose a goal into milestones, each holding a DAG of features, with a validation checkpoint per milestone. Source: packages/nikcli/src/mission/.
Overview
A Mission is a higher-altitude workflow than a Loop:
instead of a flat list of stages, it decomposes work into milestones, each
holding a directed acyclic graph of features, with a validation
checkpoint at the end of every milestone. The orchestrator drives one feature at a time
through the same goal worker the Loop engine uses, then runs a validation worker
before advancing to the next milestone.
Like Loops, missions are persisted in SQLite and run on the headless server. They keep working while the TUI is closed, survive process restarts (via lease/heartbeat), and emit bus events for the TUI to subscribe to.
Reuses primitives
The orchestrator does not reimplement iteration, budgets, persistence, or autonomy — it
reuses the existing goal worker, Session runtime, and
Scheduler.
Per-project scoping
Missions are scoped by the active project so definitions from different projects cannot
collide. Definitions and execution records are persisted through MissionRepo.
Crash-safe
Feature and milestone status is persisted on the definition after every step. A restart
resumes exactly where it left off. Orphaned runs are reconciled on the next boot
through a lease/heartbeat (MISSION_EXEC_LEASE_MS = 15s).
Concurrency cap
A synchronous single-flight claim per mission prevents overlapping runs of the same
mission. A global cap of MAX_CONCURRENT_MISSIONS = 2 keeps the host from
spawning unbounded workers.
Concepts
| Term | Definition |
|---|---|
| Mission | The top-level unit: a name, a brief, an ordered list of milestones, and a record of execution state. |
| Milestone | An ordered checkpoint that groups one or more features and applies a validation policy when they are all settled. |
| Feature | A leaf unit of work: name, objective, agent, optional model, optional token budget, optional dependsOn list of sibling features in the same milestone. |
| Validation | The policy that runs after every milestone's features are settled — scrutiny, user-test, or none. |
| Worker | The goal command driving a single feature. The validation policy drives a separate validation worker per milestone. |
| Exec / lease | A MissionExec record carries a lease/heartbeat so a crashed orchestrator can be reconciled by the next boot. |
Mission schema
All persisted types are defined in packages/nikcli/src/mission/schema.ts as
zod schemas. The shape is deliberately close to the Loop schema so the two engines can share
tooling.
Feature
| Field | Type | Notes |
|---|---|---|
id | string | Unique within the milestone. |
name | string | Display label. |
objective | string | The prompt fed to the goal worker. |
agent | string | Agent name (e.g. build, plan). |
model | "provider/model" | Optional. Defaults to the session default. |
tokenBudget | number | Optional per-feature cap. |
dependsOn | string[] | Sibling feature IDs in the same milestone that must reach done first. |
status | FeatureStatus | pending | running | done | blocked | skipped | error. |
error | string | Last surfaced error, if any. |
Milestone
| Field | Type | Notes |
|---|---|---|
id | string | Unique within the mission. |
name | string | Display label. |
features | Feature[] | One or more features per milestone. |
validation | "scrutiny" | "user-test" | "none" | Policy applied when features settle. |
status | MilestoneStatus | pending | running | validating | done | blocked. |
Mission
| Field | Type | Notes |
|---|---|---|
id | string | Stable identifier. |
name | string | Display label. |
brief | string | High-level description of the mission's intent. |
milestones | Milestone[] | Ordered list of milestones. |
models | MissionModels | Per-role model overrides (worker, validation, orchestrator). |
status | MissionStatus | pending | running | paused | complete | error | cancelled. |
createdAt | number | Epoch ms. |
Lifecycle
A mission moves through these states as the orchestrator walks it. The full
MissionStatus schema in packages/nikcli/src/mission/schema.ts also
carries planning and ready for the brief-to-milestones phase; the
states below are the ones you see in the TUI and in bus events.
- running — the orchestrator is actively driving features and validation.
- paused — held by user request. No new features start; in-flight work is not aborted.
- frozen — held automatically when a feature or validation worker has been aborted by a timeout or external error. Use
mission resumeto continue. - complete — every milestone reached
doneand the final validation (if any) passed. - error — a feature or the validation worker surfaced an unrecoverable error.
Per-feature timeouts
A hung feature can never hold the single-flight slot forever. Each feature run is capped
(DEFAULT_FEATURE_TIMEOUT_MS = 60min), bridged to prompt.cancel on
expiry. Bounds:
| Constant | Value | Purpose |
|---|---|---|
MIN_FEATURE_TIMEOUT_MS | 1_000 | Smallest accepted override. |
DEFAULT_FEATURE_TIMEOUT_MS | 60 * 60_000 | Default cap when the feature omits one. |
MAX_FEATURE_TIMEOUT_MS | 24 * 60 * 60_000 | Largest accepted override. |
MISSION_EXEC_LEASE_MS | 15_000 | Lease/heartbeat for orphan detection. |
MAX_CONCURRENT_MISSIONS | 2 | Global cap on simultaneously orchestrating missions. |
HISTORY_LIMIT | 100 | How many historical exec records to retain per mission. |
Validation policy
When every feature in a milestone has settled, the orchestrator runs a
validation worker according to the milestone's validation
policy. The validation worker is itself a goal command targeting the
mission's validation model (or the worker model if unset).
| Policy | Behavior |
|---|---|
scrutiny | Default. The validation worker reviews the milestone's outputs and either confirms done or marks the milestone blocked. |
user-test | The milestone is marked validating and held until a human (via TUI/CLI) approves or rejects it. |
none | Skip the validation worker. The milestone moves directly to done when all its features are done. |
The validation worker has the same tool surface as any other session. It is given the
milestone's name, the brief, and a list of feature outcomes. A user-test
milestone pauses until you reply from the TUI mission dialog.
CLI subcommands
nikcli mission is a thin headless wrapper over the orchestrator. It accepts
a brief from a file or flag, generates a draft plan, and lets you start, pause, resume,
or cancel execution.
| Subcommand | Purpose |
|---|---|
nikcli mission | Open the headless mission manager: list, status, quick actions. |
nikcli mission new [-f file] [--model …] [--agent …] | Create a mission from a brief. With -f, the brief is read from a Markdown or text file; otherwise it is read from --brief or stdin. |
nikcli mission start <id> | Begin orchestrating the mission. The mission moves from pending to running. |
nikcli mission pause <id> | Pause a running mission. In-flight features finish; no new features start. |
nikcli mission resume <id> | Resume a paused mission. |
nikcli mission cancel <id> | Cancel a mission. In-flight workers are aborted via prompt.cancel. |
nikcli mission get <id> | Show progress, current milestone, current feature, statuses, and last error. |
nikcli mission list | List all missions in the current project with their runtime status. |
# Draft a mission from a brief file and start it
nikcli mission new -f ./brief.md --agent build --model anthropic/claude-sonnet-4.5
nikcli mission start mss_abc123
# Watch progress
nikcli mission get mss_abc123
# Pause and resume
nikcli mission pause mss_abc123
nikcli mission resume mss_abc123
# Cancel
nikcli mission cancel mss_abc123
The strings pause, resume, clear, and
status are reserved feature objectives. Pick distinctive objectives for
your features so the orchestrator never confuses them with a control command.
Bus events
The orchestrator publishes typed bus events for the TUI, mobile, and SDK clients to
subscribe to. They live next to the orchestrator in
packages/nikcli/src/mission/orchestrator.ts.
| Event | Payload | Use |
|---|---|---|
mission.upserted | { missionID } | Definition created or replaced. |
mission.removed | { missionID } | Definition deleted. |
mission.started | { missionID } | Orchestration started. |
mission.finished | { missionID, status, error? } | Orchestration ended (complete | error | paused | frozen; the pending state never fires this event). |
mission.exec.started | { missionID, execID, kind, targetID, targetName, sessionID } | A feature or validation worker started. kind is feature or validation. |
mission.exec.finished | { missionID, execID, kind, status, sessionID?, error? } | Worker ended. |
mission.feature.updated | { missionID, milestoneID, featureID, status, error? } | Single feature state changed. |
mission.milestone.updated | { missionID, milestoneID, status } | Milestone moved into validating, done, or blocked. |
TUI surface
The TUI mission feature-plugin lives in
packages/tui/src/feature-plugins/mission/. It mirrors the
loop plugin and exposes:
- Mission home view — list of all missions with status chips, last run time, and quick actions (start, pause, resume, cancel).
- Mission detail view — per-milestone tree, per-feature rows, current feature highlight, validation status, and the live session id of the active worker.
- Draft dialog — paste a brief, pick an agent and a model, and create a mission without leaving the TUI.
- Validation review dialog — approve or reject
user-testmilestones. Approval advances the mission; rejection marks the milestoneblocked.
The plugin subscribes to the bus events above and batches updates into Solid signals. The same source of truth is consumed by the mobile app and the web app.
Failure modes
| Symptom | Likely cause | Fix |
|---|---|---|
Mission stuck in running after a crash | The orchestrator process died; the lease has expired. | Restart the host. restore() reconciles orphaned runs to error and you can resume the mission from the failed feature. |
Feature stays in running forever | The feature worker exceeded the per-feature timeout. | The orchestrator aborts the worker via prompt.cancel and marks the feature error. Inspect the worker session and resume the mission. |
Milestone stays in validating | The user-test policy is waiting for human approval. | Open the mission detail view in the TUI and approve or reject the milestone. |
| Single-flight slot held by a previous run | An earlier process crashed without releasing the slot. | The lease/heartbeat reaper releases the slot after MISSION_EXEC_LEASE_MS. If it persists, restart the host. |
| Model validation rejected at create time | The model field on a feature or the models field on the mission does not match "provider/model". | Use the canonical provider/model form, or omit the field to fall back to the session default. |
Source anchors
| File | What to inspect |
|---|---|
packages/nikcli/src/mission/schema.ts | Zod schemas and pure helpers for Mission, Milestone, Feature, MissionModels, ValidationPolicy. |
packages/nikcli/src/mission/manager.ts | CRUD and execution-record persistence. |
packages/nikcli/src/mission/orchestrator.ts | Headless engine, lease/heartbeat, single-flight, bus events. |
packages/nikcli/src/cli/cmd/mission.ts | CLI surface (nikcli mission …). |
packages/tui/src/feature-plugins/mission/ | TUI feature plugin: store, SDK, runner, dialogs. |
packages/nikcli/src/loop/engine.ts | The Loop engine whose operational guarantees the orchestrator reuses verbatim. |