Skip to content

refactor(workflow): make agent call lifecycle atomic - #120

Open
Waishnav wants to merge 2 commits into
pr/dw-cleanup-launch-errors-phasefrom
pr/dw-agent-call-transactions
Open

refactor(workflow): make agent call lifecycle atomic#120
Waishnav wants to merge 2 commits into
pr/dw-cleanup-launch-errors-phasefrom
pr/dw-agent-call-transactions

Conversation

@Waishnav

@Waishnav Waishnav commented Jul 27, 2026

Copy link
Copy Markdown
Owner

Agent-call status changes and their lifecycle events were persisted separately, so a database failure could leave the call record and workflow timeline disagreeing. Replay hits could also appear briefly as running, and worktree setup failures could happen before a matching call row existed.

Persist each call transition and its event in one SQLite transaction, including cached replay results. Create the call row before worktree setup so setup failures remain inspectable, and roll back the full transition whenever either write fails.

Stack

Based on #119. Review #121 after this PR.

Summary by CodeRabbit

  • New Features

    • Added support for recording and replaying cached workflow agent calls, including replay metadata and results.
    • Workflow agent call events are now persisted atomically with their status updates.
    • Failure records can include cleanup error details.
  • Bug Fixes

    • Improved consistency when agent-call event persistence fails, preventing partial records.
  • Refactor

    • Renamed the workflow call-starting API from beginAgentCall to startAgentCall.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: making the workflow agent call lifecycle atomic.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr/dw-agent-call-transactions

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/workflow-store.test.ts (1)

244-334: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Extend atomic rollback coverage to failAgentCall.

This test verifies rollback for startAgentCall, completeAgentCall, and cacheAgentCall, but failAgentCall (workflow-store.ts lines 819-847) was refactored the same way (row update + event insert in one transaction) and has no equivalent trigger-based rollback test here.

♻️ Suggested addition mirroring the existing pattern
     assert.equal(store.getAgentCall(atomicRun.id, 1), undefined);
     atomicDb.sqlite.exec(`drop trigger reject_agent_call_cached`);
+
+    atomicDb.sqlite.exec(`
+      create trigger reject_agent_call_failed
+      before insert on workflow_events
+      when new.type = 'agent_call_failed'
+      begin
+        select raise(abort, 'reject failed event');
+      end;
+    `);
+    assert.throws(() =>
+      store.failAgentCall({
+        runId: atomicRun.id,
+        callIndex: 0,
+        error: "boom",
+      }),
+    );
+    assert.equal(store.getAgentCall(atomicRun.id, 0)?.status, "from_cache");
+    atomicDb.sqlite.exec(`drop trigger reject_agent_call_failed`);
   } finally {
     atomicDb.close();
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/workflow-store.test.ts` around lines 244 - 334, Add trigger-based atomic
rollback coverage for failAgentCall in the existing atomicRun test: after
starting the call, create a workflow_events trigger rejecting agent_call_failed,
assert failAgentCall throws, and verify getAgentCall still reports status
"running"; drop the trigger, then complete the call and preserve the existing
cleanup and assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/workflow-store.test.ts`:
- Around line 244-334: Add trigger-based atomic rollback coverage for
failAgentCall in the existing atomicRun test: after starting the call, create a
workflow_events trigger rejecting agent_call_failed, assert failAgentCall
throws, and verify getAgentCall still reports status "running"; drop the
trigger, then complete the call and preserve the existing cleanup and
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: def862d1-dd83-468f-b121-abe381f368fb

📥 Commits

Reviewing files that changed from the base of the PR and between e55f20e and 4d958b3.

📒 Files selected for processing (5)
  • src/workflow-api.ts
  • src/workflow-engine.test.ts
  • src/workflow-store.test.ts
  • src/workflow-store.ts
  • src/workflow-ui.test.ts

@greptile-apps

greptile-apps Bot commented Jul 30, 2026

Copy link
Copy Markdown

Greptile Summary

This PR makes workflow agent-call state transitions and lifecycle events atomic.

  • Replaces beginAgentCall with transactional startAgentCall.
  • Persists replayed calls directly in their final cached state.
  • Creates call records before worktree setup so setup failures are retained.
  • Adds transactional completion and failure events, including cleanup-error details.
  • Adds rollback and lifecycle-event coverage.

Confidence Score: 3/5

The failure-persistence path needs correction before merging because it can mask the underlying call error and leave the call indefinitely marked as running.

The catch path invokes transactional failure persistence without guarding against an event-insertion error, so rollback preserves the running state and the persistence exception replaces the original provider or worktree failure.

Files Needing Attention: src/workflow-api.ts and src/workflow-store.ts

Important Files Changed

Filename Overview
src/workflow-api.ts Moves call creation ahead of worktree setup and delegates lifecycle transitions atomically, but an unhandled failure while recording a failed transition masks the original error.
src/workflow-store.ts Adds SQLite transactions coupling agent-call row mutations with lifecycle events; rollback can leave a failed invocation recorded as running when failure persistence itself errors.
src/workflow-store.test.ts Adds trigger-based tests confirming event-insertion failures roll back matching agent-call state changes.
src/workflow-engine.test.ts Updates setup-failure expectations to require a retained failed agent-call record.
src/workflow-ui.test.ts Updates the UI fixture to use the renamed call-starting API.

Sequence Diagram

sequenceDiagram
    participant API as Workflow API
    participant Store as Workflow Store
    participant DB as SQLite
    API->>Store: startAgentCall(...)
    Store->>DB: BEGIN IMMEDIATE
    Store->>DB: Insert running call
    Store->>DB: Insert agent_call_started
    Store->>DB: COMMIT
    alt call succeeds
        API->>Store: completeAgentCall(...)
        Store->>DB: Update call and insert completed event atomically
    else call fails
        API->>Store: failAgentCall(...)
        Store->>DB: Update call and insert failed event atomically
    else replay hit
        API->>Store: cacheAgentCall(...)
        Store->>DB: Insert cached call and event atomically
    end
Loading

Comments Outside Diff (1)

  1. src/workflow-api.ts, line 505-512 (link)

    P1 Failure persistence masks call errors

    When failAgentCall cannot insert its lifecycle event, its transaction rolls back the status update and the unguarded persistence exception replaces the original provider or worktree error. The call then remains permanently running in the UI and CLI because stale-run reaping does not reconcile agent-call rows.

Reviews (1): Last reviewed commit: "test(workflow): cover atomic agent call ..." | Re-trigger Greptile

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