Skip to content

Warp-Drive State Reference

The warp-drive state machine, exhaustively. State file shape, the state-machine CLI, and the full phase-transition table. Extracted from the warp-drive guide's internals section.

← docs home

Internals Reference

For contributors and power users.

State File

Location: <project>/.claude/.warp-drive-state.json

This is what state-machine.js init produces (with a few rows populated after the first transitions). Keep this in sync with the state object literal at the bottom of init() in scripts/warp-drive/state-machine.js.

json
{
  "version": 1,
  "session": {
    "started_at": "2026-05-08T15:56:59.401Z",
    "started_at_epoch": 1778255819402,
    "pid": 51506,
    "level": 3,
    "github_user": "paulirv"
  },
  "phase": "coding",
  "requirement": "42",
  "branch": "feature/issue-42-title",
  "chunk": { "index": 1, "total": 5, "acs": [["AC-01","AC-02"],["AC-03"]] },
  "checklist": {
    "docs_updated": false,
    "tests_passed": false,
    "committed": false,
    "report_filed": false
  },
  "budgets": {
    "phase_started_at": "2026-05-08T15:57:53.487Z",
    "retry_count": 0,
    "coding_cycles": 0
  },
  "aborted": false,
  "edit_counts": { "src/file.ts": 3 },
  "doom_loop_events": [],
  "gates": {
    "code_complete": { "semantic": "diff_relevance_check" },
    "docs_updated":  { "semantic": "ac_count_check" }
  },
  "completed_chunks": [],
  "history": [
    { "phase": "prerequisites", "at": "..." },
    { "phase": "discovering", "at": "...", "from": "prerequisites", "event": "prerequisites_ok" }
  ],
  "metrics": {
    "commits": 0,
    "reports_filed": 0,
    "tests_run": 0,
    "chunks_completed": 0,
    "session_duration_minutes": 0
  },
  "token_usage": {
    "session_total": null,
    "chunk_snapshots": [],
    "current_chunk_started_at": null
  },
  "main_branch": "master",
  "session_branch": null,
  "merge_target": "master",
  "merge_strategy": "ff-only"
}

Fields appear roughly in this order in the file. Notes on the less-obvious ones:

  • session.started_at_epoch and session.github_user are populated at init; the latter comes from gh api user -q .login (empty string if gh is unauthenticated, which silently disables @mention notifications).
  • aborted: false flips to true when the engine routes through the aborted phase. Cleanup messaging keys off this flag.
  • gates is seeded with the two semantic gates (diff_relevance_check, ac_count_check) plus any verification_gates from _workflow config. The targets arrays from config land alongside semantic on the matching event keys.
  • metrics.session_duration_minutes is updated when the engine writes the state — useful when reporting from warp status.
  • main_branch / session_branch / merge_target / merge_strategy are populated from ~/.claude/scripts/branch-detect.sh at init and consulted during merging.
  • After budget_exceeded, budgets gains exceeded_reasons, exceeded_at, and exceeded_from_phase to record the trip.

State Machine CLI

bash
node ~/.claude/scripts/warp-drive/state-machine.js <action> <project-root> [args]
ActionPurpose
initCreate new session: init <root> --level 2 --issue 42 --pid $PPID
statusShow current state (exit 2 if no session)
transitionMove phases: transition <root> <event> [--data '{"key":"val"}']
injectGet phase context for SessionStart hook
gateCheck if an operation is allowed: gate <root> git_commit
verifyRun verification gates: verify <root> code_complete
abortShorthand for transition <root> abort
resetDelete state file immediately

Transition Table

Every phase lists its valid events and where they lead. This matches the TRANSITIONS object in scripts/warp-drive/state-machine.js.

PhaseEventNext Phase
idlestartprerequisites
idleabortaborted
prerequisitesprerequisites_okdiscovering
prerequisitesabortaborted
discoveringwork_selectedplanning
discoveringno_worksession_ending
discoveringabortaborted
planningplan_readychunking
planningabortaborted
chunkingchunks_definedcoding
chunkingabortaborted
codingcode_completeupdating_docs
codingabortaborted
updating_docsdocs_updatedtesting
updating_docsabortaborted
testingtests_passedcommitting
testingtests_failedcoding
testingabortaborted
committingcommittedreporting
committingcommit_with_doc_gatedoc_drift_check
committingabortaborted
doc_drift_checkdrift_cleanreporting
doc_drift_checkdrift_blockedcoding
doc_drift_checkabortaborted
reportingreport_filedchunk_complete
reportingabortaborted
chunk_completenext_chunkcoding
chunk_completerequirement_donerequirement_complete
chunk_completeabortaborted
requirement_completemerge_readymerging
requirement_completeabortaborted
mergingmergedawaiting_continue
mergingmerge_failedmerging
mergingpush_failedmerging
mergingabortaborted
awaiting_continuecontinue_yesdiscovering
awaiting_continuecontinue_nosession_ending
awaiting_continueabortaborted
session_endingsession_endedcompleted
session_endingabortaborted
budget_exceededbudget_continuecoding
budget_exceededbudget_abortaborted
budget_exceededabortaborted
abortedabort_resolvedcompleted
abortedabort_cleanup_failedcompleted
abortedrestartidle

Budget-trigger reasons. When an enforced budget trips, the engine routes the current phase into budget_exceeded and records the reason on state.budgets.exceeded_reasons. The reasons are:

ReasonSourceDefault ThresholdConfig Key
phase_timeoutPhase elapsed too long30 minmax_phase_minutes (+ phase_timeout_enforcement)
retry_exceededPer-chunk retry counter exceeded5 retriesmax_retries_per_chunk
coding_cycles_exceededCode/test cycles for this chunk exceeded3 cyclesmax_coding_cycles
no_progressConsecutive identical failed attempts — same failure signature AND no new diff (stagnation, not raw attempts)3 attemptsmax_no_progress
total_chunks_exceededChunks completed in this session exceeded hard limit20 chunksmax_total_chunks
session_timeoutTotal session duration exceeded hard limit480 minmax_session_minutes

phase_timeout is only enforced (rather than a soft warning) when phase_timeout_enforcement is block or abort — see Configuration. The other five are always enforced.