Skip to main content

Phases API

The db.phases module tracks workflow phases. Phases group related steps and provide high-level progress tracking.

Contract

  • Sync: All methods are synchronous.
  • Return shape: raw rows with snake_case fields.
  • Time: Timestamps are ISO strings (not Date).

Overview

import { createSmithersDB } from "smithers-orchestrator";

const db = createSmithersDB({ path: ".smithers/my-workflow" });

// Start a phase
const phaseId = db.phases.start("implementation", 0);

// Complete the phase
db.phases.complete(phaseId);

Methods

start

Starts a new phase.
function start(name: string, iteration?: number): string
name
string
required
The name of the phase.
iteration
number
default:"0"
The Ralph iteration number (for tracking across loop iterations).
Returns: The phase ID.

complete

Marks a phase as completed.
function complete(id: string): void
id
string
required
The phase ID to complete.

fail

Marks a phase as failed.
function fail(id: string): void

current

Gets the currently active phase.
function current(): Phase | null

list

Lists all phases for an execution.
function list(executionId: string): Phase[]

Phase Type

interface Phase {
  id: string;
  execution_id: string;
  name: string;
  iteration: number;
  status: 'pending' | 'running' | 'completed' | 'skipped' | 'failed';
  started_at: string | null;
  completed_at: string | null;
  duration_ms: number | null;
  agents_count: number;
  created_at: string;
}

Usage with the Phase Component

The <Phase> component automatically integrates with this module:
import { Phase, Step } from "smithers-orchestrator";

<SmithersProvider db={db} executionId={executionId}>
  <Phase name="research">
    <Step name="research">
      <Claude>Research the topic.</Claude>
    </Step>
  </Phase>

  <Phase name="implementation">
    <Step name="implement">
      <Claude>Implement the feature.</Claude>
    </Step>
  </Phase>

  <Phase name="testing">
    <Step name="test">
      <Claude>Write and run tests.</Claude>
    </Step>
  </Phase>
</SmithersProvider>

Multi-Iteration Phases

Phases track their iteration number for workflows that loop:
<SmithersProvider db={db} executionId={executionId} maxIterations={5}>
  <Phase name="implement">
    {/* This phase will be tracked with iteration 0, 1, 2, etc. */}
    <Step name="implement">
      <Claude>Implement the feature.</Claude>
    </Step>
  </Phase>
</SmithersProvider>
Query phases by iteration:
const phases = db.phases.list(executionId);

// Group by iteration
const byIteration = phases.reduce((acc, phase) => {
  if (!acc[phase.iteration]) acc[phase.iteration] = [];
  acc[phase.iteration].push(phase);
  return acc;
}, {});

// Check iteration 2 progress
const iteration2 = byIteration[2] || [];
const completed = iteration2.filter((p) => p.status === "completed");

State-Driven Phases

Common pattern with database state:
import { useSmithers } from "smithers-orchestrator";
import { useQueryValue } from "smithers-orchestrator/reactive-sqlite";

function StateDrivenWorkflowBody() {
  const { db, reactiveDb } = useSmithers();
  const { data: phaseJson } = useQueryValue<string>(
    reactiveDb,
    "SELECT value FROM state WHERE key = 'currentPhase'"
  );
  const phase = phaseJson ? JSON.parse(phaseJson) : null;

  return (
    <>
      <If condition={phase === "implement"}>
        <Phase name="Implementation">
          <Step name="implement">
            <Claude onFinished={() => db.state.set("currentPhase", "review")}>
              Implement the feature.
            </Claude>
          </Step>
        </Phase>
      </If>

      <If condition={phase === "review"}>
        <Phase name="Review">
          <Step name="review">
            <Review
              onFinished={(r) => {
                if (r.approved) {
                  db.state.set("currentPhase", "complete");
                } else {
                  db.state.set("currentPhase", "implement");
                }
              }}
            />
          </Step>
        </Phase>
      </If>
    </>
  );
}

export function StateDrivenWorkflow({ db, executionId }) {
  return (
    <SmithersProvider db={db} executionId={executionId} maxIterations={10}>
      <StateDrivenWorkflowBody />
    </SmithersProvider>
  );
}

Querying Phases

// Get current phase
const currentPhase = db.phases.current();
if (currentPhase) {
  console.log(`Current phase: ${currentPhase.name}`);
}

// List all phases
const allPhases = db.phases.list(executionId);

// Calculate total duration
const totalDuration = allPhases
  .filter((p) => p.duration_ms)
  .reduce((sum, p) => sum + p.duration_ms!, 0);

// Find failed phases
const failed = allPhases.filter((p) => p.status === "failed");