Skip to content

dev.on_timeout salvage-if-done: a timed-out dev session with a finished, gate-green product is retried and then deferred like an empty one #776

Description

@wsquared

Summary

A dev session that hits session_timeout_min with a finished, gate-green product in the worktree is routed like one that produced nothing: decide_dev (escalation.py) returns RETRY while max_dev_attempts lasts, then defers. The review side distinguishes these cases through review.on_timeout = "salvage-if-done"; the dev side has no equivalent.

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.

One story, two dev attempts, both session-end status timeout after 10800 s.

  • Attempt 1 was killed re-running the deterministic gates after a successful review-fix round. Its worktree held a 486-line diff; the snapshot at refs/attempt-preserve-dirty/<run>-<baseline>-1 built and its changed test files passed.
  • Attempt 2 was killed in the same phase with the deterministic gates green.
  • Journal: dev-decision action: retry, reason: dev session timeout, then action: defer.
  • The kept unit branch merged to main by hand the next morning after every [verify] command passed in the worktree.

Proposal

A [dev] on_timeout policy mirroring the review-side modes:

  • retry (default, current behaviour).
  • salvage-if-done: on timeout / stalled / over_budget, if the spec frontmatter shows the product finalized (done, or in-review reset forward, as review.on_timeout already tests) and the [verify] commands pass against the worktree, proceed to review instead of rolling back; otherwise retry.
  • defer: give up on the first timeout-like verdict.

The post-kill reconcile already rescues a finished session whose artifact is on disk (policy.py comment on dev_stall_nudges); this extends it to a session killed during verification before the artifact was written. With salvage-if-done a timeout costs one verify pass instead of the attempt plus a from-scratch retry (#777). Related: #271 (the review-side salvage this mirrors), #764.

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