Repository navigation
Run skills in the background, watchable and detachable - #7
Merged
Merged
Conversation
Runs used to live inside the launching terminal: closing it (or an incautious ctrl+c) killed a 10-minute audit, and one attach session owned the only live view. Every run now executes in a detached worker process (setsid, survives the terminal): `run` starts it in the background and attaches by default, `-d` fires and forgets. The worker owns the run's lifetime, turns stop signals into the same graceful context-driven teardown an interactive abort used, and writes the existing journal (spec, stream, result, pid) that everything else reads. The journal is the event bus: `attach` replays it from the start and follows it live — ctrl+c detaches without cancelling (the common case is now instant and non-destructive), x twice cancels, and attaching to a finished run replays the whole transcript with its result. `runs` lists run states (running first, then newest), `stop` cancels through a SIGINT/SIGTERM/SIGKILL ladder, `logs` renders the transcript, and `result` prints the stored outcome exiting with the run's own code. Non-TTY attach degrades to a plain live tail; `--json` and `--no-monitor` keep the synchronous CI semantics. The monitor also shows tool results now — crush tool_result parts, truncated to keep the transcript readable — which are the bulk of a run's output and were previously invisible. Journal raw lines no longer duplicate parsed events, so replays render once. Verified end to end against the fake harness: detached start, live listing, ctrl+c detach with the run surviving, graceful stop writing an aborted result, replay of finished runs, and no orphaned workers. Fifty-five tests (race detector on), vet and staticcheck clean. 💘 Generated with Crush Assisted-by: Crush:rits/zai-org/glm-5-3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Runs used to live inside the launching terminal: closing it (or an incautious ctrl+c) killed a 10-minute audit, and one attach session owned the only live view. This PR moves every run into a detached worker process with the journal as the event bus:
runspawns a setsid worker (survives the terminal) and attaches by default;-d/--detachfires and forgets and prints the run id with hints. The worker writesoptions.jsonin, and the existing journal (spec, stream, result, pid) out; stop signals (SIGINT/SIGTERM) become context cancellations that flow through the same graceful teardown paths as before (crush cancel endpoint, server shutdown).attach <run>: replays the journal from the start and follows it live through the existing monitor. Ctrl-C / q / d detaches without cancelling — the destructive action is now the explicit one (xtwice). Attaching to a finished run replays the full transcript and exits with the run's code. Non-TTY attach degrades to a plain live tail.runs/stop/logs/result: run listing with a state machine (running/done/failed/needs-input/budget-stop/aborted/orphaned via result.json + pid liveness), a graceful SIGINT→SIGTERM→SIGKILL stop ladder, rendered journal transcripts, and stored results. Run ids get random 4-hex suffixes;attach/stop/resultaccept the suffix or any unambiguous prefix.tool_resultparts — the actual command/scanner output and the bulk of a run's transcript — now stream astool_resultevents (truncated to 6 lines/400 chars), rendered as dim blocks in the monitor and plain output. Journal raw lines no longer duplicate parsed events, so replays render once.--json/--no-monitorkeep the synchronous in-process CI semantics; the background path is the interactive default.Verification
runsshows running → ctrl+c detach with the run surviving → gracefulstopwriting an aborted result → replay of finished runs → no orphaned workers. A fast-run race (worker finishing before the parent's pid handshake) was found and fixed live.💘 Generated with Crush