Summary
After a failed dev attempt under worktree isolation, rollback-auto resets the worktree to baseline and attempt-worktree-preserved snapshots the discarded tree to refs/attempt-preserve-dirty/<slug>-<baseline>-<attempt>. The retry launches with a prompt identical to attempt 1 and no reference to that snapshot, so attempt 2 rebuilds everything.
Observed (0.11.1)
Setup: an unattended nightly sweep run with [limits] session_timeout_min = 180, max_dev_attempts = 2 and [scm] isolation = "worktree"; the dev adapter is Claude Code.
dev-decision attempt 1 action: retry reason: dev session timeout
rollback-auto baseline <baseline> note: reverting tracked changes + run-created untracked files
attempt-worktree-preserved ref: refs/attempt-preserve-dirty/<run>-<baseline>-1
session-start <story>-dev-2 prompt: <byte-identical to dev-1's prompt>
tasks/<story>-dev-1/prompt.txt and tasks/<story>-dev-2/prompt.txt are byte-identical (330 bytes). Attempt 1's snapshot held a complete 486-line implementation whose changed test files passed. Attempt 2 spent 20 minutes re-authoring the spec and 52 minutes re-implementing, reached the same verification phase, and timed out there too. Both attempts consumed about 114M raw tokens (from the session transcripts) for a product attempt 1 had already produced.
Proposal
When a retry follows a preserved attempt, name the snapshot in the retry prompt, for example:
A previous attempt of this story was rolled back after <reason>; its worktree is preserved at <ref> (git diff <baseline> <ref> shows what it had). Judge that work against the spec before writing anything new: reuse what passes, discard what does not, and say in your report which you did.
Optionally a [scm] retry_from_preserve = true that checks the snapshot out onto the fresh worktree, leaving the prompt unchanged.
The snapshot already exists, is journalled and is pruned by preserve_keep; only the hand-off to the next attempt is missing. Related: #701 (reverts with no preserve artifact), and #776 (dev.on_timeout = salvage-if-done), which would make the retry unnecessary in the timeout case.
Summary
After a failed dev attempt under worktree isolation,
rollback-autoresets the worktree to baseline andattempt-worktree-preservedsnapshots the discarded tree torefs/attempt-preserve-dirty/<slug>-<baseline>-<attempt>. The retry launches with a prompt identical to attempt 1 and no reference to that snapshot, so attempt 2 rebuilds everything.Observed (0.11.1)
Setup: an unattended nightly sweep run with
[limits] session_timeout_min = 180,max_dev_attempts = 2and[scm] isolation = "worktree"; the dev adapter is Claude Code.tasks/<story>-dev-1/prompt.txtandtasks/<story>-dev-2/prompt.txtare byte-identical (330 bytes). Attempt 1's snapshot held a complete 486-line implementation whose changed test files passed. Attempt 2 spent 20 minutes re-authoring the spec and 52 minutes re-implementing, reached the same verification phase, and timed out there too. Both attempts consumed about 114M raw tokens (from the session transcripts) for a product attempt 1 had already produced.Proposal
When a retry follows a preserved attempt, name the snapshot in the retry prompt, for example:
Optionally a
[scm] retry_from_preserve = truethat checks the snapshot out onto the fresh worktree, leaving the prompt unchanged.The snapshot already exists, is journalled and is pruned by
preserve_keep; only the hand-off to the next attempt is missing. Related: #701 (reverts with no preserve artifact), and #776 (dev.on_timeout = salvage-if-done), which would make the retry unnecessary in the timeout case.