From 3962c1b4d1db14bf1fe17596051daf2c9e4bdbba Mon Sep 17 00:00:00 2001 From: Neil Date: Thu, 10 Sep 2026 17:25:28 -0700 Subject: [PATCH] docs(session): record why a re-key clobbering an existing target stays unfixed Not a missing guard -- an unresolvable one. Keeping the target is correct when it holds a real closed-last-terminal tombstone; keeping the source is correct when the target row is a stub; nothing records which is newer. The recency map is the only one that can settle it, because Math.max needs no such ordering. --- .../tracking-repos/worktree-identity-migration.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/persistence/tracking-repos/worktree-identity-migration.ts b/src/main/persistence/tracking-repos/worktree-identity-migration.ts index 049cdf7b45b..f57a48f5791 100644 --- a/src/main/persistence/tracking-repos/worktree-identity-migration.ts +++ b/src/main/persistence/tracking-repos/worktree-identity-migration.ts @@ -132,6 +132,14 @@ export function migrateWorktreeIdentity( return false } let sessionChanged = false + /** Known and deliberately unresolved: when the target key ALREADY exists, the source wins and + * the target's row is lost. `lastVisitedAtByWorktreeId` below is the one map that settles it + * (`Math.max`), and its comment names the case — a partial migration leaves both identities + * behind. There is no safe blanket rule here: "keep the target" is right when the target holds + * a real closed-last-terminal tombstone (`tabsByWorktree[target] === []` is user intent, see + * runtime/workspace-session-worktree-id.ts), and "keep the source" is right when the target row + * is a stub, and nothing records which is newer. Reachable only by a repeated or partial + * migration: on a normal rename this store holds rows under the old id alone. */ const moveSessionKey = ( record: Record | undefined, mapValue: (value: T) => T = (value) => value