fix(recovery): treat routine duplicate-suppression as terminal-benign, not a strand (BLO-19954) - #1035
Conversation
|
Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
…, not a strand (BLO-19954) A run cancelled with errorCode `routine_execution_duplicate_suppressed` (the single-owner dispatch lock refusing a non-owner run under `concurrencyPolicy=always_enqueue`) is intentional control flow, not a failure — the run's own cancellation message says the lock owner will continue the work. `escalateStrandedAssignedIssue` previously fell through to the generic `stranded_assigned_issue` cause for this code, flipping the issue to `blocked`, creating a recovery action, and waking an owner every time the routine fired — manufacturing hourly recovery wakes for a routine that was never broken. Short-circuit this cause at the top of `escalateStrandedAssignedIssue`: cancel the routine-execution issue directly (it performed no scan and never will) instead of escalating it, with no recovery action and no wake. Genuine strands (adapter failures, workspace faults, provider quota) are unaffected — they don't carry this error code. CI: pnpm test:run -- server/src/__tests__/issue-recovery-actions.test.ts adds a paired test asserting zero recovery actions + `cancelled` status for this cause, alongside the existing `adapter_failed` test that still asserts one recovery action + `blocked`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
173aa4f to
711c69c
Compare
|
Hey @allyblockcast[bot]! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
Ally — Consolidated PR ReviewLenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex. Important Issues (2)
Strengths
Recommended Action
Because this PR is authored by |
kkroo
left a comment
There was a problem hiding this comment.
Approved: duplicate-suppressed routine runs are explicitly terminal-benign, with regression coverage for no recovery action or owner wake.
Thinking Path
Linked Issues or Issue Description
Fixes: Paperclip issue BLO-19954 — "Routine duplicate-suppression is misclassified as a strand, manufacturing hourly CEO recovery wakes" (filed by the CEO; tracked in Paperclip, not GitHub Issues, since this repo's issue tracking for this org lives in Paperclip).
What Changed
isRoutineExecutionDuplicateSuppressedRunandcancelDuplicateSuppressedRoutineExecutionIssueinserver/src/services/recovery/service.ts.escalateStrandedAssignedIssuenow short-circuits at the top: when the latest run iscancelledwitherrorCode: routine_execution_duplicate_suppressed, it cancels the routine-execution issue directly (advisory-lock transaction, fresh re-read, explanatory system comment) instead of escalating toblockedwith a recovery action +wake_owner.adapter_failed,process_lost, workspace faults, provider quota, etc.) are untouched — they don't carry this error code, so genuine strands still escalate exactly as before.server/src/__tests__/issue-recovery-actions.test.tsasserting this cause yields zero recovery actions +status: cancelled+ no wake, placed directly next to (and paired with) the existingadapter_failedtest that still asserts one recovery action +blocked.Verification
npx vitest run server/src/__tests__/issue-recovery-actions.test.ts— 60/60 passed (includes the new paired test).npx vitest run server/src/__tests__/heartbeat-process-recovery.test.ts -t "cancels a queued stale routine duplicate"— unaffected, still passes (this exercises the run-cancellation gate itself, upstream of this fix).tsc --noEmit(server package) — clean.paperclipListIssues(originId=4756349d-b78d-4e66-9006-68826a30f885): all 61 routine-execution issues for this routine are currently terminal (31done, 30cancelled, zeroblocked/todo/in_progress) — confirms the backlog named in the filing (BLO-18745, BLO-18750) was already cleared and this PR is the prospective code fix.doneexecutions should keep accruing at the routine's fire rate with zero newblockedissues carrying an activestranded_assigned_issuerecovery action for this routine.Risks
routine_execution_duplicate_suppressed, which is set in exactly one place (cancelClaimedRunForRoutineExecutionDuplicateinheartbeat.ts) and only forroutine_execution-origin issues under a dispatch-lock conflict.blocked(visible on an owner's board, requiring manual dismissal) now auto-cancels with an explanatory comment instead. This is the intended fix — theblockedstate was never actionable (there is nothing to repair; the lock owner already has the work) — but it does mean these issues disappear from active queues faster than before.heartbeat.ts), only to how the recovery sweep classifies its aftermath.Model Used
Claude Sonnet 5 (
claude-sonnet-5[1m], 1M context), running as the Paperclip PlatformSREEngineer agent via Claude Code / the Claude Agent SDK. No extended-thinking mode; standard tool use (Read/Edit/Bash/vitest/tsc) to investigate, implement, and verify.Checklist
Fixes:/Closes #/Refs #OR (b) described the issue in-PR following the relevant issue template🤖 Generated with Claude Code