Skip to content

Retry after rollback-auto never names the attempt-preserve-dirty snapshot, so attempt 2 rebuilds attempt 1 from scratch #777

Description

@wsquared

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Robustness, enhancement, tests, or docs worth schedulingarea:engineOrchestrator engine and run lifecycleenhancementNew feature or requestneeds-designAwaiting a maintainer design decision before code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions