feat(ralph): parallel dual-reviewer, structured output, and infra discovery - #623
Conversation
Adds guideline #9 instructing the reviewer agent to respect AGENTS.md and CLAUDE.md conventions, flagging deviations only when they conflict with correctness or security. Assistant-model: Claude Code
…covery, and branch-relative changeset Replace the sequential confirmation-pass review strategy with two parallel reviewer stages that must both agree the code is clean before the loop terminates. Each SDK uses its native structured output mechanism (Claude: outputFormat, Copilot: defineTool with Zod, OpenCode: format.json_schema) validated against a shared ReviewResultSchema. Add three parallel infrastructure-discovery sub-agents (codebase-locator, codebase-analyzer, codebase-pattern-finder) that dynamically explore the repo's build/test/lint/CI infrastructure before review — the reviewer then uses those findings to run verification commands. Replace `safeGitStatusS` with `captureBranchChangeset` which computes a full diff relative to the auto-discovered parent branch (main/master/ develop), capturing both committed and uncommitted changes with structured error propagation instead of silent failures. Assistant-model: Claude Code
Code Review — Ralph workflow robustnessNice direction overall — replacing Bugs1. Claude SDK result field is raw = String((msg as Record<string, unknown>).output ?? "");
2. Reviewer sub-agent is bypassed on Claude (high) — Every other stage calls 3. Unvalidated cast of structured = (msg as Record<string, unknown>).structured_output as ReviewResult;
Design concerns4. Cost/latency: three discovery sub-agents + two reviewers per iteration Infra discovery (locator + analyzer + pattern-finder) is invoked every loop iteration, but the build/test infrastructure of a repo doesn't change between iterations. Up to 10 iterations × 5 sub-agents = 50 extra calls for data that's identical after iteration 1. Hoist discovery out of the loop (or memoize the discovery context after iteration 1). Same argument for 5. Two reviewers seeing the same prompt will largely flag the same issues. 6. Verification step assumes the reviewer has Bash
7. Base-branch discovery only checks local heads —
Smaller items
Test coverageCLAUDE.md calls out TDD and Style / conventionsConsistent with CLAUDE.md otherwise — Bun APIs ( Happy to help with a follow-up patch for items 1-3 if useful — those are the only ones I'd consider merge-blocking. |
Summary
Significantly hardens the Ralph workflow across all three SDK adapters (Claude, Copilot, OpenCode) by replacing the sequential confirmation-pass review loop with a parallel dual-reviewer strategy, adding SDK-native structured output validation, introducing parallel infrastructure-discovery sub-agents, and upgrading git context from a working-tree snapshot to a full branch-relative changeset.
Key Changes
Parallel Dual-Reviewer (all adapters)
CONSECUTIVE_CLEAN_THRESHOLD = 2) with two simultaneous reviewer stages (reviewer-${iteration}-aandreviewer-${iteration}-b)mergeReviewResults()unions findings from both reviewers and takes the more conservativeoverall_correctnessverdictSDK-Native Structured Output
claudeSdkQuerywithoutputFormat: { type: "json_schema", schema: REVIEW_RESULT_JSON_SCHEMA }— no manual JSON parsingdefineTool("submit_review", { parameters: ReviewResultSchema })(Zod-validated tool handler) — each parallel reviewer gets its own isolated tool instanceformat: { type: "json_schema", schema: REVIEW_RESULT_JSON_SCHEMA }on the session prompt callReviewFindingSchemaandReviewResultSchemaZod schemas inhelpers/prompts.ts;REVIEW_RESULT_JSON_SCHEMAderived viaz.toJSONSchema()Parallel Infrastructure Discovery
buildInfraDiscoveryPrompts()generates prompts for three sub-agents that run in parallel before each review:codebase-locator,codebase-analyzer, andcodebase-pattern-finderBranch-Relative Changeset (
helpers/git.ts)safeGitStatusS()(justgit status -s) withcaptureBranchChangeset(), which captures:git diff <merge-base>...HEAD --statand--name-status(committed changes from branch point)git diff --stat(uncommitted staged/unstaged changes)git status -s(working tree snapshot)discoverBaseBranch()that auto-detects the parent branch (main/master/develop) by finding the closest merge-baseBranchChangeset.errorsand surfaced to the reviewer rather than silently returning empty stringsReviewer Agent Norms Guideline
.claude,.github,.opencode): reviewers must respect project-level norms fromAGENTS.md/CLAUDE.mdand flag deviations only when they conflict with correctness or security, not personal preference