Skip to main content

Multi-Phase Review Workflow

A workflow that implements features, reviews them, and iterates until approved.

Code

#!/usr/bin/env bun

import {
  createSmithersRoot,
  createSmithersDB,
  SmithersProvider,
  Phase,
  Step,
  Claude,
  Review,
  If,
  useSmithers,
} from "smithers-orchestrator";
import { useQueryValue } from "smithers-orchestrator/reactive-sqlite";

async function main() {
  const db = await createSmithersDB({ path: ".smithers/review-workflow" });

  // Resume if incomplete execution exists
  let executionId: string;
  const incomplete = await db.execution.findIncomplete();
  if (incomplete) {
    executionId = incomplete.id;
    console.log("Resuming execution:", executionId);
  } else {
    executionId = await db.execution.start("Review Workflow", "review-workflow.tsx");
  }

  function ReviewWorkflow() {
    const { db, reactiveDb } = useSmithers();

    // State in SQLite, reactive via useQueryValue
    const { data: phase } = useQueryValue<string>(
      reactiveDb,
      "SELECT value FROM state WHERE key = 'phase'"
    );
    const currentPhase = phase ?? "implement";

    const setPhase = (newPhase: string) => {
      db.state.set("phase", newPhase, `transition_to_${newPhase}`);
    };

    return (
      <>
        <If condition={currentPhase === "implement"}>
          <Phase name="Implementation">
            <Step name="implement">
              <Claude
                model="sonnet"
                allowedTools={["Read", "Edit", "Write", "Glob", "Grep"]}
                onFinished={() => setPhase("review")}
              >
                Implement the user authentication feature:
                1. Create a login form component
                2. Add authentication API endpoint
                3. Implement session management

                Follow existing patterns in the codebase.
              </Claude>
            </Step>
          </Phase>
        </If>

        <If condition={currentPhase === "review"}>
          <Phase name="Code Review">
            <Step name="review">
              <Review
                target={{ type: "diff", ref: "main" }}
                model="sonnet"
                criteria={[
                  "No security vulnerabilities",
                  "No hardcoded secrets or credentials",
                  "Input validation is comprehensive",
                  "Error handling covers edge cases",
                  "Code follows project conventions",
                ]}
                onFinished={(review) => {
                  if (review.approved) {
                    console.log("Review passed!");
                    setPhase("complete");
                  } else {
                    console.log("Review failed. Issues:");
                    review.issues.forEach(issue => {
                      console.log(`  [${issue.severity}] ${issue.file}: ${issue.description}`);
                    });
                    setPhase("implement");
                  }
                }}
              />
            </Step>
          </Phase>
        </If>

        {/* When phase is "complete", nothing renders, loop ends */}
      </>
    );
  }

  function App() {
    return (
      <SmithersProvider
        db={db}
        executionId={executionId}
        maxIterations={10}
        globalTimeout={3600000}
        onComplete={() => console.log("Workflow complete!")}
      >
        <ReviewWorkflow />
      </SmithersProvider>
    );
  }

  try {
    const root = createSmithersRoot();
    await root.mount(App);

    await db.execution.complete(executionId, {
      summary: "Review workflow completed",
      output: { finalPhase: db.state.get("phase") },
    });
  } catch (err) {
    const error = err instanceof Error ? err : new Error(String(err));
    await db.execution.fail(executionId, error.message);
    throw error;
  } finally {
    await db.close();
  }
}

main();

How It Works

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  ┌──────────────┐         ┌──────────────┐                 │
│  │  Implement   │────────▶│    Review    │                 │
│  │   (Claude)   │         │   (Review)   │                 │
│  └──────────────┘         └──────────────┘                 │
│         ▲                        │                          │
│         │                        │                          │
│         │    ┌───────────┐      │                          │
│         └────│ Not       │◀─────┘                          │
│              │ Approved  │       │                          │
│              └───────────┘       │                          │
│                                  │ Approved                 │
│                                  ▼                          │
│                          ┌──────────────┐                  │
│                          │   Complete   │                  │
│                          └──────────────┘                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

State Persistence

The workflow state is persisted to the database using SQLite:
// State is saved on each transition
db.state.set("phase", "review", "transition_to_review");

// State is read reactively via useQueryValue
const { data: phase } = useQueryValue<string>(
  reactiveDb,
  "SELECT value FROM state WHERE key = 'phase'"
);
const currentPhase = phase ?? "implement";
This approach ensures:
  • State survives process restarts
  • No stale closures (common with useState)
  • Automatic re-renders when state changes

Inspecting State

# View current state
smithers db state

# View transition history
smithers db transitions

Customization

Stricter Review Criteria

<Review
  criteria={[
    "No security vulnerabilities (OWASP Top 10)",
    "100% test coverage for new code",
    "All public APIs documented",
    "No TODO comments",
    "Performance considerations addressed",
  ]}
/>

Human Checkpoint

Add human approval before review:
<If condition={currentPhase === "pre-review"}>
  <Human
    message="Review implementation before AI review?"
    onApprove={() => setPhase("review")}
    onReject={() => setPhase("implement")}
  >
    Implementation complete. Ready for AI review?
  </Human>
</If>