Jobs Attach Interrupt
Scope#
Handle Ctrl-C while codealmanac jobs attach <run-id> is following a run.
Stop only the foreground attach stream, leave the underlying run untouched, and
show the exact command for cancelling that run.
Out of scope#
- Changing worker process isolation.
- Changing run cancellation behavior.
- Handling broken output pipes.
- Adding a new JSON event shape for a local CLI interruption.
Design#
jobs attach owns the interruption boundary because it is the only command that
can truthfully say the user stopped following a background run. It catches
KeyboardInterrupt, renders a concise detachment notice for human output, and
returns the conventional interrupted exit code, 130.
JSON attach output remains an uninterrupted NDJSON event stream: interruption
adds no non-JSON notice and is represented by exit code 130.
File changes#
src/codealmanac/cli/dispatch/jobs.py: catch attach interruption and return130.src/codealmanac/cli/render/job_logs.py: render the human detachment and cancellation guidance.src/codealmanac/cli/render/admin.py: export the renderer.tests/test_cli.py: cover human and JSON interruption behavior and prove the run is not mutated.almanac/reference/runs/run-states-and-events.md: document the public attach interruption contract.
Test coverage#
- No traceback or stderr output after
Ctrl-C. - Human output includes the exact cancellation command.
- Exit status is
130. - Run status remains unchanged.
- JSON output receives no human detachment text.
Read before coding#
MANUAL.mdalmanac/reference/runs/run-states-and-events.mdsrc/codealmanac/cli/dispatch/jobs.pysrc/codealmanac/cli/render/job_logs.py