Skip to content

fix: crash-resumed work-item runs must not rely on ambient cwd for agent dispatch - #619

Merged
getappz merged 1 commit into
masterfrom
task/191-opencode-agentflare-work-dispatch-doesn
Aug 27, 2026
Merged

fix: crash-resumed work-item runs must not rely on ambient cwd for agent dispatch#619
getappz merged 1 commit into
masterfrom
task/191-opencode-agentflare-work-dispatch-doesn

Conversation

@getappz

@getappz getappz commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #191: WorkflowEngine::recover() resumes non-terminal sdd_loop runs after a daemon restart by calling execute_workflow() directly, bypassing execute_work's run_in_worktree/EXECUTE_WORK_CWD_LOCK entirely (PR #601 only guards fresh dispatches from the job queue). A resumed run's agent dispatch still went through the ambient-cwd run_headless, so it silently inherited whatever worktree another concurrently-running item's chdir happened to have set — confirmed live on items #186/#187, both binding into task/186's worktree while task/187's own worktree sat completely untouched.

  • Added StepInvocation::cwd: Option<PathBuf> (crates/flare-workflow/src/json.rs).
  • Added WorkItemData::worktree_path: String (persisted, #[serde(default)]), threaded through run_or_resume/run_or_resume_with_sender from execute_work_impl's own claimed wpath.
  • build_sdd_loop_step sets StepInvocation.cwd from ctx.data.worktree_path on every implementer/judge invocation — read at execution time from persisted ctx.data, so a crash-resumed run still carries the right path.
  • real_agent_send_hook now dispatches via agent_launch::run_headless_in(cwd, ...) when cwd is Some, instead of the ambient-cwd run_headless — mirrors the pattern app_send_hook already uses for App workflows. This removes the dependency on global process cwd for this call path entirely (no lock needed — Command::current_dir is per-spawn, not shared mutable state).
  • Other StepInvocation consumers (agent_send_hook, the generic JSON-pipeline PromptExecutor) are unaffected — cwd: None preserves their existing ambient-cwd behavior.
  • Split execute_work_impl's dispatch-fixture tests out of work.rs into work_dispatch_fixture_tests.rs to stay under the file's LOC gate.

Test plan

  • New regression test sdd_loop_step_invocations_carry_the_item_s_own_worktree_path_as_cwd — captures every StepInvocation.cwd sent through run_or_resume_with_sender and asserts it equals the item's own claimed worktree; verified it fails without the fix (temporarily reverted, confirmed None != Some(worktree), then restored).
  • cargo test --bin agentflare cli::work:: — 61 passed (incl. the fix: serialize execute_work's worktree chdir against concurrent dispatch #601 cwd-race regression test and the fix: worktree stale-registration bug + item-pipeline metadata panic #550 worktree-error test).
  • cargo test --bin agentflare work_item_pipeline:: — 81 passed.
  • cargo test --bin agentflare workflow:: — 21 passed.
  • cargo test -p flare-workflow — 27 lib + 26 integration passed.
  • cargo check --workspace --all-targets, cargo clippy (touched crates), cargo fmt --check all clean.

Summary by CodeRabbit

  • Improvements

    • Work item workflows now consistently run agent actions in the correct project worktree.
    • Resumed workflows retain their project-specific working directory for more reliable execution.
    • Workflow dispatch remains stable across fresh and recovered runs.
  • Bug Fixes

    • Improved handling of pull request creation failures, including clearer failure recording and workflow state persistence.
  • Tests

    • Added regression coverage for working-directory isolation, workflow resumption, and dispatch error handling.

…ent dispatch

WorkflowEngine::recover() resumes non-terminal sdd_loop runs after a daemon
restart by calling execute_workflow() directly, bypassing execute_work's
run_in_worktree/EXECUTE_WORK_CWD_LOCK entirely (PR #601 only guards fresh
dispatches from the job queue). A resumed run's agent dispatch still went
through the ambient-cwd run_headless, so it silently inherited whatever
worktree another concurrently-running item's chdir happened to have set --
confirmed live on items #186/#187, both binding into task/186's worktree.

Thread the item's own worktree path through StepInvocation.cwd (persisted
on WorkItemData, read at step-execution time so a resumed run still has
it) and dispatch via run_headless_in instead, mirroring the pattern
app_send_hook already uses for App workflows. This removes the dependency
on global process cwd for this call path rather than trying to widen the
lock to cover the recovery path too.

Also splits the execute_work_impl dispatch-fixture tests out of work.rs
into work_dispatch_fixture_tests.rs to stay under the file's LOC gate.

Agentflare-Agent: claude-code
Agentflare-Branch: task/191-opencode-agentflare-work-dispatch-doesn
Agentflare-Item: 191
Agentflare-Session: 0be92ce2-29ad-46d0-9303-597ede893b7b
@coderabbitai

coderabbitai Bot commented Aug 27, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 839c020f-89cb-485b-9ea2-82e9a8f107c3

📥 Commits

Reviewing files that changed from the base of the PR and between b692c76 and 7fd9c35.

📒 Files selected for processing (8)
  • crates/flare-workflow/src/json.rs
  • src/cli/work.rs
  • src/cli/work_cwd_race_tests.rs
  • src/cli/work_dispatch_fixture_tests.rs
  • src/cli/work_worktree_error_tests.rs
  • src/work_item_pipeline.rs
  • src/work_item_pipeline/tests.rs
  • src/workflow.rs

Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.


📝 Walkthrough

Walkthrough

StepInvocation now carries an optional working directory. Workflow state persists the claimed worktree path, passes it through fresh and resumed runs, and uses it for agent subprocesses. Dispatch and regression tests cover path propagation and finalization behavior.

Changes

Worktree-aware workflow dispatch

Layer / File(s) Summary
Invocation and workflow state
crates/flare-workflow/src/json.rs, src/work_item_pipeline.rs
StepInvocation supports optional cwd. WorkItemData persists the worktree path. Fresh and resumed workflow entry points accept and seed this path. Role and judge invocations include it when available.
Worktree-aware dispatch execution
src/cli/work.rs, src/work_item_pipeline.rs, src/workflow.rs
execute_work_impl passes the claimed worktree path to the pipeline. Agent execution uses run_headless_in for explicit paths and retains ambient-cwd behavior when no path is set. Workflow send hooks ignore the new field while preserving dispatch behavior.
Dispatch integration and regression coverage
src/cli/work_dispatch_fixture_tests.rs, src/cli/work_cwd_race_tests.rs, src/cli/work_worktree_error_tests.rs, src/work_item_pipeline/tests.rs
Tests cover callback updates, worktree propagation, workflow metadata persistence, and PR finalization failure handling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 7fd9c

The change carries each work item's persisted worktree into resumed agent dispatch while preserving existing behavior for unaffected callers; the supplied checks pass and no actionable merge-blocking risk remains.

Sequence Diagram(s)

sequenceDiagram
  participant execute_work_impl
  participant run_or_resume_with_sender
  participant real_agent_send_hook
  participant AgentSubprocess
  execute_work_impl->>run_or_resume_with_sender: claimed worktree path
  run_or_resume_with_sender->>real_agent_send_hook: StepInvocation with cwd
  real_agent_send_hook->>AgentSubprocess: run_headless_in(worktree path)
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: preventing crash-resumed work-item runs from relying on the ambient working directory during agent dispatch.
Description check ✅ Passed The description explains the failure mode, implementation, compatibility behavior, regression coverage, and validation results. It omits the template's Notes for reviewers section and generic checklis…
Docstring Coverage ✅ Passed Docstring coverage is 84.21% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 8 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description explains the failure mode, implementation, compatibility behavior, regression coverage, and validation results. It omits the template's Notes for reviewers section and generic checklist entries, but the required technical information is otherwise complete.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task/191-opencode-agentflare-work-dispatch-doesn

Comment @coderabbitai help to get the list of available commands.

@getappz
getappz merged commit c5ba305 into master Aug 27, 2026
18 checks passed
@getappz
getappz deleted the task/191-opencode-agentflare-work-dispatch-doesn branch August 27, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant