feat(daemon): cross-process task lease recovery (roadmap-v0.6 F.1) — completes Phase F#87
Merged
Conversation
Adds TaskRegistry::snapshot_all + adopt_from_snapshot (TaskSnapshot / AdoptError) — the recovery half of invariant 12. A restarting daemon re-adopts its running tasks with stable ids, re-leasing under the new LeaseOwner and marking each Pending so a fresh worker resumes from the log (an mpsc channel can't survive a restart). Carried usage is preserved so budgets re-charge, not reset (invariant 11); an already-over-budget task is adopted terminal (Done(BudgetExhausted)); an absent worktree -> WorktreeGone; a duplicate id -> Duplicate. A re-adopted task still completes only on a VerifiedPatch (invariant 13 — adoption restores supervision, never completion). Pure state-machine steps; the dump/load + SIGTERM + restart cycle are the #[ignore]d daemon_recover_xproc_live_smoke (TODO(daemon-recover-xproc-live)), in runbook F.6. Also derives PartialEq/Eq on AgentBudget. Completes Phase F. 4 new tests; daemon-only; zero nano impact. `cargo xtask verify` green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…end) Turns F.1's recovery from snapshot/adopt-in-memory into real persistence: - encode_snapshots/decode_snapshots: a dependency-free, versioned, bounded CCTS frame (magic + version + count + per-snapshot id/chat/phase(tagged)/ lease/budget/usage/worktree-path), panic-free + fail-closed (bad magic -> BadFormat, bad version -> BadVersion, truncated/over-cap -> BadContents). - TaskRegistry::dump_snapshots(path) + load_snapshots(path): actual file I/O (std::fs only), for the SIGTERM-dump / startup-reload cycle. Now the only #[ignore]d inch is the SIGTERM hook + a real OS process restart (daemon_recover_xproc_live_smoke). 3 new tests: encode/decode round-trip (incl. worktree path + BudgetExhausted axis), bad-magic/version rejection, and a dump->load->re-adopt simulated restart. Daemon-only; zero nano impact. `cargo xtask verify` green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Summary
Roadmap-v0.6 F.1 — survive a daemon restart and re-adopt running tasks, closing the recovery half of invariant 12. Completes Phase F (daemon hardening).
TaskRegistry::snapshot_all(now) → Vec<TaskSnapshot>— pure; snapshots non-terminal tasks (the live channel is not captured — anmpscpair can't survive a restart).adopt_from_snapshot(snap, worktree_present, now) → Result<TaskId, AdoptError>— re-leases under this instance'sLeaseOwner, marksPending(a fresh worker resumes from the log), carriesusageso budgets re-charge not reset.CI core vs live seam
WorktreeGone; over-budget carried usage → adopted terminalDone(BudgetExhausted); duplicate id →Duplicate.#[ignore],TODO(daemon-recover-xproc-live)): the real dump/load file I/O + SIGTERM hook + a kill-and-restart cycle —daemon_recover_xproc_live_smoke, runbook §F.6.Trust boundary
Recovery restores supervision, never completion: a re-adopted task is
Pendingand still completes only on aVerifiedPatch(invariant 13). Budgets re-charge from carried usage (invariant 11); the lease/heartbeat model is restated under the new owner (invariant 12). Small additivePartialEq/Eqderive onAgentBudget.Tests run
cargo xtask verify— green (runbook-check: 29 ignored seams + 20 tags). Nano unchanged at 53.5% (daemon-only).With this + F.2 (#85) + F.3 (#86), Phase F is fully delivered.
🤖 Generated with Claude Code