skills/claude/workflow-state/SKILL.md
Checkpoint and resume workflow state for context persistence across sessions. Use when the user says 'save progress', 'checkpoint', 'I need to stop', or runs /checkpoint or /rehydrate. Saves current workflow phase, task progress, and artifacts for later resumption. Do NOT use for workflow initialization (handled by ideate/debug/refactor commands).
npx skillsauth add lvlup-sw/exarchos workflow-stateInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Manage persistent workflow state that survives context auto-summarization.
State files store: task details, worktree locations, PR URLs, and review status.
Activate this skill when:
/exarchos:ideate)/exarchos:rehydrate <featureId>)/exarchos:checkpoint)Valid transitions, guards, and prerequisites for all workflow types are documented in references/phase-transitions.md. CRITICAL: Phase mutation is a separate action from field mutation. When a transition has a guard, action: "update" the prerequisite fields first, then action: "transition" — guards read the most recent state, so updates land before guards evaluate. Attempting to mutate phase via action: "update" returns a RESERVED_FIELD error pointing at transition (see "Reserved fields" below).
Use exarchos_workflow({ action: "describe", actions: ["update", "init", "get"] }) for
parameter schemas and exarchos_workflow({ action: "describe", playbook: "feature" })
for phase transitions, guards, and playbook guidance. For the lightweight
oneshot variant (with its implementing → synthesize|completed choice state
driven by synthesisPolicy), call exarchos_workflow({ action: "describe", playbook: "oneshot" })
— oneshot is a first-class playbook alongside feature/debug/refactor. Use
exarchos_event({ action: "describe", eventTypes: ["workflow.transition", "task.completed"] })
for event data schemas.
Workflow state lives in the MCP event store, not the filesystem. Use exarchos_workflow get to read state and exarchos_view pipeline to discover active workflows. Do not scan ~/.claude/workflow-state/*.state.json — that path is legacy and may be stale or empty.
For full MCP tool signatures, error handling, and anti-patterns, see references/mcp-tool-reference.md.
At the start of /exarchos:ideate, use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "init" with:
featureId: the workflow identifier (e.g., "user-authentication")workflowType: one of "feature", "debug", "refactor", "oneshot"synthesisPolicy (optional, oneshot only): one of "always", "never", "on-request" (default "on-request") — silently ignored for non-oneshot typesThis creates a new workflow state entry. The initial phase depends on
workflowType:
feature → starts in plandebug → starts in triagerefactor → starts in exploreoneshot → starts in planfeature — full plan → plan-review → delegate → review → synthesize for real features with subagent dispatch and reviewdebug — triage → investigate → (thorough | hotfix) for bug workflows with track selectionrefactor — explore → brief → (polish | overhaul) for code improvements, polish for small and overhaul for multi-taskoneshot — plan → implementing → (completed | synthesize) for trivial changes; direct-commit by default with an opt-in PR path resolved via a choice-state guard driven by synthesisPolicy and the synthesize.requested eventSee @skills/oneshot-workflow/SKILL.md for the lightweight variant's full prose, including the choice-state mechanics and finalize_oneshot trigger.
Use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "get" and featureId:
featureIdquery for dot-path lookup (e.g., query: "phase", query: "tasks")fields array for projection (e.g., fields: ["phase", "featureId", "tasks"])Field projection via fields returns only the requested top-level keys, reducing token cost.
Use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "update" with featureId and updates. This action mutates non-phase fields only — phase, workflowType, featureId, createdAt, and version are reserved (see "Reserved fields" below).
updates: { "artifacts.spec": "docs/specs/2026-01-05-feature.md" }updates: { "tasks[0].status": "complete", "tasks[0].completedAt": "<timestamp>" }updates: { "worktrees.wt-001": { "branch": "feature/001-types", "taskId": "001", "status": "active" } }Worktree status values: 'active' | 'merged' | 'removed'
Use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "transition" with featureId and target:
target: "delegate"Transitions are HSM-validated and emit a workflow.transition event. Guarded transitions read state after the most recent update, so any updates: {...} that the guard depends on must land first.
tasks arrayThe dot-path parser used by set updates recognizes only numeric array brackets (tasks[0], tasks[1], …). Keyed forms like tasks[id=T-001] are NOT supported and now throw an INVALID_INPUT error with a clear message — earlier versions silently wrote to a bogus top-level key, returning success: true while the actual task was untouched. Three patterns are supported:
Replace the whole array (use this when the plan is being revised wholesale):
exarchos_workflow({
action: "update",
featureId: "<id>",
updates: { tasks: [
{ id: "T-001", title: "...", status: "pending" },
{ id: "T-002", title: "...", status: "pending" },
]},
})
Edit one task by its array index:
exarchos_workflow({
action: "update",
featureId: "<id>",
updates: { "tasks[0].status": "complete", "tasks[0].completedAt": "<ts>" },
})
First read tasks (action: "get", query: "tasks") to find the index of the task you want to edit, then set by that index.
Append a new task by writing to the next-free index. If the array currently has length N, write to tasks[N]:
// Suppose tasks already contains T-001 and T-002 (length 2). To append:
exarchos_workflow({
action: "update",
featureId: "<id>",
updates: { "tasks[2]": { id: "T-003", title: "Follow-up", status: "pending" } },
})
The parser allows writing one slot past the current length (MAX_ARRAY_GAP = 1); writing further out (tasks[5] against a length-2 array) throws INVALID_INPUT. Read the current tasks length before appending.
For context restoration after summarization, use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "get" and featureId. This outputs a minimal summary suitable for rebuilding orchestrator context.
To verify state matches git reality, run /exarchos:rehydrate <featureId> — the rehydration projection folds events newer than the last snapshot and surfaces drift in the returned envelope. For deeper manual verification, run the reconciliation script:
exarchos_orchestrate({
action: "reconcile_state",
stateFile: "<state-file>",
repoRoot: "<repo-root>"
})
On passed: true: State is consistent.
On passed: false: Discrepancies found — review output and resolve.
| Event | State Update |
|-------|--------------|
| /exarchos:ideate starts | init the workflow (initial phase plan) |
| Design & Rationale authored | update: { "artifacts.spec": "<path>" } (no transition — plan is the initial phase) |
| Decomposition added | update: { "artifacts.plan": "<path>", "tasks": [...] }, then transition target: "plan-review" |
| Plan-review gaps found | update: { "planReview.gaps": [...] }, auto-loop to plan |
| Plan-review approved | update: { "planReview.approved": true }, then transition target: "delegate" |
| Task dispatched | Set task status = "in_progress", startedAt |
| Task complete | Set task status = "complete", completedAt |
| Worktree created | Add to worktrees object |
| Review complete | Update reviews object |
| PR created | Set artifacts.pr, synthesis.prUrl |
| PR feedback | Append to synthesis.prFeedback |
Oneshot is a first-class workflow type with a compressed lifecycle and an opt-in PR path. The rows below mirror the feature-workflow table above.
| Phase | State updates | Events emitted |
|-------|---------------|----------------|
| plan (oneshot) | oneshot.planSummary, artifacts.plan, optional oneshot.synthesisPolicy | workflow.transition |
| implementing (oneshot) | tasks[].status, artifacts.tests | task.*, optional synthesize.requested (via request_synthesize) |
| synthesize (oneshot) | synthesis.prUrl, artifacts.pr | workflow.transition, stack.submitted |
| completed (oneshot) | — | workflow.transition (to completed) |
The implementing → synthesize | completed fork is a choice state resolved
by finalize_oneshot, which reads the synthesisOptedIn guard
(synthesisPolicy + synthesize.requested events). See
@skills/oneshot-workflow/SKILL.md for the full opt-in mechanics.
Skills should update state at key moments:
brainstorming/SKILL.md:
After authoring the Design & Rationale section of the unified docs/specs/ artifact:
- `action: "update"` — `updates: { "artifacts.spec": "<path>" }`
(no transition — `plan` is the initial phase; continue to decomposition in the same phase)
implementation-planning/SKILL.md:
After saving plan:
1. `action: "update"` — `updates: { "artifacts.plan": "<path>", "tasks": [...] }`
2. `action: "transition"` — `target: "plan-review"`
delegation/SKILL.md:
On task dispatch:
- Update task status to "in_progress"
- Add worktree to state if created
On task complete:
- Update task status to "complete"
- Check if all tasks done, suggest checkpoint
See docs/schemas/workflow-state.schema.json for full schema.
Key sections:
version: Schema version (currently "1.1")featureId: Unique workflow identifierworkflowType: Required. One of "feature", "debug", "refactor", or "oneshot"phase: Current workflow phaseartifacts: Paths to design, plan, PRtasks: Task list with statusworktrees: Active git worktreesplanReview: Plan-review delta analysis results (gaps, approved)reviews: Review resultssynthesis: Merge/PR statemcp__plugin_exarchos_exarchos__exarchos_workflow with action: "update" rejects two classes of paths with RESERVED_FIELD:
phase, workflowType, featureId, createdAt, version. Set once at init; never mutated directly._ (e.g. _version, _checkpoint.summary, _eventHints). These are projection or event-store metadata.Alternate write paths:
phase → mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "transition" and target: "<phase>". Transitions are HSM-validated and emit transition events.mcp__plugin_exarchos_exarchos__exarchos_event with action: "append" (e.g. checkpoint, state.patched). The projection folds the event into the field on the next read.workflowType, featureId, createdAt, version → not migratable. If you need a different workflow type, init a new workflow.A RESERVED_FIELD error envelope now carries a typed data block:
{
"success": false,
"error": {
"code": "RESERVED_FIELD",
"message": "Cannot update reserved field: phase",
"data": {
"rejectedPath": "phase",
"rule": "`phase` is top-level immutable — set once at init, never directly mutated thereafter.",
"alternateWritePath": "Use `mcp__plugin_exarchos_exarchos__exarchos_workflow` with `action: \"transition\"` and `target: \"<phase>\"` — phase changes are HSM-validated and emit transition events."
}
}
}
Read the full descriptor — including the regex catch-all for underscore paths — via mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "describe" and actions: ["update"]. The returned reservedFields block is the single source of truth.
If an Exarchos MCP tool returns an error:
mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "get" and the featureIdmcp__plugin_exarchos_exarchos__exarchos_workflow with action: "cancel" and dryRun: trueIf workflow state doesn't match git reality:
/exarchos:rehydrate <featureId> — the rehydration projection folds in events newer than the last snapshotworkflowState / artifacts with git log and branch statemcp__plugin_exarchos_exarchos__exarchos_workflow with action: "update" to match git truthIf /exarchos:checkpoint is invoked with no active workflow:
mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "list" to enumerate active workflows; if the list is empty the checkpoint command's "no active workflow" report is correct — exit cleanlylist returns a candidate, verify it: call mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "get" and that featureIdIf state references branches or worktrees that no longer exist:
/exarchos:rehydrate <featureId> — the rehydration document surfaces stale referencesgit branch -a / git worktree list to identify driftexarchos_workflow update to match git truthIf multiple workflow state files exist:
mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "cancel" and dryRun: true on stale workflows to preview cleanupStart new workflow: Use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "init" with featureId: "user-authentication", workflowType: "feature"
After authoring the Design & Rationale section (plan is already the initial phase — no transition):
action: "update", featureId: "user-authentication", updates: { "artifacts.spec": "docs/specs/2026-01-05-user-auth.md" }Check state: Use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "get" with featureId: "user-authentication"
Resume after context loss: Use mcp__plugin_exarchos_exarchos__exarchos_workflow with action: "get" with featureId: "user-authentication" to get context restoration output
testing
Create pull request from completed feature branch using GitHub-native stacked PRs. Use when the user says 'create PR', 'submit for review', 'synthesize', or runs /synthesize. Validates branch readiness, creates PR with structured description, and manages merge queue. Do NOT use before review phase completes. Not for draft PRs.
testing
Shepherd PRs through CI and reviews to merge readiness. Operates as an iteration loop within the synthesize phase (not a separate HSM phase). Uses assess_stack to check PR health, fix failures, and request approval. Triggers: 'shepherd', 'tend PRs', 'check CI', or /shepherd.
development
Single adversarial review pass over the integrated branch diff — spec-compliance, code quality, and test adequacy judged together by one fresh-context reviewer. Triggers: /review, 'review the changes', or after delegation completes. Emits one verdict (reviews.review.status). Do NOT use for plan-review (that is its own dispatched gate) or for debugging.
testing
Restore and read workflow state after a context break — re-inject workflow phase, task progress, and behavioral guidance into the current session, reconcile state against git reality, and verify whether a workflow exists. Use when the user says 'resume', 'rehydrate', 'where were we', or runs /rehydrate, or when the agent has drifted after context compaction. Do NOT use for saving or mutating state (that is /checkpoint).