Files
orca/tests/e2e/helpers
Jinwoo Hong e2ccf52dc3 fix(remote-runtime): a paired terminal accepts input again after its host app relaunches (#25736)
* test(remote-runtime): reproduce dead input after a paired host relaunch

A relaunched desktop host accepts RPC before its renderer publishes a window
graph. During that gap session.tabs.list answers with an unpublished empty
graph (publicationEpoch "none", snapshotVersion 0, tabs []). The client's
reconnect inventory treats that as removal and retires the pane
(retireRemoteTerminalId(-1)): the pane goes to "ended", the reconnect overlay
disappears, and keystrokes never reach the surviving daemon PTY.

Both tests are red on main by design; they are the repro for the fix.

- e2e: holds the relaunched host's runtime:syncWindowGraph so the client's
  reconnect deterministically meets the unpublished host (4/4 red).
- unit: transport-level repro of the same retirement (red in ~2s).
- restart helper gains a beforeFirstWindow hook; LaunchOptions moves to its
  own module to stay under the max-lines budget.

* fix(remote-runtime): a paired terminal survives its host app relaunching

After the host app quit and relaunched (daemon still running), a paired
client's terminal cleared its reconnect overlay and then ignored all input.
The relaunched host answers session.tabs.list before its renderer publishes,
with a synthesized empty frame. A paired client sees that frame through its
navigation projection as epoch "none:client-navigation", which the shared
"does this frame answer for the worktree" check did not recognise, so the
pane read it as removal and retired itself.

- hostSnapshotAffirmsWorktreeContents treats the client-projected placeholder
  as no answer at any version (the projection adds its navigation revision).
- The reconnect inventory keeps polling on such a frame instead of retiring;
  a published frame lacking the surface still retires the pane.
- Pushed frames that affirm nothing no longer report the surface absent.
- When the bounded inventory wait ends without evidence, the first published
  snapshot carrying the same handle now reattaches the pane, rather than
  waiting out the ~3 minute auto-recovery deadline.

Client-only: the host already labels the frame, old hosts send the same
frame, and the wire is unchanged. The e2e helper drops its type assertions.

* refactor(remote-runtime): simplify the host-relaunch reconnect fix

- One epoch rule: the placeholder epoch, bare or with the shared
  client-navigation suffix, is no answer. Hosts only ever send it at
  version 0, so the version check is dropped.
- Unpublished frames are dropped where pushed snapshots enter, instead of
  a nullable per-subscriber update.
- A published same-handle snapshot fires the parked retry through
  retryNow(), which now also fires a retry parked while still
  'recovering' (nothing is in flight then). This replaces state-reading
  wiring in the listener and lets online/resume fire it too.
- The Windows e2e runs the fixture through PowerShell's call operator.

* test(remote-runtime): prove the e2e hold beat the relaunched host's first publish

The spec now asks the held host for its tab list and requires the
unpublished placeholder before releasing, so a hold installed too late
fails instead of passing against unfixed code. The helper keeps its gate
in a typed global instead of Reflect lookups.

* fix(remote-runtime): keep a fenced handle's parked retry revivable

A retry parked for a handle that needs a replacement was consumed by an
early external trigger and then refused by the epoch's snapshot-wait
guard, leaving nothing to revive the pane. An external trigger now takes
over that snapshot wait as a fresh attempt, and a republished fenced
handle no longer fires the retry. Also refreshes comments that still
paired the placeholder epoch with version 0.

* fix(remote-runtime): a host answers an empty worktree for real once it has published

The host sent its unpublished placeholder for any worktree it had no
entry for, including one its window had never opened, long after
startup. With the placeholder now read as "ask me later", a paired client
opening such a worktree never got its first terminal.

The host now sends the placeholder only until its graph first publishes.
Afterwards a worktree with no tabs gets a real empty answer, and a client
that was told "ask me later" during startup is sent that answer once on
publication. Against an older host the client withholds the automatic
first terminal for such a worktree, which the user can still create.

A host push now fires only a parked retry, never cutting a scheduled
backoff short.

* chore(reliability-gates): reference the empty-worktree tests in gate commands

* test(remote-runtime): find the never-opened worktree by repo id on every platform
2026-10-06 00:47:27 -04:00
..