Skip to content

feat(sessions): nudge alive tasks whose transcript ended mid-turn - #23

Open
Antisophy wants to merge 2 commits into
CyberShadow:masterfrom
Antisophy:feat/midturn-restart-nudge
Open

feat(sessions): nudge alive tasks whose transcript ended mid-turn#23
Antisophy wants to merge 2 commits into
CyberShadow:masterfrom
Antisophy:feat/midturn-restart-nudge

Conversation

@Antisophy

@Antisophy Antisophy commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

A restart or crash that lands mid-turn is only recovered when the task was recorded "active": that resume path relaunches the process and sends the restart nudge telling the agent to retry its interrupted tool call. A turn started by the agent itself (a background-task notification inside the CLI) never passes through a send that marks the task active, so the shutdown snapshot says "alive", the resume relaunches silently, and the agent sits idle on its interrupted work until a human notices.

Witness the turn lifecycle directly instead of trusting the status: a turn-scoped event (item/, turn/) marks the task's transcript mid-turn until a turn/result or process exit closes it, while session bootstrap and other non-turn events leave the witness unchanged, so a restart's own resume traffic cannot re-open an idle task. The flag is persisted on change, so a kill at any moment leaves the truth on disk. The alive resume branch sends the restart nudge when the witness says mid-turn and stays silent otherwise, so idle tasks cost nothing extra.

The second commit extends the restart nudge itself: it now also tells the resumed agent to check on background work (shells, subagents, watchers) that did not survive the restart, since an agent whose pending work was a background job rather than an in-flight tool call would otherwise conclude nothing was pending and end its turn.

A restart or crash that lands mid-turn is only recovered when the task
was recorded "active": that resume path relaunches the process and
sends the restart nudge telling the agent to retry its interrupted
tool call. A turn started by the agent itself (a background-task
notification inside the CLI) never passes through a send that marks
the task active, so the shutdown snapshot says "alive", the resume
relaunches silently, and the agent sits idle on its interrupted work
until a human notices.

Witness the turn lifecycle directly instead of trusting the status: a
turn-scoped event (item/*, turn/*) marks the task's transcript mid-turn
until a turn/result or process exit closes it, while session bootstrap
and other non-turn events leave the witness unchanged, so a restart's
own resume traffic cannot re-open an idle task. The flag is persisted
on change, so a kill at any moment leaves the truth on disk. The alive
resume branch sends the restart nudge when the witness says mid-turn
and stays silent otherwise, so idle tasks cost nothing extra.
The restart nudge covered an interrupted tool call but said nothing
about background work, and an agent whose pending work was a background
shell or watcher rather than an in-flight tool call would conclude
nothing was pending and end its turn; the background jobs died with the
restart and their completion notifications never fire, so the task
orphans. Name that case explicitly: check what was running, relaunch
what is still needed, and do not end the turn without doing so.

@CyberShadow CyberShadow left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A turn started by the agent itself (a background-task notification inside the CLI) never passes through a send that marks the task active

I think this is the real bug here. We should already be switching the task state on a self-resume; it's possible that the behavior is an artifact of us not using a consolidated path that affects nudging properly.

Comment on lines +137 to +142
// Migration 23: whether the transcript ends inside an open turn.
// Maintained on every translated event (set on turn activity,
// cleared on turn/result and process/exit), so a restart or crash
// landing mid-turn is visible at resume time regardless of what
// the status field recorded; such tasks get the restart nudge.
"ALTER TABLE tasks ADD COLUMN turn_open INTEGER NOT NULL DEFAULT 0;",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really hope we don't actually need a migration here! Our existing data model should suffice to capture this corner case.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants