Neil
905aa11ea1
fix(ssh): stop a reconnect deleting local state the host has not seen
...
Reported from a 60-second manual test: reconnect an SSH workspace and the app
drops to the home screen, a second tab running pnpm install is gone entirely, and
one launched agent is listed twice. Three symptoms, one cause.
The snapshot is applied as the whole truth for the reconnecting target. The tab
merge iterates only the host's worktrees, then the result is spread over a gap
where every local tab for that worktree has just been dropped — so a tab created
locally whose upload has not landed has no branch that keeps it. Not a race: it
cannot survive. Same for the pointers, where a snapshot that names no active
worktree nulls activeWorktreeId and activeWorkspaceKey, which is the home screen
while the user's terminals are still running.
So the host is now authoritative for what it knows and not for what it has never
been told. A local tab absent from the snapshot is kept, the worktree union is
used so a snapshot with no entry for it at all cannot erase it, and a null active
worktree only defers to local state when that workspace demonstrably still exists
in the merged result.
Two guards this change had to earn rather than assume. A null activeTabId is NOT
missing information — it is a deliberate deselect that arms the duplicate-tab
repair, and my first attempt defeated it and broke that test; it is honoured
verbatim now. And preserving by tab id alone reintroduces the duplicate agent,
because the host can carry the same session under a new tab id, so the preserve
also checks the remote session id — the identity that survives a tab-id change.
Testing, which is the part that failed here before. Eight tests fail on the
unfixed code and pass on this one, at two levels: the merge decision table, and
the real apply path driven through a store. The end-to-end version of the same
scenario is deliberately NOT the guard and now says so in its header — measured
against unfixed code it only reproduces about one run in three, because the
destruction needs the tab created inside the debounced upload's suppression
window and nothing external can force that. Its earlier green run is exactly why
this shipped.
2026-08-16 15:36:33 -07:00
..
2026-08-13 18:11:33 -07:00
2026-08-14 01:47:03 -07:00
2026-08-15 21:45:00 -07:00
2026-07-20 01:14:17 -07:00
2026-07-06 02:12:32 -07:00
2026-06-29 22:38:29 -07:00
2026-08-13 12:48:47 -07:00
2026-07-15 13:25:24 -07:00
2026-07-28 12:33:17 -07:00
2026-07-13 19:13:19 -07:00
2026-07-28 12:33:17 -07:00
2026-06-10 17:23:12 -07:00
2026-08-07 20:36:23 -07:00
2026-08-10 15:52:59 -07:00
2026-08-10 15:52:59 -07:00
2026-06-19 17:14:55 -07:00
2026-06-11 12:46:43 -07:00
2026-08-11 21:16:36 -07:00
2026-07-10 17:27:47 -07:00
2026-07-10 17:27:47 -07:00
2026-07-30 18:51:11 -07:00
2026-08-11 21:16:36 -07:00
2026-06-07 18:16:53 -07:00
2026-07-20 03:04:28 -04:00
2026-06-08 01:00:29 -07:00
2026-08-13 12:38:08 -07:00
2026-06-28 23:13:03 -07:00
2026-07-28 00:22:22 -07:00
2026-07-20 22:04:01 -04:00
2026-08-12 16:07:08 -07:00
2026-08-03 13:02:56 -07:00
2026-08-03 13:02:56 -07:00
2026-08-03 13:02:56 -07:00
2026-08-11 03:07:44 -07:00
2026-08-03 13:02:56 -07:00
2026-08-01 21:07:58 -07:00
2026-06-29 23:37:30 -07:00
2026-08-11 18:19:43 -07:00
2026-08-11 18:19:43 -07:00
2026-08-04 22:07:30 -07:00
2026-07-20 18:18:11 -07:00
2026-08-13 20:44:16 -07:00
2026-08-15 01:25:09 -07:00
2026-06-07 17:49:01 -07:00
2026-08-15 00:41:45 -07:00
2026-08-06 21:18:52 -07:00
2026-06-29 22:38:29 -07:00
2026-06-17 20:05:55 -07:00
2026-07-27 15:22:55 -07:00
2026-07-21 20:51:28 -07:00
2026-08-07 22:33:50 -07:00
2026-06-29 22:38:29 -07:00
2026-07-25 13:42:28 -07:00
2026-06-29 22:38:29 -07:00
2026-05-13 18:48:14 -07:00
2026-05-13 18:48:14 -07:00
2026-08-03 22:55:17 -07:00
2026-05-30 22:46:38 -07:00
2026-05-30 22:46:38 -07:00
2026-07-26 23:48:20 -07:00
2026-07-06 02:12:32 -07:00
2026-06-19 17:14:55 -07:00
2026-08-05 12:57:02 -07:00
2026-08-14 19:04:55 -04:00
2026-08-14 19:04:55 -04:00
2026-05-25 22:21:39 -07:00
2026-07-28 20:52:09 -07:00
2026-04-27 20:55:47 -07:00
2026-06-22 16:27:33 -07:00
2026-07-29 21:43:45 -07:00
2026-08-11 03:07:44 -07:00
2026-06-09 20:57:43 -07:00
2026-06-10 13:41:05 -07:00
2026-06-29 22:38:29 -07:00
2026-06-29 22:38:29 -07:00
2026-08-14 00:33:15 -07:00
2026-06-29 22:38:29 -07:00
2026-07-05 19:46:49 -07:00
2026-08-11 03:07:44 -07:00
2026-08-13 10:26:20 -07:00
2026-07-10 17:27:47 -07:00
2026-08-13 10:31:08 -07:00
2026-08-10 20:42:43 -07:00
2026-08-13 09:56:30 -07:00
2026-08-13 09:31:20 -07:00
2026-08-13 00:58:55 -07:00
2026-08-13 00:58:55 -07:00
2026-08-13 10:26:20 -07:00
2026-08-13 10:31:08 -07:00
2026-08-13 09:31:20 -07:00
2026-08-13 09:56:30 -07:00
2026-08-13 09:56:30 -07:00
2026-08-15 01:02:06 -07:00
2026-08-12 21:28:32 -07:00
2026-08-13 10:26:20 -07:00
2026-07-31 00:22:53 -07:00
2026-07-29 20:04:55 -07:00
2026-08-05 12:57:02 -07:00
2026-08-05 17:49:04 -07:00
2026-08-13 23:59:18 -07:00
2026-08-11 18:19:43 -07:00
2026-07-31 18:01:24 -07:00
2026-06-29 22:38:29 -07:00
2026-08-04 22:07:30 -07:00
2026-07-20 14:50:12 -07:00
2026-08-04 12:37:59 -07:00
2026-08-09 16:35:24 -07:00
2026-08-13 22:48:24 -07:00
2026-08-03 11:11:14 -07:00
2026-07-22 16:10:53 -07:00
2026-07-17 18:57:26 -07:00
2026-07-23 23:18:03 -07:00
2026-05-25 16:43:22 -07:00
2026-07-04 23:29:05 -07:00
2026-07-31 01:57:41 -07:00
2026-06-22 12:29:18 -07:00
2026-08-12 13:42:42 -07:00
2026-08-13 22:48:24 -07:00
2026-08-13 22:48:24 -07:00
2026-07-22 18:25:05 -07:00
2026-07-22 18:25:05 -07:00
2026-08-09 01:16:09 -07:00
2026-07-30 03:05:10 -07:00
2026-08-13 22:48:24 -07:00
2026-08-13 22:48:24 -07:00
2026-07-19 11:27:29 -07:00
2026-08-14 18:36:51 -07:00
2026-08-14 18:36:51 -07:00
2026-07-29 11:31:35 -07:00
2026-07-30 00:49:23 -07:00
2026-08-09 14:49:36 -07:00
2026-07-30 00:49:23 -07:00
2026-07-30 00:49:23 -07:00
2026-08-11 23:06:12 -07:00
2026-07-29 11:31:35 -07:00
2026-08-13 22:40:58 -07:00
2026-08-12 21:35:35 -07:00
2026-08-13 00:12:20 -07:00
2026-08-07 15:01:11 -07:00
2026-08-12 02:02:10 -07:00
2026-08-13 22:48:24 -07:00
2026-08-12 16:15:39 -07:00
2026-08-08 01:47:05 -07:00
2026-08-04 22:59:06 -07:00
2026-08-03 19:44:30 -07:00
2026-07-30 18:27:06 -07:00
2026-07-30 03:05:10 -07:00
2026-07-31 16:01:44 -07:00
2026-07-29 20:04:55 -07:00
2026-08-10 16:10:47 -07:00
2026-07-29 20:04:55 -07:00
2026-08-12 22:33:19 -07:00
2026-08-12 21:35:35 -07:00
2026-07-27 17:56:07 -07:00
2026-07-27 17:56:07 -07:00
2026-07-28 12:33:17 -07:00
2026-07-27 17:56:07 -07:00
2026-08-13 22:48:24 -07:00
2026-07-31 04:32:23 -07:00
2026-08-09 23:14:17 -07:00
2026-07-15 17:14:10 -07:00
2026-08-10 12:17:21 -07:00
2026-08-01 00:00:12 -07:00
2026-08-09 21:21:18 -07:00
2026-07-23 01:45:24 -07:00
2026-08-11 18:19:43 -07:00
2026-08-13 12:38:08 -07:00
2026-08-13 22:48:24 -07:00
2026-08-14 01:21:00 -07:00
2026-07-12 22:40:57 -07:00
2026-08-13 22:48:24 -07:00
2026-08-03 22:48:37 -07:00
2026-07-27 19:04:56 -07:00
2026-06-29 22:38:29 -07:00
2026-07-17 17:18:36 -07:00
2026-07-17 17:18:36 -07:00
2026-07-12 22:40:57 -07:00
2026-05-21 01:19:49 -04:00
2026-07-28 20:51:14 -07:00
2026-08-10 14:32:08 -07:00
2026-08-10 14:32:08 -07:00
2026-08-13 22:48:24 -07:00
2026-08-13 22:48:24 -07:00
2026-08-13 22:48:24 -07:00
2026-08-08 17:15:43 -07:00
2026-08-13 02:56:43 -07:00
2026-08-13 02:56:43 -07:00
2026-06-10 21:14:53 -07:00
2026-08-07 10:14:37 -07:00
2026-08-09 01:32:34 -07:00
2026-07-05 19:46:49 -07:00
2026-07-25 19:31:44 -07:00
2026-07-30 21:45:44 -07:00
2026-08-13 12:38:08 -07:00
2026-06-16 18:56:52 -07:00
2026-07-20 14:50:12 -07:00
2026-07-30 21:45:44 -07:00
2026-07-25 19:31:44 -07:00
2026-07-04 22:56:55 -07:00
2026-06-22 16:42:20 -07:00
2026-06-22 16:42:20 -07:00
2026-08-03 16:17:00 -07:00
2026-06-22 16:42:20 -07:00
2026-06-22 16:42:20 -07:00
2026-07-31 20:45:52 -07:00
2026-08-11 03:07:44 -07:00
2026-08-03 17:32:13 -07:00
2026-08-13 08:58:04 -07:00
2026-08-03 02:18:05 -07:00
2026-08-15 21:45:00 -07:00
2026-08-10 17:33:46 -07:00
2026-07-12 23:50:00 -07:00
2026-07-24 12:05:38 -07:00
2026-08-02 20:43:27 -07:00
2026-07-11 03:20:55 -07:00
2026-07-11 03:20:55 -07:00
2026-07-31 00:36:09 -07:00
2026-08-16 15:36:33 -07:00
2026-08-12 22:33:19 -07:00
2026-08-08 19:06:50 -07:00
2026-07-20 18:54:44 -07:00
2026-07-20 18:54:44 -07:00
2026-08-13 08:58:04 -07:00
2026-08-04 17:11:18 -07:00
2026-07-10 17:27:47 -07:00
2026-07-05 21:51:32 -07:00
2026-08-13 12:38:08 -07:00
2026-06-19 17:14:55 -07:00
2026-08-10 16:11:19 -07:00
2026-05-16 11:50:26 -07:00
2026-06-25 18:36:11 -07:00
2026-08-09 11:08:04 -07:00
2026-08-10 15:52:59 -07:00
2026-08-03 21:00:57 -07:00
2026-08-14 01:47:03 -07:00
2026-06-29 22:38:29 -07:00
2026-07-20 03:04:28 -04:00
2026-05-25 15:07:40 -07:00
2026-08-08 19:06:50 -07:00
2026-07-27 20:54:02 -07:00
2026-07-14 02:58:34 -07:00
2026-07-05 21:51:32 -07:00
2026-06-20 02:03:24 -07:00
2026-06-10 21:14:53 -07:00
2026-06-19 19:43:42 -07:00
2026-08-01 23:38:46 -07:00
2026-08-13 22:48:24 -07:00
2026-07-10 21:00:31 -07:00
2026-07-10 19:50:44 -07:00
2026-08-11 21:16:36 -07:00
2026-08-13 08:58:04 -07:00
2026-07-12 22:40:57 -07:00
2026-08-08 19:06:50 -07:00
2026-06-09 13:52:58 -07:00
2026-08-08 19:06:50 -07:00
2026-08-09 16:06:00 -07:00
2026-08-14 01:47:03 -07:00
2026-07-29 16:12:20 -07:00
2026-08-08 19:06:50 -07:00
2026-08-11 00:10:40 -07:00
2026-08-11 00:10:40 -07:00
2026-08-14 01:47:03 -07:00
2026-08-14 01:47:03 -07:00
2026-07-19 22:54:39 -04:00
2026-08-15 00:13:27 -07:00
2026-08-14 01:47:03 -07:00
2026-06-19 17:14:55 -07:00
2026-08-11 12:27:54 -07:00
2026-08-11 18:19:43 -07:00
2026-07-30 03:05:10 -07:00
2026-07-10 17:27:47 -07:00
2026-08-08 19:06:50 -07:00
2026-08-09 18:40:01 -07:00
2026-08-13 10:26:20 -07:00
2026-08-01 00:25:35 -07:00
2026-06-20 01:27:41 -07:00
2026-06-20 01:27:41 -07:00
2026-08-09 16:36:12 -07:00
2026-06-27 09:30:29 -07:00
2026-08-13 23:59:18 -07:00
2026-08-15 00:54:20 -07:00
2026-07-12 22:40:57 -07:00
2026-08-15 00:54:20 -07:00
2026-07-16 13:07:44 -07:00
2026-08-15 00:54:20 -07:00
2026-08-15 00:54:20 -07:00
2026-08-15 00:54:20 -07:00
2026-08-15 00:54:20 -07:00
2026-08-15 00:54:20 -07:00
2026-07-14 00:15:34 -07:00
2026-07-29 00:47:18 -07:00
2026-08-11 18:19:43 -07:00
2026-07-15 20:28:39 -07:00
2026-06-24 20:16:14 -07:00
2026-07-17 17:18:36 -07:00
2026-07-17 17:18:36 -07:00
2026-06-20 02:03:24 -07:00
2026-07-16 13:26:15 -07:00
2026-06-22 16:42:20 -07:00
2026-07-10 17:27:47 -07:00
2026-07-13 00:48:51 -07:00
2026-08-05 00:51:33 -07:00
2026-06-22 16:42:20 -07:00
2026-07-17 17:18:36 -07:00
2026-07-29 00:47:18 -07:00
2026-07-06 20:17:35 -07:00
2026-07-13 14:17:49 -07:00
2026-06-23 00:23:34 -07:00
2026-07-15 20:28:39 -07:00
2026-08-15 15:45:17 -07:00
2026-08-06 20:07:55 -07:00
2026-07-22 00:22:36 -07:00
2026-06-19 17:14:55 -07:00
2026-08-01 03:26:30 -07:00
2026-07-10 17:27:47 -07:00
2026-08-15 01:25:09 -07:00
2026-08-03 22:48:22 -07:00
2026-08-03 22:48:22 -07:00
2026-06-23 00:23:34 -07:00
2026-07-20 03:04:28 -04:00
2026-08-11 21:16:36 -07:00
2026-07-05 21:51:32 -07:00
2026-07-05 21:51:32 -07:00
2026-06-12 16:31:24 -07:00
2026-07-16 12:38:31 -07:00
2026-07-17 16:16:17 -07:00
2026-06-22 16:42:20 -07:00
2026-07-13 21:30:10 -07:00
2026-07-20 18:54:44 -07:00
2026-07-14 14:40:40 -07:00
2026-08-03 01:00:58 -07:00
2026-06-19 17:14:55 -07:00
2026-08-13 17:06:36 -07:00
2026-05-15 23:52:37 -07:00
2026-06-07 17:49:01 -07:00
2026-08-13 12:38:08 -07:00
2026-06-29 22:38:29 -07:00
2026-05-17 15:43:53 -04:00
2026-06-18 00:11:32 -07:00
2026-08-03 20:58:25 -07:00
2026-08-09 20:25:15 -07:00
2026-08-09 21:39:24 -07:00
2026-07-05 19:46:49 -07:00
2026-08-12 23:08:37 -07:00
2026-08-11 03:07:44 -07:00
2026-04-19 15:50:19 -07:00
2026-07-13 16:15:44 -07:00
2026-07-22 15:52:42 -07:00
2026-07-31 16:15:20 -07:00
2026-06-29 22:38:29 -07:00
2026-06-18 00:11:32 -07:00
2026-07-10 03:00:51 -07:00
2026-08-13 22:48:24 -07:00
2026-07-10 03:00:51 -07:00
2026-08-01 00:40:47 -07:00