feat(loop): crash recovery on boot — resume features stranded mid-drive#9
Merged
Conversation
A drive doesn't survive a server restart, so every in_progress feature the previous run was building was stranded forever (the puller only claims `ready`). The loop now runs a one-time recovery before the puller spins (at the top of _run): for each in_progress feature, if its PR actually got opened (a crash between open_pr and open_review) adopt it → in_review; otherwise reset it to ready for a clean rebuild (a stale worktree is cleaned when the puller re-claims). in_review features are left alone — they have a PR and the webhook/merge-poll resolves them. Recovery is best-effort per feature (one failure doesn't strand the rest or stop the loop). worktree.pr_url_for_branch() is the probe (the open PR for feat/<id>, or ""). This completes the P0 resilience batch (failure classification #7, stuck-coder watchdog #8, crash recovery here): the loop now survives restarts, hung coders, and transient failures unattended. Tests: +3 (98 total) — pr_url_for_branch found/absent; _recover adopts-PR-else-requeue and is resilient to a per-feature error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
👀 Quinn is reviewing — verdict (PASS / WARN / FAIL) + findings to follow. |
There was a problem hiding this comment.
QA Audit — PR #9 | feat(loop): crash recovery on boot — resume features stranded mid-drive
VERDICT: WARN (non-blocking — CI still running; re-review pending terminal green)
CI Status
- test: ⏳ in_progress
Diff Review
_recover()inloop.py: correctly scoped — per-feature try/except so one failure never strands others, plus an outer catch in_run()so recovery can never stop the loop from starting. Only touchesin_progressfeatures;in_reviewleft alone.pr_url_for_branch()inworktree.py: follows the same_gh/rc == 0pattern as the adjacentpr_is_merged(). Clean, consistent.
Observations
- LOW: clawpatch structural review unavailable — repo not in project registry. Diff is small enough (~80 LOC) that manual review is sufficient.
- Tests (+3, 98 total) cover found/absent PR, adopt-vs-reset, and per-feature error resilience. All green locally per PR description; awaiting CI confirmation.
— Quinn, QA Engineer
|
Submitted COMMENT review on |
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.
What
The final P0 resilience port. A drive doesn't survive a server restart, so every
in_progressfeature the previous run was building was stranded forever (the puller only claimsready). This was the single biggest autonomy gap.The loop now runs a one-time
_recover()before the puller spins (top of_run): for eachin_progressfeature —open_prandopen_review) → adopt it →in_review;readyfor a clean rebuild (a stale worktree is cleaned when the puller re-claims).in_reviewfeatures are left alone — they have a PR and the webhook/merge-poll resolves them. Recovery is best-effort per feature — one failure doesn't strand the rest or stop the loop from starting.worktree.pr_url_for_branch()is the probe (the open PR forfeat/<id>, or"").This completes the P0 resilience batch
awaitin a drive is bounded)Together: the loop now survives restarts, hung coders, and transient failures unattended — the difference between "drives features" and "drives a board for days without a babysitter."
Tests
+3 (98 total), all green:
pr_url_for_branchfound/absent;_recoveradopts-PR-else-requeue, and stays resilient to a per-feature error.ruffclean.🤖 Generated with Claude Code