Skip to content

feat(daemon): cross-process task lease recovery (roadmap-v0.6 F.1) — completes Phase F#87

Merged
RNT56 merged 3 commits into
mainfrom
claude/v06-f1-recovery
Jun 29, 2026
Merged

feat(daemon): cross-process task lease recovery (roadmap-v0.6 F.1) — completes Phase F#87
RNT56 merged 3 commits into
mainfrom
claude/v06-f1-recovery

Conversation

@RNT56

@RNT56 RNT56 commented Jun 29, 2026

Copy link
Copy Markdown
Owner

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 — an mpsc pair can't survive a restart).
  • adopt_from_snapshot(snap, worktree_present, now) → Result<TaskId, AdoptError> — re-leases under this instance's LeaseOwner, marks Pending (a fresh worker resumes from the log), carries usage so budgets re-charge not reset.

CI core vs live seam

  • CI core (4 tests): snapshot/adopt round-trip (stable id, fresh lease, Pending, no id collision); absent worktree → WorktreeGone; over-budget carried usage → adopted terminal Done(BudgetExhausted); duplicate id → Duplicate.
  • Live seam (#[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 Pending and still completes only on a VerifiedPatch (invariant 13). Budgets re-charge from carried usage (invariant 11); the lease/heartbeat model is restated under the new owner (invariant 12). Small additive PartialEq/Eq derive on AgentBudget.

Tests run

cargo xtask verifygreen (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

RNT56 and others added 3 commits June 29, 2026 11:24
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>
@RNT56 RNT56 merged commit c1b2d0a into main Jun 29, 2026
1 of 3 checks passed
@RNT56 RNT56 deleted the claude/v06-f1-recovery branch June 29, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant