worktree-retention-don

Worktree retention: don't auto-reap until eval-passed AND merged; retry-in-place by default

Metadata

Statusdone
Assignedagent-579
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-27T12:30:48.613879112+00:00
Started2026-04-27T12:31:26.964934643+00:00
Completed2026-04-27T12:59:14.541600874+00:00
Tagseval-scheduled
Eval score0.83
└ blocking impact0.90
└ completeness0.85
└ constraint fidelity0.85
└ coordination overhead0.85
└ correctness0.90
└ downstream usability0.80
└ efficiency0.85
└ intent fidelity0.95
└ style adherence0.90

Description

Description

User insight: today's worktree-sweep behavior is too aggressive — it reaps worktrees on agent exit (any reason: success, failure, crash, rate-limit, signal). This destroys recoverable WIP work and prevents trivial resume.

User quote: 'we shouldn't auto reap unless eval says work done and merged basically. it should be basic to restart/retry the agent in the same worktree!!!!'

Today's behavior (problematic)

  • Agent exits (any reason) → worktree marker set → worktree-sweep removes the dir at next dispatcher tick
  • Branch survives in git, but the WORKING directory + uncommitted changes are gone
  • Retry → fresh worktree on fresh branch off main → loses all WIP context
  • Especially painful when the agent hit a transient failure (rate limit, network glitch, OOM) and just needs to resume the same work

Required behavior

  1. Retention policy: keep worktree until BOTH (a) the task's evaluation passed AND (b) the branch has been merged to main.

    • Eval pass alone isn't enough — work hasn't reached main, agent might need to address merge conflicts
    • Merge alone isn't enough — eval might still be failing
    • Both → safe to reap; the work is permanently in main
  2. Retry-in-place is the default. When wg retry <task> runs:

    • If the task's prior worktree dir still exists AND its branch still exists → reuse them. Spawn a NEW agent process (fresh memory) but the worktree state is preserved (uncommitted changes, branch state, prior context).
    • The new agent reads the prior commits + uncommitted changes, sees what was done, picks up from there.
    • Only allocate a fresh worktree if the prior was reaped (per the new retention policy, only happens after eval+merge).
  3. wg retry --fresh opt-out. If user explicitly wants to start over (work was on the wrong path), wg retry --fresh <task> discards the prior worktree and spawns clean.

  4. Agent prompt awareness. The agent prompt template should explicitly mention 'this worktree may have prior WIP from a previous attempt; check git status, git log, and any uncommitted changes before starting fresh.'

  5. Worktree state inspection. wg show <task> should display worktree status if the task is being retried: branch name, commits ahead of main, uncommitted file count, last-modified timestamp. So the user can see what's there before deciding fresh vs continue.

Example: what should have happened with agent-105 (wg-chat-as)

  • agent-105 hit 5h rate limit at 21:09 UTC
  • Worktree had 998 lines of uncommitted WIP (now committed)
  • Should have been: rate limit reset → wg retry wg-chat-as → SAME worktree, NEW agent process picks up where 105 left off
  • Instead: would spawn fresh worktree off main → 15 hours of work effectively lost (unless human intervenes to merge or hand-pass branch context)

Files likely to touch

  • src/commands/service/worktree.rs — sweep logic; add eval-passed AND merged gates
  • src/commands/service/coordinator.rs — spawn path; check for prior worktree before allocating new
  • src/commands/spawn.rs — spawn-in-existing-worktree path
  • src/commands/retry.rs — wire --fresh flag, default behavior
  • src/commands/show.rs — worktree-state display
  • Agent prompt template (in src/agency/prompt.rs or src/service/executor.rs) — add WIP-awareness preamble

Out of scope

  • Garbage collection policy for VERY old branches (separate concern)
  • Multi-agent collaboration on the same worktree (not supported, not in this task)

Validation

  • Failing tests first:
    • test_worktree_not_reaped_on_agent_failure — agent fails, worktree dir survives, sweep skips it
    • test_worktree_reaped_only_after_eval_pass_and_merge — both conditions required
    • test_retry_reuses_existing_worktree_by_default — wg retry X after agent failure reuses the dir + branch; agent sees prior commits
    • test_retry_fresh_flag_allocates_new_worktree
    • test_show_displays_worktree_state_for_retried_tasks
  • Implementation makes tests pass
  • cargo build + cargo test pass with no regressions
  • Manual smoke (HARD GATE):
    1. Create a task, dispatch
    2. Kill the agent mid-run (simulating rate limit / crash)
    3. wg retry <task> — observe new agent spawned in SAME worktree dir (same path), reads prior commits, continues
    4. Repeat without intervention until task completes + eval passes + branch merges
    5. Worktree dir gets reaped only after the merge
    6. Compare: wg retry --fresh <task> discards and starts new worktree

Depends on

Required by

Log