fix(miner): guard runAttempt's worktree cleanup and hosted claim release in the finally block (#9677) - #9912
Conversation
|
Tip ✅ LoopOver review result - approve/merge recommendedReview updated: 2026-07-29 22:08:09 UTC
Review summary Nits — 5 non-blocking
Decision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
…ase in the finally block (JSONbored#9677) runAttempt's `finally` performs the whole teardown in order: cleanup worktree -> release local claim -> release hosted claim -> release allocator slot -> discard DB fork -> close every store. Only the DB-fork discard was defensive. The two riskiest steps -- `cleanupAttemptWorktree` (a `git worktree remove` subprocess) and the hosted `submitSoftClaim(... "released")` (a network POST) -- sat before the claim release, the allocator release, and every close(), unguarded. If either rejected, the `finally` threw: the soft-claim stayed `active` (wrongly telling a sibling miner the issue is in flight, for the ledger's full 14-day expiry window), the worktree pool slot stayed leased, and every open SQLite handle was left unclosed. Wrap each of the two calls in its own try/catch that reports via captureMinerError with a distinct kind (attempt_worktree_cleanup_failed, attempt_hosted_claim_release_failed) and the repoFullName/attemptId context -- exactly mirroring the DB-fork discard block below them. Neither catch changes the return value or swallows silently; the claim release, allocator release, and close()s are now reachable on every path. Two named regression tests: a rejecting cleanupAttemptWorktree still runs the claim release + allocator release/close and returns the same exit code as a clean cleanup; a rejecting hosted release still runs the allocator release and closes every store. Both fail against the unguarded code; the success arms are already covered by the existing end-to-end tests. Closes JSONbored#9677 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9912 +/- ##
===========================================
- Coverage 91.86% 79.62% -12.24%
===========================================
Files 921 282 -639
Lines 113221 58872 -54349
Branches 27287 6930 -20357
===========================================
- Hits 104005 46876 -57129
- Misses 7929 11706 +3777
+ Partials 1287 290 -997
Flags with carried forward coverage won't be shown. Click here to find out more.
|
What
runAttempt'sfinallyperforms the whole teardown in order: cleanup worktree → release local claim → release hosted claim → release allocator slot → discard DB fork → close every store. Only the DB-fork discard was defensive. The two riskiest steps —cleanupAttemptWorktree(agit worktree removesubprocess) and the hostedsubmitSoftClaim(... "released")(a network POST) — sat before the claim release, the allocator release, and everyclose(), unguarded. If either rejected, thefinallythrew and the rest never ran: the soft-claim stayedactive(wrongly telling a sibling miner the issue is in flight, for the ledger's full 14-day expiry window), the worktree pool slot stayed leased, and every open SQLite handle was left unclosed.How
Wrap each of the two calls in its own
try/catchthat reports viacaptureMinerErrorwith a distinctkind(attempt_worktree_cleanup_failed,attempt_hosted_claim_release_failed) and therepoFullName/attemptIdcontext — exactly mirroring the DB-fork discard block below them (attempt-cli.ts:1120-1126). Neither catch changes the return value or swallows silently; the claim release, allocator release, andclose()s are now reachable on every path through thefinally. The SIGINT/SIGTERM handlers and the ordering are unchanged.Tests
Two named regression tests in
test/unit/miner-attempt-cli.test.ts:cleanupAttemptWorktreestill runs the local claim release, the allocator release +close(), and returns the same exit code as a clean cleanup (pinned by a control run)."released"POST rejects; the initial"active"claim succeeds) still runs the allocator release and closes every store.Both fail against the unguarded code; the two success arms are already covered by the existing end-to-end submitted-path and discovery-plane release tests.
Closes #9677