Skip to main content
Each successful task attempt captures the current JJ change ID into _smithers_attempts.jj_pointer. revert restores the workspace to that state and discards any graph snapshots recorded after the attempt began, so the run’s timeline rolls back to the point-in-time of that attempt.
API reference: Time Travel lists every revert and time-travel export, its options, and links to source and tests.
bunx smithers-orchestrator revert workflow.tsx \
  --run-id RUN_ID --node-id NODE_ID [--attempt N=1] [--iteration N=0]
Revert restores files only; it doesn’t alter JJ history. The restoration creates a new change on top of the current working copy.

Requirements

  • JJ in PATH (brew install jj or cargo install jj-cli)
  • Workspace is a JJ repository (jj git init or jj init)
  • The target attempt was completed when JJ was available (otherwise no pointer was captured)

Programmatic

import { revertToAttempt, timeTravel } from "smithers-orchestrator";

const result = await revertToAttempt(adapter, {
  runId: "abc123",
  nodeId: "implement",
  attempt: 2,
  iteration: 0,
});
where adapter is the SmithersDb instance for the run’s database. revertToAttempt returns { success: false, error: string } if the attempt is not found or has no recorded JJ pointer (it does not throw for these cases). Inspect the returned result.success boolean to detect failures. On success it returns { success: true, jjPointer: string }.
type RevertOptions = {
  runId: string;
  nodeId: string;
  iteration: number;
  attempt: number;
  onProgress?: (event: SmithersEvent) => void;
};

type RevertResult = {
  success: boolean;
  error?: string;
  jjPointer?: string;
};

function revertToAttempt(adapter: SmithersDb, opts: RevertOptions): Promise<RevertResult>;
Use timeTravel when you want the higher-level reset flow: it can restore VCS, reset the target node, and reset dependent nodes after the selected attempt.
const reset = await timeTravel(adapter, {
  runId: "abc123",
  nodeId: "implement",
  attempt: 2,
  iteration: 0,
  resetDependents: true,
  restoreVcs: true,
});
type TimeTravelOptions = {
  runId: string;
  nodeId: string;
  iteration?: number;
  attempt?: number;
  resetDependents?: boolean;
  restoreVcs?: boolean;
  onProgress?: (event: SmithersEvent) => void;
};

type TimeTravelResult = {
  success: boolean;
  jjPointer?: string;
  vcsRestored: boolean;
  resetNodes: string[];
  error?: string;
};

function timeTravel(adapter: SmithersDb, opts: TimeTravelOptions): Promise<TimeTravelResult>;