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

Summary

  • write agent-call state changes and matching lifecycle events in one SQLite transaction
  • record replay hits atomically without an intermediate running row
  • create the call row before worktree setup so setup failures retain a matching failed call record
  • add rollback coverage for started, completed, and cached lifecycle events

Validation

  • npm test
  • npm run build

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

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: adef446c-1591-43a3-9f71-7b1bd1bab10d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ 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