
Wf Player
- 17 installs
- 2.1k repo stars
- Updated June 18, 2026
- catlog22/claude-code-workflow
Support for wf-player
About
Provides workflow support for wf-player. Solo builders use this to streamline development.
- wf-player
Wf Player by the numbers
- 17 all-time installs (skills.sh)
- Ranked #2,076 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/catlog22/claude-code-workflow --skill wf-playerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 17 |
|---|---|
| repo stars | ★ 2.1k |
| Last updated | June 18, 2026 |
| Repository | catlog22/claude-code-workflow ↗ |
What it does
Support for wf-player
Files
Workflow Run
Load a workflow template → bind variables → execute DAG → persist checkpoints → resume capable.
Architecture
Skill(skill="wf-player", args="<template> --context goal='...'")
|
+-- Phase 0: Entry Router
|-- --list -> list available templates, exit
|-- --resume -> load session, skip to Phase 3 (Execute)
|-- --dry-run -> load + show execution plan, no execution
|-- default -> Phase 1 (Load)
|
+-- Phase 1: Load & Bind
| Load template JSON, bind {variables} from --context, validate required vars
|
+-- Phase 2: Instantiate
| Init session state, topological sort, write WFR session file
|
+-- Phase 3: Execute Loop
| For each node in order:
| skill node -> Skill(skill=...) [synchronous]
| cli node -> ccw cli [background + stop, hook callback]
| command node -> Skill(skill="namespace:cmd") [synchronous]
| agent node -> Agent(...) [run_in_background per node config]
| checkpoint -> save state, optionally pause
|
+-- Phase 4: Complete
Archive session, output summaryShared Constants
| Constant | Value |
|---|---|
| Session prefix | WFR |
| Session dir | .workflow/sessions/WFR-<slug>-<date>/ |
| State file | session-state.json |
| Template dir | .workflow/templates/ |
| Template index | .workflow/templates/index.json |
Entry Router
Parse $ARGUMENTS:
| Detection | Condition | Handler |
|---|---|---|
| List templates | --list in args | -> handleList |
| Resume session | --resume <session-id> in args | -> Phase 2 (resume) |
| Dry run | --dry-run in args | -> Phase 1 + 2, print plan, exit |
| Normal | Template slug/path provided | -> Phase 1 |
| No args | Empty args | -> handleList + AskUserQuestion |
handleList
Scan .workflow/templates/index.json. Display:
Available workflow templates:
feature-tdd-review [feature, complex] 3 work nodes, 2 checkpoints
quick-bugfix [bugfix, simple] 2 work nodes, 1 checkpoint
...
Run: Skill(skill="wf-player", args="<slug> --context goal='...'")---
Phase 0 (Resume): Session Reconciliation
Trigger: --resume <session-id> or active WFR session found in .workflow/sessions/WFR-*/
1. Scan .workflow/sessions/WFR-*/session-state.json for status = "running" | "paused" 2. Multiple found → AskUserQuestion for selection 3. Load session-state.json 4. Identify last_checkpoint and node_states 5. Reset any running nodes back to pending (they were interrupted) 6. Determine next executable node from topological_order after last checkpoint 7. Resume at Phase 3 (Execute Loop) from that node
---
Phase 1: Load & Bind
Read phases/01-load.md and execute.
Objective: Load template, collect missing variables, bind all {variable} references.
Success: Template loaded, all required variables bound, bound_context{} ready.
---
Phase 2: Instantiate
Read phases/02-instantiate.md and execute.
Objective: Create WFR session directory, init state, compute execution plan.
Success: session-state.json written, topological_order ready.
---
Phase 3: Execute Loop
Read phases/03-execute.md and execute.
Objective: Execute each node in topological_order using appropriate mechanism.
CRITICAL — CLI node blocking:
- CLI nodes launch
ccw cliin background and immediately STOP - Wait for hook callback — DO NOT poll with TaskOutput
- Hook callback resumes execution at next node
Success: All nodes completed, all checkpoints saved.
---
Phase 4: Complete
Read phases/04-complete.md and execute.
Objective: Archive session, output execution summary and artifact paths.
---
Error Handling
| Scenario | Resolution |
|---|---|
| Required variable missing | AskUserQuestion to collect it |
| Template not found | Show --list and suggest closest match |
| Node failed (on_fail=abort) | AskUserQuestion: Retry / Skip / Abort |
| Node failed (on_fail=skip) | Log warning, continue to next node |
| Node failed (on_fail=retry) | Retry once, then abort |
| Interrupted mid-execution | State saved at last checkpoint; resume with --resume <session-id> |
| Cycle in DAG | Error immediately, point to template for fix |
Specs Reference
| Spec | Purpose |
|---|---|
| specs/node-executor.md | Execution mechanism per node type |
| specs/state-schema.md | session-state.json schema |
Phase 1: Load & Bind
Objective
Locate and load the workflow template, collect any missing context variables from the user, bind all {variable} references.
Workflow
Step 1.1 — Resolve Template Path
Parse $ARGUMENTS for template identifier:
Path resolution order: 1. Absolute path: use as-is 2. Relative path (starts with .): resolve from cwd 3. Slug only (e.g. feature-tdd-review): look up in .workflow/templates/index.json → get path 4. Partial slug match: scan index for closest match → confirm with user
If not found:
- Show available templates from index
- AskUserQuestion: "Which template to run?"
Step 1.2 — Parse --context Arguments
Extract --context key=value pairs from $ARGUMENTS.
Examples:
--context goal="Implement user auth" --context scope="src/auth"
--context goal='Fix login bug' scope=src/authBuild bound_context = { goal: "...", scope: "..." }.
Step 1.3 — Load Template
Read template JSON from resolved path.
Validate:
template_id,nodes,edges,context_schemaall presentnodesarray non-empty
Step 1.4 — Collect Missing Required Variables
For each variable in context_schema where required: true:
- If not in
bound_context: collect via AskUserQuestion - If has
defaultvalue: use default if not provided
AskUserQuestion({
questions: [{
question: "Provide values for required workflow inputs:",
header: "Workflow: <template.name>",
// one question per missing required variable
}]
})For optional variables not provided: use default value or leave as empty string.
Step 1.5 — Bind Variables
Apply substitution throughout all args_template strings:
- Replace
{variable_name}withbound_context[variable_name] - Leave
{N-001.session_id}and{prev_*}references unresolved — these are runtime-resolved in Phase 3
Write bound context to memory for Phase 3 use.
Step 1.6 — Dry Run Output (if --dry-run)
Print execution plan and exit:
Workflow: <template.name>
Context:
goal = "<value>"
scope = "<value>"
Execution Plan:
[1] N-001 [skill] workflow-lite-plan "<goal>"
[2] CP-01 [checkpoint] After Plan auto-continue
[3] N-002 [skill] workflow-execute --resume-session {N-001.session_id}
[4] CP-02 [checkpoint] Before Tests pause-for-user
[5] N-003 [skill] workflow-test-fix --session {N-002.session_id}
To execute: Skill(skill="wf-player", args="<slug> --context goal='...'")Success Criteria
- Template loaded and validated
- All required context variables bound
- bound_context{} available for Phase 2
Phase 2: Instantiate — Init Session State
Objective
Create the WFR session directory, initialize session-state.json with all nodes marked pending, compute topological execution order.
Workflow
Step 2.1 — Generate Session ID
session_id = "WFR-<template-slug>-<YYYYMMDD>-<HHmmss>"
session_dir = ".workflow/sessions/<session_id>/"Create session directory.
Step 2.2 — Topological Sort
Run topological sort on template.nodes + template.edges:
function topoSort(nodes, edges):
build adjacency list from edges
Kahn's algorithm (BFS from nodes with no incoming edges)
return ordered node IDsParallel group handling: Nodes in the same parallel_group can execute concurrently. In topological order, keep them adjacent and mark them as a parallel batch.
Store execution_plan:
[
{ "batch": 1, "nodes": ["N-001"], "parallel": false },
{ "batch": 2, "nodes": ["CP-01"], "parallel": false },
{ "batch": 3, "nodes": ["N-002a", "N-002b"], "parallel": true },
{ "batch": 4, "nodes": ["N-003"], "parallel": false }
]Step 2.3 — Init Node States
For each node in template:
{
"N-001": {
"status": "pending",
"started_at": null,
"completed_at": null,
"session_id": null,
"output_path": null,
"artifacts": [],
"error": null
}
}Checkpoint nodes:
{
"CP-01": {
"status": "pending",
"saved_at": null,
"snapshot_path": null
}
}Step 2.4 — Write session-state.json
See specs/state-schema.md for full schema. Write to <session_dir>/session-state.json:
{
"session_id": "<WFR-id>",
"template_id": "<template.template_id>",
"template_path": "<path to template>",
"template_name": "<template.name>",
"status": "running",
"context": { /* bound_context from Phase 1 */ },
"execution_plan": [ /* batches */ ],
"current_batch": 1,
"current_node": "N-001",
"last_checkpoint": null,
"node_states": { /* all nodes as pending */ },
"created_at": "<ISO>",
"updated_at": "<ISO>"
}Step 2.5 — Show Execution Start Banner
[wf-player] ============================================
[wf-player] Starting: <template.name>
[wf-player] Session: <session_id>
[wf-player] Context: goal="<value>"
[wf-player]
[wf-player] Plan: <N> nodes, <C> checkpoints
[wf-player] N-001 [skill] workflow-lite-plan
[wf-player] CP-01 [checkpoint] After Plan
[wf-player] N-002 [skill] workflow-execute
[wf-player] ============================================Success Criteria
<session_dir>/session-state.jsonwrittenexecution_planhas valid topological order- Status = "running"
Phase 3: Execute Loop
Objective
Execute each node batch in topological order. Use the correct mechanism per node type. Save state after every checkpoint. Support CLI serial-blocking with hook callback resume.
Pre-execution: Runtime Reference Resolution
Before executing each node, resolve any {N-xxx.field} and {prev_*} references in args_template:
function resolveArgs(args_template, node_id, session_state):
for each {ref} in args_template:
if ref matches {variable}:
replace with session_state.context[variable]
if ref matches {N-001.session_id}:
replace with session_state.node_states["N-001"].session_id
if ref matches {N-001.output_path}:
replace with session_state.node_states["N-001"].output_path
if ref matches {prev_session_id}:
find previous non-checkpoint node -> replace with its session_id
if ref matches {prev_output}:
find previous non-checkpoint node -> replace with its output_text
if ref matches {prev_output_path}:
find previous non-checkpoint node -> replace with its output_path
return resolved_argsNode Execution by Type
Read specs/node-executor.md for full details. Summary:
skill node
resolved_args = resolveArgs(node.args_template, ...)
mark node status = "running", write session-state.json
result = Skill(skill=node.executor, args=resolved_args)
extract from result: session_id, output_path, artifacts[]
update node_states[node.id]:
status = "completed"
session_id = extracted_session_id
output_path = extracted_output_path
artifacts = extracted_artifacts
completed_at = now()
write session-state.json
advance to next nodecommand node
Same as skill node but executor is a namespaced command:
Skill(skill=node.executor, args=resolved_args)cli node — CRITICAL: serial blocking
resolved_args = resolveArgs(node.args_template, ...)
mark node status = "running", write session-state.json
Bash({
command: `ccw cli -p "${resolved_args}" --tool ${node.cli_tool} --mode ${node.cli_mode} --rule ${node.cli_rule}`,
run_in_background: true
})
write session-state.json // persist "running" state
STOP — wait for hook callbackHook callback resumes here:
// Called when ccw cli completes
load session-state.json
find node with status "running"
extract result: exec_id, output_path, cli_output
update node_states[node.id]:
status = "completed"
output_path = extracted_output_path
completed_at = now()
write session-state.json
advance to next nodeagent node
resolved_args = resolveArgs(node.args_template, ...)
mark node status = "running", write session-state.json
result = Agent({
subagent_type: node.executor,
prompt: resolved_args,
run_in_background: node.run_in_background ?? false,
description: node.name
})
update node_states[node.id]:
status = "completed"
output_path = result.output_path or session_dir + "/artifacts/" + node.id + ".md"
completed_at = now()
write session-state.json
advance to next nodeParallel agent nodes (same parallel_group):
// Launch all agents in parallel
for each node in parallel_batch:
mark node status = "running"
Agent({
subagent_type: node.executor,
prompt: resolveArgs(node.args_template, ...),
run_in_background: true, // parallel
description: node.name
})
// Wait for all to complete (Agent with run_in_background=false blocks — use team-coordinate pattern)
// team-coordinate: spawn as team-workers with callbacks if complex
// For simple parallel: use multiple Agent calls synchronously or use team-coordinate's spawn-and-stopcheckpoint node
// Save snapshot
snapshot = {
session_id: session_state.session_id,
checkpoint_id: node.id,
checkpoint_name: node.name,
saved_at: now(),
node_states_snapshot: session_state.node_states,
last_completed_node: previous_node_id
}
write session-state.json (last_checkpoint = node.id)
write <session_dir>/checkpoints/<node.id>.json
if node.auto_continue == false:
// Pause for user
AskUserQuestion({
questions: [{
question: node.description + "\n\nReview checkpoint state and confirm to continue.",
header: "Checkpoint: " + node.name,
options: [
{ label: "Continue", description: "Proceed to next node" },
{ label: "Pause", description: "Save state and exit (resume later)" },
{ label: "Abort", description: "Stop execution" }
]
}]
})
on "Pause":
session_state.status = "paused"
write session-state.json
output "Session paused. Resume with: Skill(skill='wf-player', args='--resume <session_id>')"
EXIT
on "Abort":
session_state.status = "aborted"
write session-state.json
EXIT
// auto_continue or user chose Continue
mark checkpoint status = "completed"
write session-state.json
advance to next nodeProgress Display
After each node completes, print progress:
[wf-player] [2/5] CP-01 checkpoint saved ✓
[wf-player] [3/5] N-002 workflow-execute ... runningError Handling
On node failure (exception or skill returning error state):
on_fail = node.on_fail || "abort"
if on_fail == "skip":
mark node status = "skipped"
log warning
advance to next node
if on_fail == "retry":
retry once
if still fails: fall through to abort
if on_fail == "abort":
AskUserQuestion:
- Retry
- Skip this node
- Abort workflow
handle choice accordinglyLoop Termination
After last node in execution_plan completes:
- All node_states should be "completed" or "skipped"
- Proceed to Phase 4 (Complete)
Phase 4: Complete — Archive + Summary
Objective
Mark session complete, output execution summary with artifact paths, offer archive/keep options.
Workflow
Step 4.1 — Mark Session Complete
Load session-state.json.
Set:
{
"status": "completed",
"completed_at": "<ISO timestamp>"
}Write back to session-state.json.
Step 4.2 — Collect Artifacts
Aggregate all artifacts from node_states:
const artifacts = Object.values(node_states)
.filter(s => s.artifacts && s.artifacts.length > 0)
.flatMap(s => s.artifacts.map(a => ({ node: s.node_id, path: a })));
const outputPaths = Object.values(node_states)
.filter(s => s.output_path)
.map(s => ({ node: s.node_id, path: s.output_path }));Step 4.3 — Execution Summary
[wf-player] ============================================
[wf-player] COMPLETE: <template_name>
[wf-player]
[wf-player] Session: <session_id>
[wf-player] Context: goal="<value>"
[wf-player]
[wf-player] Nodes: <completed>/<total> completed
[wf-player] N-001 workflow-lite-plan ✓ (WFS-plan-xxx)
[wf-player] CP-01 After Plan ✓ (checkpoint saved)
[wf-player] N-002 workflow-execute ✓ (WFS-exec-xxx)
[wf-player] CP-02 Before Tests ✓ (checkpoint saved)
[wf-player] N-003 workflow-test-fix ✓ (WFS-test-xxx)
[wf-player]
[wf-player] Artifacts:
[wf-player] - IMPL_PLAN.md (N-001)
[wf-player] - src/auth/index.ts (N-002)
[wf-player] - test/auth.test.ts (N-003)
[wf-player]
[wf-player] Session dir: .workflow/sessions/<session_id>/
[wf-player] ============================================Step 4.4 — Completion Action
AskUserQuestion({
questions: [{
question: "Workflow complete. What would you like to do?",
header: "Completion Action",
options: [
{ label: "Archive session", description: "Move session to .workflow/sessions/archive/" },
{ label: "Keep session", description: "Leave session active for follow-up" },
{ label: "Run again", description: "Re-run template with same or new context" },
{ label: "Nothing", description: "Done" }
]
}]
})Archive:
- Move
<session_dir>to.workflow/sessions/archive/<session_id>/ - Update
session-state.jsonstatus = "archived"
Keep: No action, session stays at .workflow/sessions/<session_id>/
Run again:
- AskUserQuestion: "Same context or new?" → new context → re-enter Phase 1
Nothing: Output final artifact paths list, done.
Success Criteria
- session-state.json status = "completed" or "archived"
- All artifact paths listed in console output
- User presented completion action options
Node Executor — Execution Mechanisms per Node Type
Overview
Each node type uses a specific execution mechanism. This spec defines the exact invocation pattern.
1. skill node
Mechanism: Skill() tool — synchronous, blocks until complete.
Skill({
skill: "<node.executor>",
args: "<resolved_args>"
})Output extraction: Parse Skill() result for:
- Session ID pattern:
WFS-[a-z]+-\d{8}orTC-[a-z]+-\d{8} - Output path: last
.mdor.jsonfile path mentioned - Artifacts: all file paths in output
Session ID sources:
- Explicit: "Session: WFS-plan-20260317" in output
- Implicit: first session-like ID in output
Examples:
// Planning skill
Skill({ skill: "workflow-lite-plan", args: "Implement user authentication" })
// Execute skill (with prior session)
Skill({ skill: "workflow-execute", args: "--resume-session WFS-plan-20260317" })
// Test skill (with prior session)
Skill({ skill: "workflow-test-fix", args: "--session WFS-exec-20260317" })---
2. command node
Mechanism: Skill() tool with namespace command name — synchronous.
Skill({
skill: "<node.executor>", // e.g. "workflow:refactor-cycle"
args: "<resolved_args>"
})Examples:
Skill({ skill: "workflow:refactor-cycle", args: "Reduce coupling in auth module" })
Skill({ skill: "workflow:debug-with-file", args: "Login fails with 401 on valid tokens" })
Skill({ skill: "issue:discover", args: "" })
Skill({ skill: "issue:queue", args: "" })---
3. cli node
Mechanism: Bash() with run_in_background: true — STOP after launch, resume via hook callback.
// Build command
const prompt = resolveArgs(node.args_template, ...)
const cmd = `ccw cli -p "${escapeForShell(prompt)}" --tool ${node.cli_tool} --mode ${node.cli_mode} --rule ${node.cli_rule}`
// Launch background
Bash({ command: cmd, run_in_background: true })
// Save CLI task ID to node state for hook matching
node_state.cli_task_id = <captured from stderr CCW_EXEC_ID>
// Write session-state.json
// STOP — do not proceed until hook callback firesHook callback (triggered when ccw cli completes):
// Identify which node was running (status = "running" with cli_task_id set)
// Extract from CLI output:
// - output_path: file written by CLI
// - cli_exec_id: from CCW_EXEC_ID
// Mark node completed
// Advance to next nodeCLI output escaping:
function escapeForShell(s) {
// Use single quotes with escaped single quotes inside
return "'" + s.replace(/'/g, "'\\''") + "'"
}Example:
Bash({
command: `ccw cli -p 'PURPOSE: Analyze auth module architecture\nTASK: • Review class structure • Check dependencies\nMODE: analysis\nCONTEXT: @src/auth/**/*\nEXPECTED: Architecture report with issues list\nCONSTRAINTS: Read only' --tool gemini --mode analysis --rule analysis-review-architecture`,
run_in_background: true
})---
4. agent node
Mechanism: Agent() tool.
Single agent (serial):
Agent({
subagent_type: node.executor, // "general-purpose" or "code-reviewer"
prompt: resolveArgs(node.args_template, ...),
run_in_background: false, // blocks until complete
description: node.name
})Parallel agents (same parallel_group — use team-coordinate pattern):
// For 2-3 parallel agents: launch all with run_in_background: true
// Use SendMessage/callback or wait with sequential Skill() calls
// For complex parallel pipelines: delegate to team-coordinate
Skill({
skill: "team-coordinate",
args: "<description of parallel work>"
})Output extraction:
- Agent output is usually the full response text
- Look for file paths in output for
output_path
---
5. checkpoint node
Mechanism: Pure state management — no external calls unless auto_continue: false.
// 1. Write checkpoint snapshot
Write({
file_path: "<session_dir>/checkpoints/<node.id>.json",
content: JSON.stringify({
session_id, checkpoint_id: node.id, checkpoint_name: node.name,
saved_at: now(), context_snapshot: session_state.context,
node_states_snapshot: session_state.node_states,
last_completed_node: prev_node_id,
next_node: next_node_id
}, null, 2)
})
// 2. Update session state
session_state.last_checkpoint = node.id
node_states[node.id].status = "completed"
node_states[node.id].saved_at = now()
node_states[node.id].snapshot_path = checkpointPath
Write({ file_path: session_state_path, content: JSON.stringify(session_state, null, 2) })
// 3. If auto_continue = false: pause for user (see 03-execute.md)
// 4. If auto_continue = true: proceed immediately---
Context Passing Between Nodes
The runtime reference resolver in 03-execute.md handles {N-xxx.field} substitution.
Key resolved fields by node type:
| Node type | Exposes | Referenced as |
|---|---|---|
| skill | session_id | {N-001.session_id} |
| skill | output_path | {N-001.output_path} |
| skill | artifacts[0] | {N-001.artifacts[0]} |
| cli | output_path | {N-001.output_path} |
| agent | output_path | {N-001.output_path} |
| any | shorthand prev | {prev_session_id}, {prev_output_path} |
Fallback: If referenced field is null/empty, the args_template substitution results in empty string. The executor should handle gracefully (most skills default to latest session).
Session State Schema
File Location
.workflow/sessions/WFR-<slug>-<date>-<time>/session-state.json
Full Schema
{
"session_id": "WFR-feature-tdd-review-20260317-143022",
"template_id": "wft-feature-tdd-review-20260310",
"template_path": ".workflow/templates/feature-tdd-review.json",
"template_name": "Feature TDD with Review",
"status": "running | paused | completed | failed | aborted | archived",
"context": {
"goal": "Implement user authentication",
"scope": "src/auth"
},
"execution_plan": [
{ "batch": 1, "nodes": ["N-001"], "parallel": false },
{ "batch": 2, "nodes": ["CP-01"], "parallel": false },
{ "batch": 3, "nodes": ["N-002"], "parallel": false },
{ "batch": 4, "nodes": ["CP-02"], "parallel": false },
{ "batch": 5, "nodes": ["N-003a", "N-003b"], "parallel": true },
{ "batch": 6, "nodes": ["N-004"], "parallel": false }
],
"current_batch": 3,
"current_node": "N-002",
"last_checkpoint": "CP-01",
"node_states": {
"N-001": {
"status": "completed",
"started_at": "2026-03-17T14:30:25Z",
"completed_at": "2026-03-17T14:35:10Z",
"session_id": "WFS-plan-20260317",
"output_path": ".workflow/sessions/WFS-plan-20260317/IMPL_PLAN.md",
"artifacts": [
".workflow/sessions/WFS-plan-20260317/IMPL_PLAN.md"
],
"error": null
},
"CP-01": {
"status": "completed",
"saved_at": "2026-03-17T14:35:12Z",
"snapshot_path": ".workflow/sessions/WFR-feature-tdd-review-20260317-143022/checkpoints/CP-01.json",
"auto_continue": true
},
"N-002": {
"status": "running",
"started_at": "2026-03-17T14:35:14Z",
"completed_at": null,
"session_id": null,
"output_path": null,
"artifacts": [],
"error": null,
"cli_task_id": "gem-143514-x7k2"
},
"CP-02": {
"status": "pending",
"saved_at": null,
"snapshot_path": null
},
"N-003a": {
"status": "pending",
"started_at": null,
"completed_at": null,
"session_id": null,
"output_path": null,
"artifacts": [],
"error": null
},
"N-003b": { "status": "pending", "..." : "..." },
"N-004": { "status": "pending", "..." : "..." }
},
"created_at": "2026-03-17T14:30:22Z",
"updated_at": "2026-03-17T14:35:14Z",
"completed_at": null
}Status Values
| Status | Description |
|---|---|
running | Active execution in progress |
paused | User paused at checkpoint — resume with --resume |
completed | All nodes executed successfully |
failed | A node failed and abort was chosen |
aborted | User aborted at checkpoint |
archived | Completed and moved to archive/ |
Node State Status Values
| Status | Description |
|---|---|
pending | Not yet started |
running | Currently executing (may be waiting for CLI callback) |
completed | Successfully finished |
skipped | Skipped due to on_fail: skip |
failed | Execution error |
Checkpoint Snapshot Schema
.workflow/sessions/<wfr-id>/checkpoints/<CP-id>.json:
{
"session_id": "WFR-<id>",
"checkpoint_id": "CP-01",
"checkpoint_name": "After Plan",
"saved_at": "2026-03-17T14:35:12Z",
"context_snapshot": { "goal": "...", "scope": "..." },
"node_states_snapshot": { /* full node_states at this point */ },
"last_completed_node": "N-001",
"next_node": "N-002"
}Session Directory Structure
.workflow/sessions/WFR-<slug>-<date>-<time>/
+-- session-state.json # Main state file, updated after every node
+-- checkpoints/ # Checkpoint snapshots
| +-- CP-01.json
| +-- CP-02.json
+-- artifacts/ # Optional: copies of key artifacts
+-- N-001-output.md