Skip to content

Warn when remote terminal input delivery cannot be confirmed - #26548

Open
nwparker wants to merge 3 commits into
OrcaWin/phase35from
nwparker/remote-terminal-input-receipts
Open

nwparker wants to merge 3 commits into
OrcaWin/phase35from
nwparker/remote-terminal-input-receipts

Conversation

@nwparker

@nwparker nwparker commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 13 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​682 $\color{#cf222e}{\Huge{\mathbf{−}}}$​72 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​610
Prod 22 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​408 $\color{#cf222e}{\Huge{\mathbf{−}}}$​48 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​360

ELI5

A remote terminal can look connected while its network has stopped carrying data. Typing in that window may never arrive, or it may run while the reply gets lost. Orca now warns you to check the terminal before retrying; it does not resend an uncertain command.

What Changed

Ordinary keyboard batches now request host write receipts. New hosts negotiate ackInput: 1, reuse the existing Input frame's sequence field, and return a JSON receipt after the PTY provider settles the write. Older hosts use the existing terminal.send request/reply path. No new binary opcode is introduced, and unnegotiated clients keep their existing behavior.

Unanswered writes show a persistent, dismissible warning after 15 seconds or stream teardown. Unrelated output cannot settle a receipt. Parser replies remain untracked. A thrown stream handoff cannot trigger an automatic RPC resend. Receipt state retains only bounded numeric IDs and times.

Why

A controlled real SSH TCP stall reproduced missing input while Orca still reported connected. Receipt loss cannot distinguish a lost command from an executed command whose reply vanished, so automatic replay could execute it twice. Execution-host receipts preserve that distinction and keep the existing binary batching for updated peers.

Linked Issue

Related: SSH consolidation #26483, known half-open input finding F1.

Visual Proof

Before: reconnect silently loses the DURING line; the same remote process receives BEFORE and AFTER.

Before

After: the warning remains visible after reconnect, with the same process and no replay.

After

Original host-ledger reproduction, unchanged-app warning failure, final source-built server run, older-server run.

Testing

CI integration follow-up: the sidecar subscription test now requires ackInput:1, and the half-open SSH test runs in the managed-server lane that builds its template. Source routing, dedicated-job selection, and lane reachability are covered by 65 passing integration tests.

  • I manually tested these changes locally
  • Automated tests added/updated

Hidden macOS Electron + Linux arm64 Docker SSH: both a two-way TCP stall and a reply-only stall pass against the source-built server, then pass against the installed pre-receipt server. A final source-built run passes both again. The independent host ledger requires one process, BEFORE/AFTER exactly once, lost DURING absent for a two-way stall, and executed DURING exactly once for a reply-only stall. Real keyboard input and the rendered warning are asserted; warnings appear around 15.1–15.3 seconds. Faults use an owned TCP proxy, not a claimed physical network outage.

330 affected tests across 52 files pass (one existing skip), including batching, stale stream fencing, output recovery, rejected-write pane recovery, and no fallback resend after a handoff throws. The 10-test real-release terminal wire suite also passes, including both mixed-version pairings; only new/new negotiates input receipts. Full pnpm tc, pnpm lint, changed-code quality, Electron e2e build, and headless-server build pass.

Reliability class/gate: terminal-input.remote-delivery-uncertainty, experimental. Invariant: only host receipts settle writes; uncertainty stays visible without replay or process replacement. Local/daemon transports are unchanged, with the Linux daemon exercised through the host. Native Windows/WSL and Linux desktop clients remain coverage gaps. Receipts prove provider acceptance, not command execution; old hosts that omit settlement fields prove request receipt only.

Performance: existing 8 ms batching stays; updated peers send without awaiting prior round trips. At most 1,024 numeric receipts and one deadline timer per active stream; no polling, inventory scans, subprocesses, or startup waits. Broad WAN latency and long-term soak remain unproved.

Review

Self-reviewed stream teardown, same-ID replacements, host-owned settlements, old-peer fallback, parser replies, and both directions of network uncertainty. This addresses silent input uncertainty; it cannot recover an unacknowledged command safely.

Agent skill upstream boundary

  • Not applicable; no upstream skill-installer material copied.

Checklist

  • This PR is small and focused on remote keyboard delivery uncertainty
  • Explained ELI5, before/after, mechanism, and alternative
  • Before/after screenshots and real-host logs attached
  • Self-reviewed correctness, security, and performance
  • Cross-platform, SSH/remote, and wire compatibility considered
  • Local lint, typecheck, affected tests, and builds pass

@nwparker
nwparker requested a review from brennanb2025 as a code owner October 8, 2026 10:45
@OrcaWin

OrcaWin commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #26630, which negotiates input sequence numbers and acks on the same Input frame seq field and replays unconfirmed input instead of warning. Landing both would put two ack protocols on the wire. The warning for non-replayable cases (old hosts, respawned terminals) may be folded into #26630 as a follow-up.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants