feat(workflows): run Ralph stages from optional git worktree - #1068
Conversation
Review: Optional Ralph worktree supportThanks for the well-scoped change — the worktree plumbing is generally clean, the env-var scrubbing is the right call for hook contexts, and Bugs / correctness
Goal worker contract
Test coverage gaps
Minor / nits
What looks good
Overall: solid foundation, but the cleanup/re-run gap and the silent-fallback behavior are worth fixing before merge — the rest can be follow-ups. |
ReviewThanks for this PR — the worktree feature is a nice addition for isolating Ralph runs, and the test coverage of the new code paths is genuinely solid (relative path, absolute path, occupied-path failure, re-run, and null-byte fallback all exercised against a real git repo). Findings grouped by priority. High priority
Medium priority
Low priority / nits
Things I liked
Verification I did not do
Overall: the worktree mechanics are well-thought-out, but the indentation issue, the silent-data-loss path, and the unrelated formatting churn in goal.ts should be addressed before merge. |
PR Review —
|
Code Review — Ralph git worktree supportNice, well-structured change: detached-HEAD worktree lifecycle, env-var sanitization, real-git integration tests, and explicit user recovery commands when things go wrong. Most of the critical paths (path resolution, null-byte fallback, fail-fast on dirty target, preserve-on-failure) have direct integration coverage. A handful of concerns worth addressing before merge: Findings[P1] Successful workflow result is discarded if worktree cleanup fails [P2] `WORKER_PREFLIGHT_CONTRACT` duplicates `project_initialization_preflight` in `ralph.ts` [P2] Missing CHANGELOG entry [P2] `if (Date.now() < 0) { await ralphCtx.task(...) }` is fragile
Today's pattern works, but the next reader will treat it as a typo and try to delete it. [P2] `runGit` uses `spawnSync` and blocks the event loop [P3] Recovery command JSON-quotes paths — not shell-safe [P3] Detached-HEAD PR handoff doesn't verify auth from the worktree [P3] Type cast `ctx as WorkflowRunContext` swallows API drift [P3] Fallback-path collision risk is documented in the input but not in code Test coverageSolid. The integration tests genuinely exercise `git worktree add/remove` with real repos and verify both happy-path cleanup and failure preservation. Two small gaps worth filling:
Nits
Overall: ship-worthy after addressing the cleanup-vs-result issue [P1] and the duplicated prompt contract [P2]. The remaining items are quality-of-life. |
|
placeholder - real review below |
|
placeholder superseded by the review comment below |
|
Review — feat(workflows): run Ralph stages from optional git worktree Overall this is a thoughtful change: clear scope (no behavior change when git_worktree_dir is empty), good lifecycle separation between successful runs (clean up) and failed runs (preserve + recovery command), and real-git integration coverage. The preflight contract extraction in goal.ts is also reasonable. A few items below — most are minor; the dead-code block and the cleanup-failure semantics are the two I would want addressed before merge. Findings [P1] Unreachable In packages/workflows/builtin/ralph.ts, inside the top-level .run handler, there is an always-false guard whose body calls [P1] Cleanup failure in the When [P2]
[P2] Silent fallback when
[P3] The new constant in goal.ts and the orchestrator [P3] Two adjacent
[P3] At the top of the .run handler, Tests Integration coverage is solid (real git repo fixtures, relative + absolute paths, happy-path cleanup, fail-fast on bad path, rerun, fallback, preservation-on-failure). A couple of gaps worth considering:
Smaller nits
— Reviewed against CLAUDE.md (Bun-only, no build step for workflows, raw .ts, ESM .js import specifiers — all respected). |
PR Review: feat(workflows): run Ralph stages from optional git worktreeNice scope — small surface, real isolation benefit, and the helper extraction + tests are solid. A few correctness and policy notes below. High-priority issues1. Dead fallback branch in After the Either:
No integration test exercises the fallback either, which is consistent with it being unreachable. 2. Force-removing the worktree on "success" can silently destroy work when the PR stage fails to push (
This is the opposite of the PR's stated guarantee ("failed runs preserve it for recovery"). The user only learns after the fact, because the cleanup path doesn't warn on success. Suggested fix: have the PR stage return a structured signal (e.g. via a 3. Missing CHANGELOG entry
Medium-priority4. const workflowCtx: WorkflowRunContext<RalphInputs> = {
...ralphCtx,
task: (name, options) => ralphCtx.task(name, options),
parallel: (steps, options) => ralphCtx.parallel(steps, options),
};The comment says "Discovery validates workflow shape without executing helpers, so this live adapter keeps direct stage primitive calls visible while the helper owns the real orchestration body." If that's an actual constraint of the workflow discovery system, please leave a code reference to the validator that needs this — otherwise this looks like dead indirection and should be removed (just pass 5. Recovery error message can mislead on concurrent runs ( The thrown error suggests "If this path is an orphaned Ralph worktree from an interrupted run, recover or remove it." When two Ralph runs target the same path concurrently (which the PR description warns against), the second run's failure message will tell the user to remove the first run's live worktree. Consider softening to "another Ralph run, or an orphaned worktree from an interrupted run." Minor / nits6. 7. Pre-existing but in your diff: model config 8. Spec path writes to host repo while orchestrator runs in worktree cwd ( Things that are good
|
Code reviewSolid PR overall — clean separation between worktree lifecycle and the workflow body, comprehensive integration tests, and the no-worktree path is preserved as a true no-op. A few things worth flagging: Correctness / bugs
Code quality
Performance
Test coverageThe new integration suite is genuinely good — covers cleanup, preservation, fail-fast, recovery guidance, and repeat-runs. A few gaps:
SecurityGenerally fine — null bytes are rejected, Nit
Nothing blocking — the substring-match issue (#1) and the Windows quoting (#3) are the most concrete defects worth addressing before merge. |
Claude Code ReviewSolid, well-scoped change — the worktree lifecycle is preserve-by-default on every failure mode I can see, the recovery commands are surfaced in both errors and warnings, and the integration test suite is genuinely thorough (8 tests covering relative/absolute paths, non-repo, occupied path, null bytes, missing base branch, multi-iteration, cleanup-failure, and preserve-on-throw). The Bugs / correctness1. PR description ↔ implementation mismatch on relative-path resolution. const repoRoot = requireGitRepositoryForWorktree(cwd);
const requestedWorktreeDir = resolveWorktreePath(trimmed, repoRoot);The input 2. 3. Stale
4. Code smell — the
|
Review — Ralph git worktree supportThanks for this — the worktree isolation, the evidence-based PR cleanup signal, and the broad integration test matrix are all great. A few comments below, mostly around robustness and minor polish. Correctness / behavior
Minor
Tests
Style / conventions
Overall: solid, well-tested change. The two items I'd most want addressed before merge are (1) a defensive check for uncommitted/unpushed commits before cleanup, and (2) updating the |
Code Review —
|
Code Review — PR #1068 (Ralph git worktree support)Nice piece of work: scope is well-contained, the Correctness / bugs1. 2. PR-stage prompt assumes a reused worktree is detached HEAD. 3. Race / footgun4. TOCTOU between Style / nits5. Worker stages inherit the un-scrubbed Git env. 6. PR description references a `test/unit/discovery.test.ts` update that isn't in the changed-files list. 7. Missing trailing comma. 8. `as WorkflowRunContext` cast in the run wrapper. TestsCoverage is solid: relative/absolute path, fail-fast outside repo, missing base branch, non-empty non-git dir, null-byte rejection, multi-iteration cwd propagation, failed-run persistence, reuse with uncommitted state, retry without cleanup. Things that aren't covered and would harden the contract:
Nice-to-haves; the existing tests cover the headline contract well. SecurityNo new shell-injection surface — `spawnSync(["worktree","add",...])` passes args as an array, so user-supplied paths aren't shell-interpreted. The null-byte rejection in `resolveWorktreePath` is a nice guard. No new credentials or secrets touched. Performance`spawnSync` blocks the event loop, but only for one-shot bookkeeping calls (`rev-parse --show-toplevel`, `worktree add`, `rev-parse --is-inside-work-tree`). Acceptable. CLAUDE.md compliance
SummarySolid PR overall. The biggest item worth addressing before merge is #1 (worktree-vs-repo identity check); the rest is quality-of-life polish. |
Code Review —
|
Review —
|
|
Claude Code Review — PR #1068 Thanks for this — the worktree feature is well-scoped and the integration test coverage is excellent. Notes below, organized by severity. Finding 1 — Empty-graph validation is a behavior change for callers of The PR description says "Breaking Changes: None," but moving the empty-graph check from discovery to If
The user-facing experience also changes: previously a no-stage workflow was filtered at discovery (never showed up). Now it appears in the catalogue and only fails when the user picks it. That trade-off is worth being explicit about in CHANGELOG. Finding 2 — Partial-creation retry path produces an unhelpful error (severity: low) In That error message has no recovery hint, unlike the initial failure path which references Finding 3 —
Finding 4 — Worktree creation race between concurrent Ralph runs (severity: low) The PR description acknowledges shared worktrees by design, but the creation race is a different case: two Ralph runs that both see Finding 5 — Windows quote-escaping in
Finding 6 — Subtle In the parallel discovery block (around lines 1450-1452 of Security
Test coverage Excellent — the 10 integration tests cover most realistic states. A few gaps to consider, none blocking:
Smaller things
Summary The core design ( Nice work. — Generated with Claude Code (Opus 4.7) |
Code Review —
|
Review —
|
Code Review (atomic-monorepo conventions)Solid PR overall — the Bugs / correctness
Style / conventions (per CLAUDE.md)
Test coverage
Performance / Security
Process
🤖 Generated with Claude Code |
Code Review — feat(workflows): Ralph git worktree supportReviewed the Ralph worktree integration, shared preflight prompt, and the discovery/runtime validation refactor. Overall: focused, well-tested PR with clean fail-fast semantics, sensible "Claude Code-style" no-lock reuse model, and good defense against shell injection via A few findings worth considering before merge: Bugs / Correctness[P2] [P2] [P3] Robustness[P3] [P3] Design observations (not blockers)
Test coverageCoverage of the new worktree paths is good:
Gaps worth filling:
Style / conventionsThe PR adheres to the repo's Bun + raw-TS conventions, uses Nice work on the artifact-vs-worktree path split (specs stay under invocation cwd, stages run from worktree cwd) — that's exactly the right division for retry/inspection ergonomics. 🤖 Generated with Claude Code |
PR Review — feat(workflows): run Ralph stages from optional git worktreeReviewed against Likely-genuine issues1. Discovery validation probe now executes user/project workflow
The PR description treats this as an internal cleanup, but it's a real behavior change for downstream workflow authors: any user-authored workflow that follows this very natural pattern will leak temp dirs, fire spawns, and possibly hit the network on every CLI startup. Two suggestions:
2. Probe rejects workflows that conditionally create stages based on input. .run(async (ctx) => {
if (ctx.inputs.feature_enabled) {
await ctx.task("foo", { ... });
}
})will be rejected with 3. Smaller items4. Probe sentinel can be swallowed by user 5. Misleading error when 6. PR-stage prompt assumes detached HEAD. 7. Bundled-only shape validation means user workflows now pay an async-discovery cost. Test coverage — strong
Nits
SummaryThe Ralph worktree feature itself is well-designed, well-tested, and ships with helpful error messages and recovery commands. The two items I'd most want addressed before merge are (1) the silent side-effect change for non-bundled workflow discovery and (2) the conditional-stage false-negative — both are correctness/UX regressions vs. the previous behavior for user workflow authors. (3) dead code is a quick cleanup. |
Review for PR #1068 —
|
ReviewSolid, well-scoped PR. The worktree integration is implemented as a tight, fail-fast surface around Ralph; the discovery refactor replaces a brittle regex with a real observation probe; and test coverage (especially the 12 real-Git fixture integration tests) is excellent. A handful of concerns worth considering before merge. Code quality & correctness
TOCTOU between
Inherited Discovery validation probeReal
TestsCoverage is genuinely strong here. Two minor nits:
Nits
SummaryLGTM with the caveats above. The |
Review of #1068 — Ralph git worktree + discovery probe refactorThanks for the well-documented PR. Test coverage is excellent — 12 new integration tests plus thorough unit coverage of the discovery probe semantics. I focused on the moving parts that have non-obvious runtime implications. Findings below, prioritized P1–P3 per the repo's reviewer norms. [P1] Discovery now executes user workflow bodies at startup
Notes:
Suggestions: (a) document the contract loudly above [P2]
|
Code Review — PR #1068 (
|
Review: Optional Ralph worktree + workflow cwd plumbingSolid follow-up on the earlier review pass. The same-repository worktree classification, stable spec file across iterations, and fail-fast guards directly address the cleanup/silent-fallback concerns from the prior round. Arg-array Bugs / correctness
Code quality / maintainability
Security / safety
Test coverage
Nits
Overall the worktree plumbing reads cleanly, the safety guards are well-thought-out, and the test bed is genuinely good. The biggest items I'd consider before merging are #1 (stale baseline on resume) and #3 (spec outside worktree → not in PR diff), since both affect end-user output. |
Add git_worktree_dir support so Ralph can create a detached worktree from the comparison base and execute planner, orchestrator, discovery, review, and PR stages from that checkout. Also strengthen goal worker instructions to perform evidence-based repository setup discovery before implementation work. Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
Assistant-model: GPT-5.5
ea0b935 to
26f15d4
Compare
PR Review: feat(workflows): run Ralph stages from optional git worktreeOverall a well-scoped change with strong test coverage (12 new integration tests with a real Git fixture, plus expanded unit coverage for the SDK seams). The fail-fast guards (null-byte rejection, foreign-repo detection, missing base branch) are appropriately defensive, and the move to shape-only discovery with runtime empty-graph validation is a nice tightening of the contract. A few notes below. Correctness
Performance
Minor / nits
TestsThe new integration tests ( SecurityPath handling is solid: null-byte rejection, foreign-repo detection via LGTM in spirit. The env-sanitization gap is the only one I'd consider blocking unless the PR description is updated to drop that claim; the others are polish or follow-up. |
Code Review: feat(workflows): run Ralph stages from optional git worktreeReviewed the implementation, executor wiring, worktree primitive, builder API, and the new test surface. Overall this is well-scoped, defensively coded, and very well tested — the integration suite exercises a broad set of failure modes against real Git fixtures, and the input-binding builder API is a clean way to thread reusable worktree defaults without polluting every stage call. The PR description matches the implementation, breaking-change story holds (default A few items below worth addressing before/after merge. Bugs / correctness
Code quality / API
Tests
Nits
Nice work overall — the worktree primitive itself is the highlight, with good symlink handling, clear error messaging, and careful Git env scrubbing. The performance issue in #1 is the only finding I'd block on for production use of Ralph with reusable worktrees. |
* feat(workflows): run Ralph stages from optional worktree Add git_worktree_dir support so Ralph can create a detached worktree from the comparison base and execute planner, orchestrator, discovery, review, and PR stages from that checkout. Also strengthen goal worker instructions to perform evidence-based repository setup discovery before implementation work. Assistant-model: GPT-5.5 * fix(workflows): harden Ralph worktree lifecycle Assistant-model: GPT-5.5 * fix(workflows): preserve Ralph worktrees on failure Assistant-model: GPT-5.5 * test(workflows): make Ralph worktree checks portable Assistant-model: GPT-5.5 * fix(workflows): require git repo for Ralph worktrees Assistant-model: GPT-5.5 * fix(workflows): preserve Ralph result on cleanup failure Assistant-model: GPT-5.5 * fix(workflows): preserve unpushed Ralph worktrees Assistant-model: GPT-5.5 * fix(workflows): harden Ralph worktree cleanup markers Assistant-model: GPT-5.5 * test(workflows): canonicalize Ralph worktree paths Assistant-model: GPT-5.5 * fix(workflows): reuse Ralph worktrees without cleanup Assistant-model: GPT-5.5 * test(workflows): escape null-byte fixture Assistant-model: GPT-5.5 * fix(workflows): lock Ralph worktree runs Assistant-model: GPT-5.5 * revert(workflows): remove Ralph worktree lock Assistant-model: GPT-5.5 * fix(workflows): validate empty graphs at runtime Assistant-model: GPT-5.5 * fix(workflows): reject foreign Ralph worktrees Assistant-model: GPT-5.5 * docs(workflows): clarify Ralph worktree sharing Assistant-model: GPT-5.5 * test(workflows): remove cwd-global test coupling Assistant-model: GPT-5.5 * fix(workflows): validate empty workflow graphs at startup Assistant-model: GPT-5.5 * fix(workflows): clarify validation and worktree diagnostics Assistant-model: GPT-5.5 * fix(workflows): revise Ralph specs in place Assistant-model: GPT-5.5 * fix(workflows): thread named workflow cwd Assistant-model: GPT-5.5 * fix(workflows): fail closed on Ralph path canonicalization Assistant-model: GPT-5.5 * fix(workflows): keep discovery side-effect free Assistant-model: GPT-5.5 * test(workflows): avoid generated path interpolation Assistant-model: GPT-5.5 * feat(workflows): add reusable git worktree bindings * test(workflows): normalize worktree temp paths
Summary
Adds an optional `git_worktree_dir` input to the Ralph workflow so stages can run from a detached Git worktree instead of the caller's checkout. Pairs with side-effect-free workflow discovery, runtime empty-graph validation, and `ctx.cwd` exposure to replace the previous static source-inspection approach.
Key Changes
Ralph Workflow (`packages/workflows/builtin/ralph.ts`)
Worktree Bindings (`packages/workflows/src/runs/shared/worktree.ts`)
Executor (`packages/workflows/src/runs/foreground/executor.ts`)
Workflow Discovery (`packages/workflows/src/extension/discovery.ts`)
Shared Prompts (`packages/workflows/builtin/shared-prompts.ts`)
Deep-Research Workflow (`packages/workflows/builtin/deep-research-codebase.ts`)
Tests
Breaking Changes
None — `git_worktree_dir` defaults to `""` preserving existing behavior. The workflow SDK authoring API and compiled `WorkflowDefinition` shape are unchanged.