Optional abduco nesting so sessions survive the agent #19

Open
opened 2026-08-19 23:58:48 +00:00 by dusan · 0 comments
Owner

Context

The agent owns every pty master, which is what lets sessions outlive their
windows. The consequence is written down as a failure mode in
docs/spec/session-agent.md:

The agent dying takes every session with it — all masters close, all
children get SIGHUP. Mitigation is to keep the agent small and panic-free:
unwrap and expect are denied in this crate, so failures are values.
Optional per-session abduco nesting remains available if this ever bites.

The first mitigation is in place. This issue is the second one, which the plan
listed as optional and to be added "only if it bites".

What it would mean

abduco (ISC, ~1.5k lines) detaches a program from its controlling terminal:
abduco -A name command creates or attaches to a session. Running a session's
command under it means the child survives even the agent dying — at the cost of
another pty layer between Terminalko and the program.

Shape of the work:

  • a per-session setting, off by default, since it changes what the session
    actually runs;
  • crates/terminalko-agent/src/launch.rs is where it belongs: it already turns a
    session's configuration into an argument list as a pure function, with 24 tests,
    and this is one more transformation — wrap the computed argv rather than special
    casing each kind;
  • recovery is the interesting half and the reason to be careful: after the agent
    is restarted, sessions that were nested are not in its HashMap any more.
    Something has to enumerate abduco's socket directory and re-adopt them, which
    means a session identity that survives the agent — today the id is a GSettings
    UUID, which does survive, so name the abduco session after it;
  • abduco must be a runtime dependency only when the setting is on: preflight
    already refuses a session whose program is missing, and the message should say
    which program and why.

Whether to do it

Only with evidence. The question to answer first: has the agent ever died on
you?
It is a small single-purpose process with panics denied in the pty and IPC
paths, and nothing has reported a crash. Two pty layers per session is a real
cost — resize forwarding, signal propagation and an extra process each — for a
failure nobody has seen.

If issue #18 (socket activation) lands, a crashed agent is also restarted
automatically, which makes the recovery path here more valuable and the crash
itself less damaging. Consider that first.

Acceptance criteria

  • With the setting on, killing the agent with SIGKILL leaves the session's
    program running, and a new agent re-adopts it and can attach a window to it with
    its output.
  • With the setting off, nothing changes at all: same argv, same tests.
  • Resizing and Ctrl+C behave the same through the extra layer — the nested-pty
    resize test (a_resize_reaches_a_terminal_nested_in_another) is the model to
    follow.
  • docs/spec/session-agent.md explains the setting and its cost.

Notes

## Context The agent owns every pty master, which is what lets sessions outlive their windows. The consequence is written down as a failure mode in `docs/spec/session-agent.md`: > **The agent dying takes every session with it** — all masters close, all > children get `SIGHUP`. Mitigation is to keep the agent small and panic-free: > `unwrap` and `expect` are **denied** in this crate, so failures are values. > Optional per-session `abduco` nesting remains available if this ever bites. The first mitigation is in place. This issue is the second one, which the plan listed as optional and to be added "only if it bites". ## What it would mean `abduco` (ISC, ~1.5k lines) detaches a program from its controlling terminal: `abduco -A name command` creates or attaches to a session. Running a session's command under it means the child survives even the agent dying — at the cost of another pty layer between Terminalko and the program. Shape of the work: * a per-session setting, off by default, since it changes what the session actually runs; * `crates/terminalko-agent/src/launch.rs` is where it belongs: it already turns a session's configuration into an argument list as a pure function, with 24 tests, and this is one more transformation — wrap the computed argv rather than special casing each kind; * recovery is the interesting half and the reason to be careful: after the agent is restarted, sessions that were nested are **not** in its `HashMap` any more. Something has to enumerate abduco's socket directory and re-adopt them, which means a session identity that survives the agent — today the id is a GSettings UUID, which does survive, so name the abduco session after it; * `abduco` must be a runtime dependency only when the setting is on: preflight already refuses a session whose program is missing, and the message should say which program and why. ## Whether to do it Only with evidence. The question to answer first: **has the agent ever died on you?** It is a small single-purpose process with panics denied in the pty and IPC paths, and nothing has reported a crash. Two pty layers per session is a real cost — resize forwarding, signal propagation and an extra process each — for a failure nobody has seen. If issue #18 (socket activation) lands, a crashed agent is also restarted automatically, which makes the recovery path here more valuable and the crash itself less damaging. Consider that first. ## Acceptance criteria - With the setting on, killing the agent with `SIGKILL` leaves the session's program running, and a new agent re-adopts it and can attach a window to it with its output. - With the setting off, nothing changes at all: same argv, same tests. - Resizing and `Ctrl+C` behave the same through the extra layer — the nested-pty resize test (`a_resize_reaches_a_terminal_nested_in_another`) is the model to follow. - `docs/spec/session-agent.md` explains the setting and its cost. ## Notes - <https://github.com/martanne/abduco> — ISC, so adapting code is allowed with an entry in `NOTICE`; see `CONTRIBUTING.md`.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dusan/terminalko#19
No description provided.