fix(daemon): defer artifact cleanup until active downloads close

Merged
TH
2d ago
+1046-76

Summary

Keep directory archives and sources owned until downloads settle, with abortable pipelines, bounded lifetimes, teardown, immediate ID retirement, and JSON open errors. Cancel shared archive preparation only after every active download is cancelled.

FU-ART; seven files; artifact-download scope. Prior blocker: #4060 (not reproduced).

Validation

  • Base: a0e7c7dc239922bf93adaceff20a2f7e78579146; prior reviewed head: 3a4f1582ae989b722b3c428c90fa2a232b1a6ab1; tested head: e4ad2f37e3381dc09ad1b382e1ffe17e3599d5f1.
  • Red first: cancelling archive-builder A caused waiting B to fail with A’s RESOURCE_EXPIRED error; the same test now verifies B’s complete archive payload. All-waiter cancellation still aborts preparation and removes files; real HTTP client-abort coverage also passes.
  • Truncation and deadline-first tests preserve source data, prove registration expiry remains armed, and verify bounded source/archive cleanup; neither additional permanent-leak claim reproduced.
  • Explicit wire/HTTP/owner selection: 330 passed. pnpm format: passed.
  • Foreground pnpm check:affected --run --head e4ad2f37e3381dc09ad1b382e1ffe17e3599d5f1: passed; receipt run-SWZ47c, exactCommit=true, checkoutChanged=false; 16,988 unit passed, 304 related passed; all runnable stages passed.
  • Released-wire compatibility passed; protocol 2 unchanged.
  • Live private-state daemon: two identical 16,782,807-byte curl archives, each containing the full 16 MiB payload; preparation and streaming aborts at 0/167,936 bytes; source/inventory cleaned, daemon stopped.
  • Mutable-source growth remains deferred. New-head CI/native lanes pending; cold self-review only this round.