Problem
CoS has a separate portos-cos runner so agent work can remain isolated from the main PortOS web process, but direct TUI sessions currently violate that boundary.
When an agent resolves to the direct TUI path (useRunner: false), its PTY is owned by portos-server. Restarting only portos-server therefore destroys the active agent session even though portos-cos remains online and has uninterrupted uptime. The task can then be recorded as completed or enter orphan retry handling despite never completing its work.
This defeats the purpose of running CoS separately: a safe web/API restart is still destructive to active agent work.
Observed behavior
In a live reproduction:
- A user task spawned through the Claude TUI path in an isolated worktree.
portos-cos remained online throughout.
- Restarting only
portos-server terminated the server-owned TUI session.
- The persisted agent output contained only the lifecycle events for starting the TUI and pasting the prompt—no completion output.
- The agent record was nevertheless shown as completed; after an automatic retry was interrupted the same way, the task was blocked by orphan retry cooldown.
Identifiers, paths, host details, and task contents are intentionally omitted.
Expected behavior
A portos-server restart must not terminate an active CoS TUI agent. After the server comes back, it should reconnect to the durable agent owner, rediscover the running session, and resume relaying output/state.
A deliberate full-stack restart may still stop agents, but that should be an explicit, distinguishable operation.
Proposed direction
Move PTY/TUI process ownership out of portos-server and into the durable portos-cos runner (or another dedicated process). The server should act as a reconnectable control/relay client rather than the lifecycle owner.
Also harden recovery semantics:
- Never infer success from a closed/disappeared PTY without a valid completion signal.
- Classify a host-process interruption as interrupted/orphaned, not completed.
- Preserve the task worktree/branch and resume pointer for recovery.
- Do not consume normal agent failure/retry budget for a PortOS host restart.
- Reconcile runner-owned active sessions when
portos-server reconnects.
Acceptance criteria
Problem
CoS has a separate
portos-cosrunner so agent work can remain isolated from the main PortOS web process, but direct TUI sessions currently violate that boundary.When an agent resolves to the direct TUI path (
useRunner: false), its PTY is owned byportos-server. Restarting onlyportos-servertherefore destroys the active agent session even thoughportos-cosremains online and has uninterrupted uptime. The task can then be recorded as completed or enter orphan retry handling despite never completing its work.This defeats the purpose of running CoS separately: a safe web/API restart is still destructive to active agent work.
Observed behavior
In a live reproduction:
portos-cosremained online throughout.portos-serverterminated the server-owned TUI session.Identifiers, paths, host details, and task contents are intentionally omitted.
Expected behavior
A
portos-serverrestart must not terminate an active CoS TUI agent. After the server comes back, it should reconnect to the durable agent owner, rediscover the running session, and resume relaying output/state.A deliberate full-stack restart may still stop agents, but that should be an explicit, distinguishable operation.
Proposed direction
Move PTY/TUI process ownership out of
portos-serverand into the durableportos-cosrunner (or another dedicated process). The server should act as a reconnectable control/relay client rather than the lifecycle owner.Also harden recovery semantics:
portos-serverreconnects.Acceptance criteria
portos-server.portos-serverdoes not send a termination signal to active CoS TUI agents.