Multi-Phase Review Workflow
A workflow that implements features, reviews them, and iterates until approved.Code
Copy
Ask AI
#!/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
Copy
Ask AI
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Implement │────────▶│ Review │ │
│ │ (Claude) │ │ (Review) │ │
│ └──────────────┘ └──────────────┘ │
│ ▲ │ │
│ │ │ │
│ │ ┌───────────┐ │ │
│ └────│ Not │◀─────┘ │
│ │ Approved │ │ │
│ └───────────┘ │ │
│ │ Approved │
│ ▼ │
│ ┌──────────────┐ │
│ │ Complete │ │
│ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
State Persistence
The workflow state is persisted to the database using SQLite:Copy
Ask AI
// 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";
- State survives process restarts
- No stale closures (common with useState)
- Automatic re-renders when state changes
Inspecting State
Copy
Ask AI
# View current state
smithers db state
# View transition history
smithers db transitions
Customization
Stricter Review Criteria
Copy
Ask AI
<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:Copy
Ask AI
<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>