Files
PaperClipAI/server
Devin FoleyandPaperclip 3389bea708 fix(recovery): surface exhausted review-path repair (#15764)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - An issue in review needs a saved path to its next action.
> - A consumed review path starts one automatic repair run.
> - The repair run can finish with only a promise to check later.
> - The old code skips another wake but records no recovery action.
> - This change records a board decision when that repair also leaves no
saved path.
> - The issue lock protects a new monitor, a changed owner, or newer
work from stale finalization.

## Linked Issues or Issue Description

**What happened?**

An agent waiting for an external build said it would check again soon.
Its one-shot monitor had already fired. The automatic review-path repair
also finished without saving another monitor. The task stayed in review
with no future wake or recovery card.

**Expected behavior**

The repair must save a monitor or another review path. If it cannot do
so, Paperclip must show an explicit recovery action and stop automatic
retries.

**Steps to reproduce**

1. Leave an agent-owned issue in review after consuming its last monitor
or interaction.
2. Let the source run finish without saving another review path.
3. Let the single automatic repair run also finish without saving a
path.
4. Before this change, the task stays in review without a scheduled
follow-up. After this change, it is blocked with a board-owned recovery
action and an inline notice that links the repair run.

Related work: Refs #14757 (preserve active review during stale
recovery), Refs #11925 (review-path liveness). This PR handles exhausted
repair wakes; it does not change path aging.

## What Changed

- Return an explicit exhausted result after the single review-path
repair attempt.
- Record the recovery action, blocked state, notice, and activity in one
transaction. Preserve the original assignee. Keep implicit service reads
on the transaction connection.
- Recheck the company, owner, saved review paths, and latest issue run
before escalation. Publish activity after commit.
- Tell the repair agent to save a one-shot monitor and report its check
time when an external check remains pending.
- Retry missed escalation from the saved terminal repair run during the
stranded-issue sweep. Cover restart recovery and rollback with a
one-connection pool.
- Preserve valid due and claimed monitors for dispatch while the owner
permits on-demand wakes. Surface overdue monitors after those wakes are
disabled. Keep the future-only liveness classifier unchanged.
- Cover monitor repair, stale finalization, company boundaries,
duplicate finalization, and failed repair. Document the behavior.

## Verification

- `pnpm exec vitest run
server/src/services/recovery/review-path-recovery.test.ts
server/src/__tests__/heartbeat-issue-liveness-escalation.test.ts
server/src/__tests__/issue-liveness.test.ts` — 62 tests passed,
including PostgreSQL integration tests.
- `pnpm --filter @paperclipai/server exec tsc --noEmit` — passed.
- `pnpm -r typecheck` and `pnpm build` — passed.
- `pnpm test:run` — 18,144 passed, with three unrelated local fixture
failures. Two Git fixtures pass when run with their expected initial
branch (`master`); this machine defaults to `main`. The native same-task
replacement fixture also fails on an unchanged checkout of master. No
unrelated production behavior was changed to accommodate those fixtures.
- Apex review — 5/5 on commit `3aca7059848`, with no unresolved review
comments.
- Latest-head CI — all required checks passed, including test shards,
typecheck, build, browser checks, and canary dry run. No merge
conflicts.
- Repeat the steps above. Confirm that the issue has one recovery
notice, one board-owned action, and no second automatic repair wake.
Save a monitor during repair and confirm that the issue stays in review.

## Risks

- A review repair that exhausts its one attempt now moves the task to
blocked and asks the board to act. This is an intentional behavior
change.
- The check uses the current review-path classifier. A path that the
classifier treats as healthy still suppresses escalation.
- No schema, API, or UI contract changes are required. Existing recovery
controls render the action and notice.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The
runtime does not expose a more specific model ID or context window.

## 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 (62 tests for this change;
full-suite fixture limitations are listed above)
- [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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-09 18:56:20 -07:00
..