Repository navigation
feat(host): keep sessions running in a background host you can attach to - #652
jiro-by-nori[bot] wants to merge 3 commits into
Conversation
|
D2 visual verification for Current PR head: flowchart LR
C["Terminal A · controller"] -->|"authenticated commands"| H["Background host"]
W["Terminal B · watcher"] -->|"authenticated subscribe / Alt+T takeover"| H
H -->|"sequenced replay + live events"| C
H -->|"sequenced replay + live events"| W
H --> M["SessionManager"]
M --> A["ACP agent processes"]
H --- O["One controller at admission; other terminals watch"]
|
|
Independent verification of Result: 0 blockers, 2 should-fix issues, 1 nit.
The lifecycle/auth/controller/replay checks below pass. Child-row alignment is not covered end to end: D2 exposes no supported child-creation operation; Test totalsReal mock ACP subprocesses, real host processes and sockets, and tmux-driven attached terminals. All requested suites ran with
Independent wire/lifecycle probe: 38 assertions passed, 0 failed (separate from Cargo totals). The known flaky Full test logs and reproduction scripts Completed suite totals and verification summary Finding evidenceShould-fix: old attachment remains reconnecting after same-port restart Fresh attachment sees the new empty host Should-fix: long TITLE wraps beneath ID at 120 columns Nit: current badge consumes the current row ID Wire proofTokens are deliberately omitted. These excerpts came from real connections to the running host: {"jsonrpc":"2.0","id":3,"error":{"code":-32016,"message":"watcher is read-only; take control before changing a session"}}All three clients received contiguous prefixes Scenario capturesEvery image is a 120×40 terminal rendered from actual tmux ANSI using Ghostty Web 0.4.0. DejaVu Sans Mono, Noto Sans Symbols and Noto Sans Symbols 2 were installed first. Raw ANSI is retained; only the final row delimiter was removed for rendering, preventing the header from scrolling off-screen. Summary panels show actual probe results, not simulated application screens. Lifecycle and auth: start, duplicate, last close, stop, stale kill-9 recovery, occupied port and permissionsHost starts detached; duplicate start retains PID Independent lifecycle and auth assertions Last session is closed; attached host stays alive Host remains listable after last close and stops explicitly Attach, creation, detach and reattach historyPlain attach opens the empty session list Plain attach opens the nonempty session list Session created from attach; first client controls Named reattach restores full short transcript once Controller/watcher: three clients, refused mutations and takeoverWatcher prompt is refused with a clear read-only error Former controller is notified and continues watching Watcher cannot resolve pending permission Third client takes control and resolves the pending permission Takeover during a streaming turn; new controller cancels Three-client wire assertions and exact replay cursors Dropped TCP and silent lossAbrupt TCP close: reconnecting after 0.3 seconds TCP recovery: missed prompt and response replay once Sockets stay open without traffic: detected after 9.9 seconds Silent-loss recovery: missed prompt and response replay once Recovered client takes control and submits another prompt D1 Ctrl+R and single-session regressionFailed row selected for Ctrl+R Ctrl+R preserves the ID, second-row position and history Existing watcher receives the post-restart turn under the same ID multi_session=false: ordinary single-session prompt and answer Build and all testing used the exact head above. Product tree remained unchanged; proof files live only on |
D2 verifier fixes — terminal proofCaptured from Same-port restartStarted a host, attached, created a session, and retained an unsent draft. Stopped the host, then started a new empty host on the same port. The old attachment refreshed the local token once, detected the new host instance, and stopped reconnecting before replay. The persistent message says “Host restarted; sessions were lost. Re-run nori attach.” History and the draft remain visible; Ctrl+D detaches. Long title in the host table
Current session IDThe selected row keeps short ID Verification
Linux CI and cargo-deny passed on The PR remains draft, based on |





































Summary
🤖 Generated with Nori
nori hostnow owns sessions in a background Unix process. Terminals can detach without stopping agents, and an empty host stays alive untilnori host stop.nori host lsprints the flat ID / AGENT / STATUS / AGE / TITLE table, with TTY status colors, terminal-width title truncation, and full plain titles when piped.Feature-gated
nori attachopens the session list;nori attach <id>opens a conversation. Every host connection requires a private bearer token, including loopback; same-machine clients discover it automatically. The first terminal controls, later terminals watch, and Alt+T transfers control without disconnecting either terminal. Watcher prompts and permission answers are refused. Attachments reconnect after socket failure or a silent connection outage and resume from their applied sequence cursor without retrying ambiguous mutations. Reconnect validates the host instance before replay. Local attachments refresh discovered credentials once on an authentication rejection; a replaced host or failed refresh leaves a persistent explanation and asks the user to runnori attachagain. Session-list selection keeps the short ID visible.Stacked D2 on
feat/multi-session-d-remote/ #651. Draft; never merge. Existing single-session startup and the legacy--remotesurface retain their behavior. Host attachment uses the existingmulti_sessionflag.Design and boundaries
/acproute on the host./sessionsopen the list. Ctrl+R resumes a failed row under the same Nori ID. Ctrl+D detaches.Validation
--all-features --tests,-D warnings) pass.--no-fail-fast: transport 114 passed, harness 432 passed / 1 ignored, TUI 1,472 passed / 4 ignored, CLI 69 passed, and all 8 D2 PTY tests passed. Full PTY: 193 passed / 9 ignored. Total: 2,280 passed, 0 failed, 14 ignored; the known cloud auth-error test passed on its first attempt.9b65150833f4f4ed9232e6df381aea5d4d9fc587. Linux CI: 2,454 passed, 0 failed, 14 ignored, with formatting, build, and Clippy passing.Original terminal proof and host/controller/watcher diagram.
Verifier-fix terminal proof: restart notice, truncated host table, and visible current-row ID.
Originating chat: https://demo.norisessions.com/chat/01a1df89-8a29-7764-9c1b-06afdcc05775
Share Nori with your team: https://www.npmjs.com/package/nori-skillsets