fix(cos): start the PR page's Resolve & merge agent immediately - #6068
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 inexecuteand under its daily action budget — so on any other setting the task satpendinguntil it was started by hand from the task page, which is exactly what the button existed to avoid.The click is the approval, so
/resolvenow 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 viasuppressDequeue— the patterncosJobRoutes.jsalready 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.js—spawnReviewLoopFollowUpgainsdispatch: 'queue' | 'immediate'.queue(default) keeps the autonomous lane exactly as it was;immediatesuppresses the dequeue, force-spawns, and reportsdispatch: { started, reason }. Duplicate rejections return the existing task.server/routes/apps/pullRequests.js—/resolvepassesdispatch: 'immediate'and surfacesstarted+queueReasonin 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,
prWatcherescalation) 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 reportsstarted: true; a refused dispatch reportsstarted: 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.biome lintclean.https://claude.ai/code/session_01JErGn4inLCwQiWtXc99m2o