Skip to content

fix(cos): start the PR page's Resolve & merge agent immediately - #6068

Merged
atomantic merged 1 commit into
mainfrom
cos/task-mtlko6vu/agent-d09f43a9
Sep 3, 2026
Merged

fix(cos): start the PR page's Resolve & merge agent immediately#6068
atomantic merged 1 commit into
mainfrom
cos/task-mtlko6vu/agent-d09f43a9

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

Pressing Resolve & merge on an app's Pull Requests tab queued the review-loop follow-up as an auto-approved system task and then left it to the CoS dequeue. That tier (spawnDequeuePriority2AutoApproved) only spawns system tasks while CoS auto-run is in execute and under its daily action budget — so on any other setting the task sat pending until it was started by hand from the task page, which is exactly what the button existed to avoid.

The click is the approval, so /resolve now dispatches the follow-up itself through the same force-spawn path as the task list's Run now button (cos.forceSpawnTask), suppressing the racing dequeue via suppressDequeue — the pattern cosJobRoutes.js already uses for a manually triggered job.

When the spawn genuinely can't proceed (no agent slots, daemon stopped/paused, runner unreachable) the task stays queued in place and the response reports the reason instead of claiming an agent is on it; the tab's toast then says "Started an agent to…" or names what it's waiting for.

Also fixes a related silent gap found while wiring this: a follow-up the task store rejected as a duplicate persisted nothing under the id the service had minted, so callers reported (and would have force-spawned) a task that did not exist. The service now returns the already-queued record with duplicate: true.

Changes

  • server/services/agentWorktreeCleanup.jsspawnReviewLoopFollowUp gains dispatch: 'queue' | 'immediate'. queue (default) keeps the autonomous lane exactly as it was; immediate suppresses the dequeue, force-spawns, and reports dispatch: { started, reason }. Duplicate rejections return the existing task.
  • server/routes/apps/pullRequests.js/resolve passes dispatch: 'immediate' and surfaces started + queueReason in the response.
  • client/src/components/apps/tabs/PullRequestsTab.jsx — toast/tooltip/help text report what actually happened; a queued-but-not-started result gets the neutral toast with its reason.

Autonomous follow-ups (worktree cleanup, prWatcher escalation) are untouched — the run that produced their PR was itself autonomous, so its continuation stays under the auto-run gate and budget.

Test plan

  • server/services/cleanupAgentWorktree.test.js — default dispatch leaves the spawn to the dequeue (suppressDequeue: false, no force-spawn); immediate dispatch suppresses the dequeue and force-spawns the new task id; a refused spawn reports its reason with the task still queued; a duplicate rejection returns the queued record instead of force-spawning a phantom id.
  • server/routes/apps/pullRequests.test.js — the route requests an immediate dispatch and reports started: true; a refused dispatch reports started: false + queueReason; a store-rejected duplicate is reported as such.
  • client/src/components/apps/tabs/PullRequestsTab.test.jsx — "Started an agent…" on success; the waiting reason surfaced on the neutral toast with the row still showing Queued.
  • Full server suite: 38,426 passed / 14 skipped. Full client suite: 10,161 passed / 2 skipped. biome lint clean.

https://claude.ai/code/session_01JErGn4inLCwQiWtXc99m2o

Resolve & merge on an app's Pull Requests tab queued the review-loop
follow-up as an auto-approved SYSTEM task and then waited for the CoS
dequeue to pick it up. That tier only spawns system tasks while CoS
auto-run is in `execute` and under its daily action budget, so the task
sat `pending` until it was started by hand from the task page — the one
thing the button existed to avoid.

Pressing the button is the approval, so the route now dispatches the
follow-up itself through the same force-spawn path as the task list's
Run now button, suppressing the racing dequeue. When the spawn can't
proceed (no agent slots, daemon stopped/paused, runner unreachable) the
task stays queued and the response reports the reason instead of
claiming an agent is on it — the tab's toast says "Started…" or names
what it is waiting for.

Also fixes a related silent gap: a follow-up the task store rejected as
a duplicate persisted nothing under the id the service had minted, so
callers reported a task that did not exist. The service now returns the
already-queued record.

Claude-Session: https://claude.ai/code/session_01JErGn4inLCwQiWtXc99m2o
@atomantic
atomantic merged commit d034c13 into main Sep 3, 2026
7 checks passed
@atomantic
atomantic deleted the cos/task-mtlko6vu/agent-d09f43a9 branch September 3, 2026 14:19
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