Skip to content

A session that ends its turn waiting on a background task is killed, and the Run fails with 'no PR found' #58

Closed

Description

@JacobStephens2

This was generated by AI during triage.

A Run on JacobStephens2/vacation#29 failed with no PR found after the implement session ended while the agent was still waiting on a background test run.

The agent started ./mvnw test -Dtest='GamesPageTest' with run_in_background: true, said "Waiting on the test run's completion notification.", and ended its turn (stop_reason: end_turn, terminal_reason: completed). Headless claude -p then exited and killed both background Bash tasks ("status":"killed" in the stream). The agent never committed, pushed, or ran gh pr create, so the Run's PR check failed. The work survived only because the Failed run path committed and pushed it (2a4a624 on issue-29).

The terminal showed only thirdshift: no PR found, which hides the cause.

Session log: ~/.thirdshift/logs/JacobStephens2-vacation-issue-29-20260925T213850Z-implement.jsonl

Activity

  1. JacobStephens2 commented on Sep 25, 2026

    @JacobStephens2
    OwnerAuthor

    This was generated by AI during triage.

    Agent Brief

    Category: bug
    Summary: A session that ends its turn while waiting on a background Bash task is killed mid-job, and the Run fails with an unexplained no PR found

    Current behavior:
    thirdshift runs each session with claude -p. If the agent starts a Bash command with run_in_background: true and then ends its turn to wait for the completion notification, the CLI exits and kills the background task. That is different from background sub-agents, which the session does wait for and resume after (the Progress docs assume every waiting session resumes). The implement session therefore stops before committing or opening a PR. The Run then pushes, fails open_pr with no PR found, and takes the Failed run path. Nothing on stderr says the session ended while waiting on a killed task. A Repair session could hit the same thing and leave CI unfixed.

    Desired behavior:

    1. Prevention: the prompts for every session kind (prompt::fresh, prompt::continuation, prompt::conflict_repair, prompt::ci_fix_repair) tell the agent that it runs headless: run tests and other long commands in the foreground (raising the Bash timeout if needed), and never end its turn while a background task it depends on is still running, because ending the turn ends the session and kills the task.
    2. Recovery: when a session exits cleanly but its stream shows background tasks that were killed at the end (system events with subtype: "task_updated" and patch.status: "killed", or a task_notification with status: "stopped", after the last result), thirdshift resumes that same session once with claude -p --resume <session_id>. It passes a short prompt saying the background work was killed when the turn ended, and asking the agent to re-run whatever it was waiting on in the foreground and finish its job. The resumed session is logged and reported like any other: its own log file, labelled for example implement-resume, with progress lines and a summary. It runs through the same interrupt handling.
    3. Diagnosis: if the session still ends with killed background tasks after the one resume, the Run fails with an error that says so, naming the session kind and the killed task's description, for example implement session ended while waiting on a background task (./mvnw test ...), which was killed. It does not fall through to no PR found.

    Key interfaces:

    • Progress, or whatever condenses the stream: it records the session_id from system/init and whether background tasks were killed after the last result, and makes both available once the process exits
    • session::run: returns enough for the caller to know whether a resume is needed (for example a small outcome struct rather than ()), or does the single resume itself
    • The prompt builders: each gets the headless / no-background-waiting instruction; keep the wording in one place and share it
    • CONTEXT.md: if the resume counts as its own session kind, add it to the glossary alongside Repair

    Acceptance criteria:

    • Every prompt thirdshift sends includes the instruction to run long commands in the foreground and not end the turn while waiting on a background task
    • Given a recorded stream whose last result is followed by a killed background task, stream processing reports "killed background work" and the session id; a stream with no killed tasks, or with only background sub-agents that resumed, reports nothing
    • A session that ends with killed background tasks is resumed exactly once via --resume <session_id>, and the resumed session gets its own log path and progress lines
    • If the resumed session finishes its job (for implement, a PR exists), the Run continues as normal
    • If the resumed session also ends with killed background tasks, the Run fails with a message naming the session kind and the killed task, not no PR found
    • The Failed run path still commits and pushes uncommitted work in every one of these cases
    • Tests cover the stream detection with fixture lines and the resume-once / fail-with-reason behavior, using the same fake-claude approach the existing Run tests use

    Out of scope:

    • Resuming more than once, or making the resume count configurable
    • Resuming sessions that ended for other reasons (errors, max_turns, interrupts)
    • Changing how Repairs are counted against MAX_REPAIRS; a resume is not a Repair
    • CPU contention between Runs on the same machine (the vacation agent's first test run produced no output, apparently because another worktree was using the CPU); file that separately if it keeps happening
    • When an error response from thirdshift, comes back, give the user a sample command to address the problem #53's broader "suggest a command for each error" work
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

    bugSomething isn't workingready-for-agentFully specified, ready for an AFK agent

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions