# Execution thread When a run stops partway through a plan and a later run resumes it, the state file holds two partial histories rather than one complete one. The execution thread is how Hankweave reconciles them: a newest-first walk across the continuation chain that answers the questions the runtime actually asks, such as which codon runs next, whether the thread has failed, and which session a `continue-previous` codon should resume. This page is a source-level reference for that reconstruction. It defines the thread's data types, walks through the analysis algorithm and its continuation edge cases, and ends with how to exercise the logic using replay. It assumes you know what a run and a codon are in passing; where a concept has its own home, the page links out rather than re-teaching it. ## How runs form an execution thread An execution thread is the newest-first history Hankweave reconstructs across a chain of runs: the current run's codons plus retained codons from continuation ancestors. A run is a recorded pass through a codon plan, and a codon is an individual agent task. A hank is the configured work description whose codons form that plan. A checkpoint – a recorded git state associated with a codon – carries checkpoint metadata, and a rig – a codon's setup step – can produce a `rig-setup` checkpoint. To trace this reconstruction in 0.10.0, start with `server/execution-thread.ts`, `server/state-manager.ts`, and `server/types/state-types.ts`. Source references use repository-relative paths such as `server/execution-thread.ts`, not package import specifiers. The entry points are `CheckpointInfo`, `ThreadCodon`, `ExecutionThread` and its `failed` getter, `analyzeExecutionThread`, `getNextCodonId`, `findContinuationSessionId`, and `StateManager.getExecutionThread`. The sections below follow that order: first the data a thread is made of, then the failure rule, then the walk that builds it, then the lookups and the consumer that tie it into the runtime. Declarations and signatures are copied from the tagged source, with behavior notes for reading or extending the implementation. The package exports only `.`, `./schemas`, and `./types`. These definitions are therefore source-reference material, not consumer imports. See [client and exported types](/0.10.0/files/integrate/client-and-exported-types) for the public export contract. > **Pitfall:** `hankweave/server/execution-thread` is not an importable path. Read the source at its repository-relative path and tag instead. ## Which fields identify a thread codon ### `CheckpointInfo` `CheckpointInfo` records the kind and git metadata of a checkpoint associated with a codon. Its `type` is one of `rig-setup`, `completed`, `error`, or `skipped`; the record also contains a SHA, message, ISO 8601 timestamp, and branch. ```ts export interface CheckpointInfo { type: "rig-setup" | "completed" | "error" | "skipped"; sha: string; message: string; timestamp: string; // ISO 8601 timestamp branch: string; } /** * A codon with its complete context */ export interface ThreadCodon { // The codon data codon: CodonExecution; // Run context runId: RunId; runStatus: "running" | "completed" | "failed" | "crashed"; runStartTime: string; runEndTime: string | null; // null for running runs, string for completed runs gitBranch: string; // Position in execution history globalIndex: number; // 0 = latest codon across all runs runIndex: number; // Which run this came from (0 = latest run) codonIndexInRun: number; // Position within that run // All checkpoints for this codon with validation validatedCheckpoints: CheckpointInfo[]; // Derived information continuationSessionId: SessionId | null; // Session ID this codon continued from, null if none } /** ``` The `validatedCheckpoints` list on each thread codon is filtered against git, not trusted from state alone. Validation keeps only checkpoint SHAs present in the supplied git checkpoint-data map. A state-file checkpoint missing from git is dropped, and omitting checkpoint data produces an empty `validatedCheckpoints` list. [Checkpoints](/0.10.0/files/concepts/checkpoints) explains the checkpoint lifecycle; [the state-file reference](/0.10.0/files/reference/state-file) owns persisted run data. ### `ThreadCodon` `ThreadCodon` carries one codon together with its run context, position in the reconstructed history, validated checkpoints, and `continuationSessionId`. The thread is newest-first: `globalIndex` 0 is the most recently executed codon across all runs, `runIndex` 0 is the latest run, and larger run indexes move up the continuation chain. The walk retains each codon's source `codonIndexInRun` while visiting a run from its last index toward zero, so a codon's position in the thread and its position in its original run are both recoverable. When present, loop membership is carried by the `codon` value's `loopContext`: `loopId`, zero-based `iteration`, and `codonIndexInLoop`. `continuationSessionId` comes from `previousSessionId` when that field is present; otherwise it is `null`. ## How the thread reports failure ### `ExecutionThread` `ExecutionThread` stores the reconstructed codons, total run count, running-codon flag, and the already-selected `nextCodonId`; all constructor fields have defaults. `failed` is a derived getter rather than stored state, and its rule is narrower than "some run failed". ```ts export class ExecutionThread { constructor( public codons: ThreadCodon[] = [], public totalRuns: number = 0, public hasRunningCodon: boolean = false, public nextCodonId: CodonId | null = null, ) {} /** * Check if the execution thread is in a failed state. * * The thread is considered failed only if: * 1. The most recent codon explicitly has status "failed" * 2. OR the run crashed/failed while a codon was still running (non-terminal state) * * Historical runs being marked as "failed" (e.g., due to server shutdown after * successful codon completion) should NOT cause the thread to be considered failed. */ get failed(): boolean { // If there are no codons, the thread is not failed if (this.codons.length === 0) { return false; } // Check only the most recent codon (index 0, since thread is in reverse order) const mostRecent = this.codons[0]; // Thread is failed if the most recent codon explicitly failed if (mostRecent.codon.status === "failed") { return true; } // Thread is failed if the run crashed/failed while a codon was still running // (codon wasn't terminal when run ended) if ( (mostRecent.runStatus === "failed" || mostRecent.runStatus === "crashed") && !isTerminalCodonStatus(mostRecent.codon.status) ) { return true; } return false; } } // ------------- // Main Analysis Function - Simplified Algorithm // ------------- /** * Analyze execution history to build a unified thread with all metadata. * * @param state - The complete Hankweave state (including executionPlan) * @param checkpointData - Map of SHA to git checkpoint data (optional) * @param targetRunId - Specific run to analyze (defaults to latest) * @param logger - Optional logger for debugging * @returns Complete execution thread with all metadata preserved ``` The getter is true when the most recent codon explicitly has status `failed`, or when the latest run is `failed` or `crashed` while that codon is non-terminal. The statuses `completed`, `failed`, and `skipped` are terminal; `preparing`, `starting`, `initializing`, `running`, and `completing-sentinels` are not, so `hasRunningCodon` means "not yet terminal" rather than only `running`. A failed status in a superseded historical run does not, by itself, fail the thread. [Resume, rollback, and retry](/0.10.0/files/operate/resume-rollback-and-retry) uses this state during recovery. ## How the cross-run walk chooses history ### `analyzeExecutionThread` `analyzeExecutionThread` is the function that builds everything above. It starts with the run named by `targetRunId`, or with `state.runs[0]` when no target is supplied. Runs are stored latest-first. With no runs it returns an empty thread. It visits the selected run's codons backward from the last index, then follows each continuation's `startingConditions.source.runId` to its parent. A visited-run set prevents a cycle from extending the walk. ```ts export async function analyzeExecutionThread( state: HankweaveState, checkpointData?: Map, targetRunId?: RunId, logger?: Logger, ): Promise { // Get execution plan from state const executionPlan = state.executionPlan; // Find starting run const startRun = targetRunId ? state.runs.find((r) => r.runId === targetRunId) : state.runs[0]; // Latest run is first if (!startRun) { logger?.log("No runs found for execution thread analysis", "debug"); return new ExecutionThread([], 0, false, null); } // Initialize thread building const codons: ThreadCodon[] = []; const visited = new Set(); let currentRun: Run | null = startRun; let untilCodon = startRun.codons.length - 1; // Start by including all codons let runIndex = 0; let globalIndex = 0; let hasRunningCodon = false; // Process runs following the continuation chain while (currentRun && !visited.has(currentRun.runId)) { visited.add(currentRun.runId); logger?.log( `Processing run ${currentRun.runId} (status: ${currentRun.status}, ` + `codons: ${currentRun.codons.length}, including up to index ${untilCodon})`, "debug", ); // Process codons in this run (backwards, from untilCodon to 0) for (let i = untilCodon; i >= 0; i--) { const codon = currentRun.codons[i]; // Check if this is a running codon if (!isTerminalCodonStatus(codon.status)) { hasRunningCodon = true; } // Build checkpoint information with git metadata const validatedCheckpoints = buildCheckpointInfo(codon, checkpointData); // Extract continuation session ID if present const continuationSessionId: SessionId | null = "previousSessionId" in codon && codon.previousSessionId ? codon.previousSessionId : null; // Build the thread codon entry with all metadata const threadCodon: ThreadCodon = { codon, runId: currentRun.runId, runStatus: currentRun.status, runStartTime: currentRun.startTime, runEndTime: currentRun.endTime || null, gitBranch: currentRun.gitBranch, globalIndex, runIndex, codonIndexInRun: i, validatedCheckpoints, continuationSessionId, }; codons.push(threadCodon); globalIndex++; } // Check if this run is a continuation and move to parent if (currentRun.startingConditions.type === "continuation") { const source = currentRun.startingConditions.source; const parentRunId: RunId = source.runId; const afterCodon = source.afterCodon; const checkpointSha = source.checkpointSha; // Find parent run const parentRun = state.runs.find((r: Run) => r.runId === parentRunId); if (!parentRun) { logger?.log(`Parent run ${parentRunId} not found, ending chain`, "info"); break; } // Calculate untilCodon for the parent run if (!afterCodon) { // Continuation from beginning - exclude all codons from parent untilCodon = -1; } else { // Find the codon in parent run const afterCodonIndex = parentRun.codons.findIndex( (p: CodonExecution) => p.codonId === afterCodon, ); if (afterCodonIndex === -1) { logger?.log( `Codon ${afterCodon} not found in parent run ${parentRunId}, including all codons`, "info", ); untilCodon = parentRun.codons.length - 1; } else { const afterCodonData = parentRun.codons[afterCodonIndex]; // Check if it's a rig-setup continuation if ( "rigSetupCheckpoint" in afterCodonData && afterCodonData.rigSetupCheckpoint === checkpointSha ) { // Rig setup continuation - exclude the codon that will be re-run untilCodon = afterCodonIndex - 1; logger?.log( `Rig setup continuation for ${afterCodon}, excluding it from parent`, "debug", ); } else { // Normal continuation - include up to and including afterCodon untilCodon = afterCodonIndex; logger?.log( `Normal continuation after ${afterCodon}, including codons up to index ${afterCodonIndex}`, "debug", ); } } } // Move to parent run currentRun = parentRun; runIndex++; } else { // Fresh start - we're done break; ``` The continuation branch at the end of the loop is where the walk decides how much of a parent run to keep. For a normal continuation, the parent contributes codons through and including `afterCodon`. If the parent codon's `rigSetupCheckpoint` equals `source.checkpointSha`, the rig-setup continuation stops before that codon because it will be run again. `afterCodon: null` contributes no parent codons. A missing parent ends the chain with a log message; if `afterCodon` is absent from the parent, the walk logs the condition and includes all of that parent's codons. ![Parent codon retention rules during continuation walk](/content-assets/cf45dff5691c48c0/diagrams/contribute-execution-thread/1.svg) Parent codon retention rules during continuation walk
Diagram as text ```text +-------------------------+ | startingConditions.type | +-----+-------------+-----+ fresh | | continuation v v +--------------+ +------------------------------+ | end the walk | | inspect source.afterCodon | +--------------+ +----+-----------+-----------+-+ | | | afterCodon is null | matches a | | normal | rigSetupCheckpoint | continuation v v v +--------------------+ +--------------------+ +--------------------+ | untilCodon = -1 | | untilCodon = | | untilCodon = | | (exclude all | | afterCodonIndex - 1| | afterCodonIndex | | parent codons) | | (exclude afterCodon| | (include through | +---------+----------+ +---------+----------+ | afterCodon) | | | +---------+----------+ +----------------------+----------------------+ v +------------------------+ | move to the parent run | +------------------------+ ```
After the walk, a separate block selects `nextCodonId`, the codon the runtime would execute if it continued from here. ```ts let nextCodonId: CodonId | null = null; // Don't suggest next codon if the current run failed if (startRun.status === "failed") { // TODO nextCodonId = null; } else if (!hasRunningCodon && codons.length > 0) { const latestCodon = codons[0]; // Check if we're continuing from a rig-setup checkpoint // This happens when the latest run is a continuation that will re-run a codon if (startRun.startingConditions.type === "continuation") { const { afterCodon, checkpointSha } = startRun.startingConditions.source; // Check if this continuation is from a rig-setup checkpoint if (afterCodon && codons.length === 0) { // TODO // No codons executed yet in continuation run // Check if the continuation is from rig-setup const sourceRun = state.runs.find( (r) => r.runId === ( startRun.startingConditions as { type: "continuation"; source: { runId: RunId }; } ).source.runId, ); if (sourceRun) { const sourceCodon = sourceRun.codons.find((p) => p.codonId === afterCodon); if ( sourceCodon && "rigSetupCheckpoint" in sourceCodon && sourceCodon.rigSetupCheckpoint === checkpointSha ) { // Rig-setup continuation - next codon is the same codon nextCodonId = afterCodon; } } } } // If not rig-setup continuation, find next codon in execution plan if (!nextCodonId) { const codonIndex = executionPlan.findIndex((e) => e.codonId === latestCodon.codon.codonId); if (codonIndex >= 0 && codonIndex < executionPlan.length - 1) { nextCodonId = executionPlan[codonIndex + 1].codonId; } } } else if (!hasRunningCodon && codons.length === 0) { // No codons executed yet if (startRun.startingConditions.type === "continuation") { const { afterCodon, checkpointSha } = startRun.startingConditions.source; if (!afterCodon) { // Continuation from beginning nextCodonId = executionPlan[0]?.codonId ?? null; } else { // Check if it's a rig-setup continuation const sourceRun = state.runs.find( (r) => r.runId === ( startRun.startingConditions as { type: "continuation"; source: { runId: RunId }; } ).source.runId, ); if (sourceRun) { const sourceCodon = sourceRun.codons.find((p) => p.codonId === afterCodon); if ( sourceCodon && "rigSetupCheckpoint" in sourceCodon && sourceCodon.rigSetupCheckpoint === checkpointSha ) { // Rig-setup continuation - re-run the same codon nextCodonId = afterCodon; } else { // Normal continuation - run next codon after afterCodon const codonIndex = executionPlan.findIndex((e) => e.codonId === afterCodon); if (codonIndex >= 0 && codonIndex < executionPlan.length - 1) { nextCodonId = executionPlan[codonIndex + 1].codonId; } } } } } else { // Fresh run - start with first codon nextCodonId = executionPlan[0]?.codonId ?? null; } } ``` The decision tree has three outcomes worth remembering. `nextCodonId` is `null` when the selected start run is `failed`. A rig-setup continuation selects the same codon again; otherwise the walk selects the execution-plan successor of the latest thread codon. An empty fresh run starts at `executionPlan[0]`. When all codons are complete, `nextCodonId` is `null`; a re-invoked server logs `all codons completed` and exits 0 without naming the execution. The walk reads each run's continuation information from the `StartingConditions` union, which distinguishes a fresh run from a continuation. A fresh value may contain `initialCheckpointSha`; a continuation names `source.runId`, `afterCodon`, and `checkpointSha`, and may record `reason` as `retry`, `rollback`, or `continue`. ```ts export type StartingConditions = | { type: "fresh"; initialCheckpointSha?: string; // SHA of the initial checkpoint commit } | { type: "continuation"; source: { /** * Which run we're continuing from. * * Used by: Building run relationships tree */ runId: RunId; /** * Which codon to continue after. * null means start from beginning of that run. * * Example: "codon-2" means start from codon-3 * Used by: Determining next codon to execute */ afterCodon: CodonId | null; /** * Git commit SHA we restored to. * This is the exact state we're continuing from. * * Used by: Verifying correct restoration */ checkpointSha: string; }; /** * Human-readable reason for continuation. * Optional metadata for UI/analytics. * * Used by: Understanding user patterns */ reason?: "retry" | "rollback" | "continue"; }; ``` The capture below shows what this looks like in practice: a normalized excerpt of `state.json` after a kill-and-resume, not a literal `HankweaveState` serialization. Its `latestRun` key is a capture-added convenience key that duplicates `runs[0]`, not a state field; the `runs[]` entries retain the continuation-chain evidence. The continuation run appears first and contains `write-second`; its parent contains completed `write-line` and failed `write-second`. The captured server log beneath it shows the thread the analyzer builds from that state: first one codon across two runs with `write-second` as next, then two codons with nothing left to run. ```text { "currentRunId": null, "latestRun": { "runId": "", "status": "completed", "startingConditions": { "type": "continuation", "source": { "runId": "", "afterCodon": "write-line", "checkpointSha": "" }, "reason": "rollback" }, "codons": [ { "codonId": "write-second", "status": "completed", "exitCode": 0 } ] }, "runs": [ { "runId": "", "status": "completed", "startingConditions": { "type": "continuation", "source": { "runId": "", "afterCodon": "write-line", "checkpointSha": "" }, "reason": "rollback" }, "codons": [ { "codonId": "write-second", "status": "completed", "exitCode": 0 } ] }, { "runId": "", "status": "completed", "startingConditions": { "type": "fresh" }, "codons": [ { "codonId": "write-line", "status": "completed", "exitCode": 0 }, { "codonId": "write-second", "status": "failed", "exitCode": -1 } ] } ] } ``` ```text [] [DEBUG] Built execution thread: 1 codons across 2 runs, next codon: write-second [] [DEBUG] Built execution thread: 1 codons across 2 runs, next codon: write-second … [] [DEBUG] Built execution thread: 2 codons across 2 runs, next codon: none [] [DEBUG] Built execution thread: 2 codons across 2 runs, next codon: none [] [DEBUG] Built execution thread: 2 codons across 2 runs, next codon: none ``` See [checkpoints](/0.10.0/files/concepts/checkpoints) for checkpoint records and [resume, rollback, and retry](/0.10.0/files/operate/resume-rollback-and-retry) for continuation procedures. ## How a continuation finds its session Two small lookups sit on top of the finished thread. One reads the plan position the analyzer already chose; the other finds the agent session a `continue-previous` codon should resume. ### `getNextCodonId` `getNextCodonId(thread)` returns the `nextCodonId` computed during analysis; it does not recompute the plan position. ```ts export function getNextCodonId(thread: ExecutionThread): CodonId | null { // Simply return what was already calculated at the thread level return thread.nextCodonId || null; } /** * Find session ID for continuing a specific codon */ export function findContinuationSessionId( thread: ExecutionThread, codonId: CodonId, state: HankweaveState, ): SessionId | null { const executionPlan = state.executionPlan || []; const entry = executionPlan.find((e) => e.codonId === codonId); // Only continue-previous codons need a session if (!entry || entry.codon.continuationMode !== "continue-previous") { return null; } // Find the codon before this one in the execution plan const entryIndex = executionPlan.findIndex((e) => e.codonId === codonId); if (entryIndex <= 0) return null; const previousCodonId = executionPlan[entryIndex - 1].codonId; // Find the most recent execution of the previous codon for (const threadCodon of thread.codons) { if (threadCodon.codon.codonId !== previousCodonId) continue; const codon = threadCodon.codon; // Must have a session ID if (!("claudeSessionId" in codon) || !codon.claudeSessionId) continue; // Check if it's valid for continuation if (codon.status === "completed") { return codon.claudeSessionId; } if ( codon.status === "skipped" && "assistantMessageCount" in codon && codon.assistantMessageCount && codon.assistantMessageCount > 0 ) { return codon.claudeSessionId; } } return null; } ``` ### `findContinuationSessionId` `findContinuationSessionId(thread, codonId, state)` returns `null` unless the plan entry requests `continue-previous`. It then scans the thread newest-first for the previous plan codon and returns its session only when that codon is `completed`, or is `skipped` with `assistantMessageCount > 0`. The state fields are literally `claudeSessionId`, `claudeLogPath`, and `claudePid` for the Claude SDK and Pi SDK harnesses at 0.10.0. Pi session ids are translated into the Claude-shaped `session_id` message field before storage; the `claude*` prefix is a naming remnant, not evidence of shims. The reconstruction's `previousSessionId` and this lookup's `claudeSessionId` are separate fields: the former populates `continuationSessionId`, while the latter is returned for a valid previous codon. For the execution directory used by a continuation, the checkpoint store is a shadow git repository at `/.hankweave/checkpoints/.hankweavecheckpoints`; here `` denotes that execution directory, with the git directory redirected there and the working tree at `agentRoot/`. A session is the per-codon agent conversation identified by `claudeSessionId`/`SessionId`. [The state-file reference](/0.10.0/files/reference/state-file) owns persisted fields; [client and exported types](/0.10.0/files/integrate/client-and-exported-types) covers the public consumer surface. ## Where the thread is consumed ### `StateManager.getExecutionThread` `StateManager.getExecutionThread` is the runtime-facing wrapper around the analyzer. It accepts an optional target run and defaults `includeCheckpointValidation` to `true`. It builds the git checkpoint-data map only when validation is requested and `CheckpointGit` is initialized. If `state.executionPlan` is empty during startup, it synthesizes an effective plan from `codonConfigs` before calling the analyzer. ```ts * @param targetRunId - Optional run ID to start from (defaults to latest) * @param includeCheckpointValidation - Whether to validate checkpoints against git * @returns Complete execution thread with all metadata * * NOTE: The codonConfigs fallback exists for initialization timing issues where the plan * hasn't been built yet (e.g., during HankweaveRuntime.start() before startNewRun()). */ async getExecutionThread( targetRunId?: RunId, includeCheckpointValidation = true, ): Promise { // Get checkpoint data if requested and available const checkpointData = includeCheckpointValidation && this.checkpointGit?.isInitialized() ? await this.getCheckpointDataMap() : undefined; let effectivePlan: ExecutionCodonEntry[]; if (this.state.executionPlan.length > 0) { effectivePlan = this.state.executionPlan; } else { // Fallback: Convert codonConfigs to ExecutionCodonEntry format // This treats each config as a single execution entry with no loop context effectivePlan = (this.codonConfigs || []).map((config) => ({ codon: config.type === "loop" ? config.codons[0] : config, codonId: CodonIdConstructor(config.id), loopContext: undefined, })); } // If using a custom plan different from stored state, create temporary state const stateToAnalyze: ST.HankweaveState = effectivePlan !== this.state.executionPlan ? { ...this.state, executionPlan: effectivePlan } : this.state; return analyzeExecutionThread(stateToAnalyze, checkpointData, targetRunId, this.logger); ``` The runtime consumes the thread to resolve a `continue-previous` session before a codon starts, search for rollback targets across runs, advance `autoStartNextCodon`, and perform the startup failure check. When `thread.failed` is true at startup, the runtime logs `Execution thread failed, rolling back...` and calls `rollbackToLastSuccess`. If that startup rollback cannot find its target in the archive manifest, the resulting `Target checkpoint … not found in manifest` failure belongs to [resume, rollback, and retry](/0.10.0/files/operate/resume-rollback-and-retry), which documents the failure mode. ## How to exercise the thread with replay Reading the source is one way to understand the walk; watching it run against a recorded execution is another. Clone the `SouthBridgeAI/hankweave-runtime` repository at tag `v0.10.0`; the implementation is `server/execution-thread.ts`. A multi-run thread is produced when a hank is killed or fails mid-plan and resumes with `-e/--execution `. Resume-by-state uses the execution-directory option; there is no `--resume` flag. ### `--replay` supplies a provider-free run `--replay ` re-runs a recorded execution without provider contact. Since 0.5.6, replay skips model self-tests and requires no API keys, making it a provider-free way to exercise thread and resume logic. The flag is parsed but absent from `--help` at 0.10.0; [the CLI reference](/0.10.0/files/reference/cli) owns its flag contract. > **VersionNote:** `--replay` exists since 0.5.6 but is parsed-yet-absent from `--help` at 0.10.0. Replay always starts a fresh run and ignores existing state, logging `[REPLAY] Starting fresh run (replay mode ignores existing state)`. It therefore does not reconstruct an existing multi-run state; resume-by-state with `-e/--execution ` is the path described above for that. The recorded state and logs under `` remain replay's input. ### Replay reads recorded files Replay loads `/.hankweave/state.json`. For each codon, it resolves the log through that codon's recorded `claudeLogPath`, normalizing path separators for portability. Missing logs cause `[ReplayLoader] N codon log file(s) not found`. Lookup first uses the runtime codon id and falls back to the base codon id for older loop-suffixed ids; a missing log never falls back to real execution. When explicit paths are absent, replay discovers the hank configuration and data path from `/.hankweave/execution-meta.json`, using `hankPath` and `readOnlySourceDataPath`. That metadata has schema version `1.1.0`, changed in 0.5.0, and includes `hankweaveVersion` plus `environment.{invocationMethod,platform,arch,osRelease,runtime}`. Its own `version: "1.1.0"` is separate from `hankweaveVersion`, so the metadata and Hankweave `0.10.0` are independently versioned. [Execution directory](/0.10.0/files/reference/execution-directory) owns the complete metadata contract. [The CLI reference](/0.10.0/files/reference/cli) owns flag syntax; [resume, rollback, and retry](/0.10.0/files/operate/resume-rollback-and-retry) connects replay with recovery.