Tracking issue for docs/designs/01-daemon-canonical-terminal.md (Accepted).
Problem
When a single agent harness emits sustained PTY output, the desktop GPUI thread becomes unresponsive until the harness calms down. The render thread is on the parse path: LiveTerminalRuntime::apply_output (app/src/terminal_runtime.rs:283) runs alacritty_terminal::vte::ansi::Processor::advance synchronously inside drain_terminal_launch_replies (app/src/app.rs:6059) and drain_session_events (app/src/app.rs:5910). Existing mitigations (DRAIN_OUTPUT_BYTE_CAP, watchdog from #125) limp under typical load.
Decision
Per the design doc:
- One
alacritty_terminal::Term per PTY, owned by a per-tab tokio task in the daemon.
- New wire:
SessionEvent::TerminalFrame { Full | Diff } with monotonic seq, pull-paced via Control::TerminalSubscribe { max_fps, since_seq }.
- Scrollback + search become RPCs (
Control::TerminalReadScrollback, Control::TerminalSearch).
- Bell/title via dedicated
WorkerReply::Push variants.
- PTY spawn moves to the daemon; GPUI-side fulfillment (
pending_tab_launches, TabResizeRequest) goes away.
- Inactive tabs still parse daemon-side; no frames emitted for unsubscribed (viewer, tab) pairs.
terminal-wrapping-principle refined: ANSI/VT parsing may live daemon-side; per-agent semantic parsing still forbidden.
Phases (see design doc for sub-phase breakdown)
References
Tracking issue for
docs/designs/01-daemon-canonical-terminal.md(Accepted).Problem
When a single agent harness emits sustained PTY output, the desktop GPUI thread becomes unresponsive until the harness calms down. The render thread is on the parse path:
LiveTerminalRuntime::apply_output(app/src/terminal_runtime.rs:283) runsalacritty_terminal::vte::ansi::Processor::advancesynchronously insidedrain_terminal_launch_replies(app/src/app.rs:6059) anddrain_session_events(app/src/app.rs:5910). Existing mitigations (DRAIN_OUTPUT_BYTE_CAP, watchdog from #125) limp under typical load.Decision
Per the design doc:
alacritty_terminal::Termper PTY, owned by a per-tab tokio task in the daemon.SessionEvent::TerminalFrame { Full | Diff }with monotonic seq, pull-paced viaControl::TerminalSubscribe { max_fps, since_seq }.Control::TerminalReadScrollback,Control::TerminalSearch).WorkerReply::Pushvariants.pending_tab_launches,TabResizeRequest) goes away.terminal-wrapping-principlerefined: ANSI/VT parsing may live daemon-side; per-agent semantic parsing still forbidden.Phases (see design doc for sub-phase breakdown)
max_fpshonoring (deferred; own issue when triggered)References
docs/designs/01-daemon-canonical-terminal.mddocs/architecture/terminal-wrapping-principle.md