You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A thirdshift-plugin-* temp dir can outlive its Run #24
After the vacation#5 acceptance run (#12), /tmp/thirdshift-plugin-AVc5lH/ (skills + .claude-plugin) was still there. Its mtime is 11:55 UTC, before that run started at 12:38, so an earlier run or test leaked it, not the acceptance run.
What we know
Plugin wraps a tempfile::TempDir (src/plugin.rs), so the dir is removed only if Plugin is dropped. SIGINT/SIGTERM are recorded and go through the Failed run path (src/interrupt.rs), so those should clean up. Candidates not verified: SIGKILL or a closed terminal (SIGHUP isn't handled), a panic with panic = "abort", a std::process::exit while the Plugin is alive, or a test that leaks it.
To do
Find which path leaked it. Consider handling SIGHUP too, and/or sweeping stale thirdshift-plugin-* dirs at startup.
Category: bug Summary: Treat SIGHUP like SIGINT and SIGTERM, so a Run whose terminal closes goes through the Failed run path and cleans up
Current behavior:
SIGINT and SIGTERM are recorded, not fatal: the Run stops its agent session, goes through the Failed run path, and removes the plugin temp directory. Verified during triage: with an extra check added to the existing SIGINT/SIGTERM tests, the scenario's $TMPDIR is empty afterwards.
SIGHUP (such as a closed terminal) isn't handled, so thirdshift dies on the spot. Verified during triage with a throwaway test that sends HUP while the fake agent runs:
the thirdshift-plugin-* directory is left in $TMPDIR
the agent session keeps running after thirdshift is gone, because it runs in its own process group and nothing stops it (the fake agent finished its full sleep 30)
there is no Failed run: no failure commit and no push, so the work in the worktree isn't saved
For context: the leak that prompted this issue came from a real Run for #7 (started 11:55:33, and its session log ends 12s later with [Request interrupted by user]), not from a test. Tests set TMPDIR to their own scenario directory, so they can't leak into /tmp. Which signal killed that Run couldn't be pinned down, but SIGHUP is the confirmed path the current code doesn't handle.
Desired behavior:
SIGHUP behaves the same as SIGINT and SIGTERM:
the Run is marked interrupted
the running agent session is stopped (its whole process group)
the Run goes through the Failed run path: work is pushed and the failure is reported as interrupted
the plugin temp directory is removed
Key interfaces:
The interrupt module's install(): it registers the signals that set the interrupt flag, and should include SIGHUP. Its module doc names the handled signals and should be updated to match.
interrupt::requested(): unchanged; SIGHUP just sets the same flag.
The interrupt tests in the Failed run test suite (assert_interrupt_fails_the_run(signal) and the per-signal tests that call it).
Acceptance criteria:
Sending SIGHUP to thirdshift while an agent session runs stops the session within the existing stop grace period, and the Run finishes well before the fake agent's own sleep would end
After SIGHUP, the Issue branch on origin has the thirdshift: failed run (interrupted) commit containing the agent's half-done work, the same as the SIGINT and SIGTERM tests check
A SIGHUP test exists alongside the SIGINT and SIGTERM tests
The shared interrupt assertion checks that the scenario's tmp/ directory is empty afterwards, for all three signals
cargo test passes
Out of scope:
Sweeping stale thirdshift-plugin-* directories at startup. Runs can overlap, so a blind sweep would delete a live Run's plugin; a safe sweep needs a liveness design, which is a separate decision
SIGKILL, which can't be handled
Changing the interrupt semantics or the Failed run path beyond adding SIGHUP
Activity
JacobStephens2 commentedon Sep 25, 2026
Agent Brief
Category: bug
Summary: Treat SIGHUP like SIGINT and SIGTERM, so a Run whose terminal closes goes through the Failed run path and cleans up
Current behavior:
SIGINT and SIGTERM are recorded, not fatal: the Run stops its agent session, goes through the Failed run path, and removes the plugin temp directory. Verified during triage: with an extra check added to the existing SIGINT/SIGTERM tests, the scenario's
$TMPDIRis empty afterwards.SIGHUP (such as a closed terminal) isn't handled, so thirdshift dies on the spot. Verified during triage with a throwaway test that sends HUP while the fake agent runs:
thirdshift-plugin-*directory is left in$TMPDIRsleep 30)For context: the leak that prompted this issue came from a real Run for #7 (started 11:55:33, and its session log ends 12s later with
[Request interrupted by user]), not from a test. Tests setTMPDIRto their own scenario directory, so they can't leak into/tmp. Which signal killed that Run couldn't be pinned down, but SIGHUP is the confirmed path the current code doesn't handle.Desired behavior:
SIGHUP behaves the same as SIGINT and SIGTERM:
interruptedKey interfaces:
install(): it registers the signals that set the interrupt flag, and should include SIGHUP. Its module doc names the handled signals and should be updated to match.interrupt::requested(): unchanged; SIGHUP just sets the same flag.assert_interrupt_fails_the_run(signal)and the per-signal tests that call it).Acceptance criteria:
thirdshift: failed run (interrupted)commit containing the agent's half-done work, the same as the SIGINT and SIGTERM tests checktmp/directory is empty afterwards, for all three signalscargo testpassesOut of scope:
thirdshift-plugin-*directories at startup. Runs can overlap, so a blind sweep would delete a live Run's plugin; a safe sweep needs a liveness design, which is a separate decisionMerge pull request #76 from JacobStephens2/issue-64