A restart of osfd throws away running steps' work: recovery should continue in place, as resume does #70
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
A restart of osfd throws away the work of every agent step that was running. On 2026-09-26 at 23:11 the deploy of #68 restarted osfd while
openspec.apply[1]ofrun_01M3GB3KN38YT9TZJ7KA7RQ5M0was 15 minutes in. Recovery closed attempt 1 asOrphaned, and attempt 2's entry checkpoint is the same tree as attempt 1's (105ce4f8d9): the worktree was rolled back, and the step started over from nothing.That's the path #60 left alone. #60 made a resume continue in place: keep the worktree, and start a new session seeded with the last handoff plus
git status/git diff. Its design listed "restart recovery and the stall watchdog keep rolling back" as a non-goal. Every deploy that doesn't wait for idle, and every crash, pays for it.Why continuing in place is right here
A restart kills the run's
opencode servetoo (it runs inside the osfd container), so the old session can't be reattached. But the worktree survives the restart intact. That's exactly the state resume continues from.Proposal
Orphanedpath, and the recovery gate's "resume" answer), mark its ready eventcontinue: true, asresume_rundoes._run_attemptthen skips the rollback, and the executor seeds the session with the step's latest recorded handoff and the instruction to readgit statusandgit difffirst. That machinery is all #60's, reused as it is.Done when
Shipped in PR #72 (
850dbab), live on production since 2026-09-27 01:57. Archived asopenspec/changes/archive/2026-09-27-restart-continues-in-place(5cd985a), withrestart-recoveryupdated.What shipped:
resumefor every agent step.resumeandrepromptputcontinue: trueon the ready event. The next attempt keeps the worktree, and its session is seeded with the last handoff and told to readgit status/git difffirst. That's #60's machinery, reused as it was.resume_safeis retired. It no longer decided anything, sinceresumeandrollback_retryboth rolled back. The built-in pipelines and the generated apply chain drop it, and the loader ignores it where an existing.osf/pipeline.yamlstill writes it.tools/test.sh fullwithOSF_URLused to die on macOS bash 3.2 before its browser step. That's fixed.Checked on production: I restarted osfd at 02:38:47 while
openspec.apply[4]ofrun_01M3GB3KN38YT9TZJ7KA7RQ5M0had been editing, in attempt 4 (git diff HEADfingerprint97eb98f, 20 files; entry treedc07cd6).resume, and the ready event carriedcontinue.continued: true, with entry tree4ec9c58, notdc07cd6.97eb98f.An earlier restart at 02:01 took the same path, but that attempt had only been reading, so it couldn't show that no rollback happened.
Found on the way: #73 (the digest showed a dead attempt's tool call as running).