7945c70396
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Issues are the unit of agent work, and a "done" issue should stay done unless something explicit reopens it > - The implicit-reopen path (human comment on a terminal issue) already keeps agents from reopening their own issues via `shouldImplicitlyMoveCommentedIssueToTodo`, but the explicit `reopen: true` path was not similarly guarded > - That gap lets the assignee agent reopen its own `done`/`cancelled` issue just by posting a log-style comment with `reopen: true` — the same "log lines are not reopen signals" semantics that the implicit path already encodes > - This pull request adds a focused `isAssigneeSelfCommentOnTerminalIssue` guard applied at both `PATCH /issues/:id` and `POST /issues/:id/comments`, forcing `effectiveMoveToTodoRequested = false` when the actor is an agent commenting on its own terminal issue without `resume: true` > - The benefit is a single, narrow invariant: only an explicit `resume: true` (or a different-agent / human commenter) reopens a terminal issue — assignee self-comments stay communicative ## Linked Issues or Issue Description Refs #3980 Refs #3935 Refs #6601 ## What Changed - Adds `isAssigneeSelfCommentOnTerminalIssue` helper in `server/src/routes/issues.ts` next to the existing `shouldImplicitlyMoveCommentedIssueToTodo` - Applies the guard at both comment entry paths (`PATCH /issues/:id` with a `comment` body and `POST /issues/:id/comments`) so `effectiveMoveToTodoRequested` is forced to `false` when actor is an agent and matches the **current** assignee of a `done`/`cancelled` issue — even if `reopen: true` was sent explicitly - PATCH path compares against `existing.assigneeAgentId` (not `requestedAssigneeAgentId`), so a different agent that PATCHes a terminal issue with `{ comment, reopen: true, assigneeAgentId: <self> }` still reopens as today - The `resume: true` explicit-resume path is preserved verbatim — the guard short-circuits on `resumeRequested` - Existing external-caller paths (different agent / human user commenting on terminal) are unchanged and still reopen - New unit tests in `server/src/__tests__/issue-comment-reopen-routes.test.ts`: - `does not reopen via POST comment+reopen when the assignee agent is the actor on a done issue` - `does not reopen via POST comment+reopen when the assignee agent is the actor on a cancelled issue` - `does not reopen via PATCH comment+reopen when the assignee agent is the actor on a done issue` - `still reopens a done issue via PATCH when a different agent reassigns to self with reopen=true` ## Verification - [x] `vitest run src/__tests__/issue-comment-reopen-routes.test.ts` — 65/65 pass locally (4 new + 61 existing) - [x] `tsc --noEmit` — no new errors in changed files - [x] Manual trace: explicit-resume path (`resume: true`) still reopens because the guard short-circuits on `resumeRequested` ## Risks Low. The guard is a single short-circuit before the existing reopen decision and only fires when actor is an agent commenting on its own `done`/`cancelled` issue without `resume: true`. The `resume: true` path is unchanged, and the PATCH comparison uses the current assignee so cross-agent takeover with `reopen: true` continues to reopen. ## Model Used - Provider: Anthropic - Model: Claude Opus 4.7 (`claude-opus-4-7`) - Mode: extended thinking + tool use (Claude Code agent harness) ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots (N/A — server-only) - [x] I have updated relevant documentation to reflect my changes (no docs touch the reopen guard) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --- ## Cross-references and status (maintainer) Rebased on current `master`. The implicit-reopen case is already handled upstream by the user-actor branch of `shouldImplicitlyMoveCommentedIssueToTodo`; this PR adds the matching guard for the explicit `reopen: true` path. The PATCH-path guard compares against `existing.assigneeAgentId` so cross-agent reassignment + reopen still reopens. Refs #3980 Refs #3935 Refs #6601 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>