mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-13 07:12:00 +01:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - A lead agent creates tasks and assigns them to other agents > - A task created without an assignee goes to its creator, with a queued run that has not started yet > - When the lead then reassigns the task, the route stopped only a running run. The queued run kept the task's execution lock > - The new assignee's wake waited behind that lock, so nothing ran until the queue reached and withheld the old run > - This pull request releases the outgoing assignee's never-started run on reassignment and wakes the new assignee at once > - The benefit is that reassignment starts the new owner's work immediately, without a stale lock or a duplicate task ## Linked Issues or Issue Description **What happened?** In the paid chat eval `tasks.attachment-brief`, the CEO created a task with no assignee, so it went to the CEO with a queued run. The CEO then reassigned it to Morgan. The CEO's queued run kept the execution lock. Morgan's assignment wake was deferred behind it. After 86 seconds the queue cancelled the stale run as `issue_assignee_changed`. Before that, the CEO got a 403 when it tried to cancel the run, and it created a second copy of the task. **Steps to reproduce** 1. Assign a task to an agent that is busy, so the task's assignment run stays queued. 2. Reassign the task to another agent. 3. The queued run keeps the execution lock, and the new assignee's wake is deferred. **Expected behavior** Reassignment cancels the outgoing assignee's never-started run for that task and wakes the new assignee at once. ## What Changed - `server/src/routes/issues.ts`: on reassignment, when no running run holds the task, also stop the outgoing assignee's queued run that holds the task's execution lock. The stop uses the existing `issue_reassigned` code and the existing stop settlement. - Reassignment stops pass `suppressImmediateRecovery: true`. Without it, releasing the lock queued an `issue_assignment_recovery` run for the outgoing assignee, which took the lock back before the reassignment was saved. The new assignee's wake is the successor. - `server/src/__tests__/issue-reassignment-queued-run.test.ts`: a database-backed route test. It is red on master (the queued run stays queued and holds the lock, and the new assignee's wake is `deferred_issue_execution`). It is green here (the run is cancelled as `issue_reassigned`, and the new assignee has an admitted run for the task). A control case shows that a queued lock holder that is not the outgoing assignee's run is not touched. ## Verification - `cd server && npx vitest run src/__tests__/issue-reassignment-queued-run.test.ts` (2 passed; red on master) - `cd server && npx vitest run src/__tests__/issue-agent-mutation-ownership-routes.test.ts src/__tests__/issue-queued-comments-routes.test.ts src/__tests__/human-directed-work.test.ts` (378 passed) - `cd server && npx tsc --noEmit` passes. - Paid E2E run on a combined branch: https://github.com/paperclipai/paperclip/actions/runs/43161593494 (results in a comment below). ## Risks - Behavior change: a reassignment now cancels the outgoing assignee's queued run that holds the task. Before, that run was cancelled later at claim time with `issue_assignee_changed`. The eval and the run log already recognize both codes. - Reassignment stops no longer queue an immediate recovery run for the outgoing assignee. If the reassignment write then fails, the periodic recovery sweep still recovers the task. - No schema or saved-state change. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, with tool use and code execution in Claude Code. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>