mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
Chasing why the pane-retry path could not request source recovery turned up the real answer: nothing can. Recovery is dead on every SSH reconnect, and the byte tail is not a fallback but the only path that has ever run. Five links, each read rather than inferred. setWrite reuses primaryClient including its id, so a reconnected client presents the SAME clientId. activate() tests exactly that at line 99 and returns 'existing' at 108, which makes the rotateDelivery branch at 118-142 reachable only when the ids differ — never here. So no sourceRecovery comes back, so finishSourceRecovery fails its !pendingRecovery guard and abandons, cancelling the delivery and deleting the checkpoint. The pane retry then opens fresh and takes the tail. This also explains the blank panes exactly. The relay concluded that this client already held the stream because, by its own identity rule, it does. The fix that implies is smaller than anything proposed so far and avoids what sank the three earlier attempts: bump a transport generation on the client record in setWrite and compare it alongside clientId, so a reconnect rotates the delivery instead of matching as 'existing'. Deliveries still outlive their clients and nothing retires on onClientDetached — the rotation happens on re-attach, which is what the recovery design already intends. RequestContext, setWrite and the publication are all relay-internal, and client and relay ship in one build, so there is no wire change and no compatibility exposure. Left explicitly unverified: whether rotateDelivery's identity preconditions hold at that moment, whether outputFlowControl is granted on the reconnected session, and what a rotation gives the RENDERER — which still remounts an empty xterm and needs a screen, not a post-checkpoint delta. Recovery keeps main's model whole; it does not by itself repaint a fresh terminal, so the tail may still be wanted for the pane even once the model stops going stale.