From ca7119c4d219e5ecbeecd8fe427fb9e4d902a72f Mon Sep 17 00:00:00 2001 From: Merge Sim Date: Sat, 5 Sep 2026 20:06:43 -0700 Subject: [PATCH] fix(native-chat): narrow the retraction frame through its own type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Typecheck caught what the tests could not: `removed` is not on RuntimeMobileSessionTabsResult. The repo already names the shape — RuntimeMobileSessionTabsRemovedResult — so this reads it through a guard rather than the inline cast the mainstream path uses. --- .../snapshot-apply.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts b/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts index df5fa57a98f..03e9b12ae88 100644 --- a/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts +++ b/src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts @@ -1,4 +1,7 @@ -import type { RuntimeMobileSessionTabsResult } from '../../../../shared/runtime-types' +import type { + RuntimeMobileSessionTabsRemovedResult, + RuntimeMobileSessionTabsResult +} from '../../../../shared/runtime-types' import type { WorktreeRuntimeOwnerState } from '../../lib/worktree-runtime-owner' import { getExecutionHostIdForWorktree } from '../../lib/worktree-runtime-owner' import { @@ -26,6 +29,13 @@ import { hostSnapshotAffirmsWorktreeContents } from '../host-session-snapshot-au export const LOCAL_STRUCTURED_SESSION_OWNER = 'local-structured-session' +/** The host saying it no longer publishes this worktree at all, rather than publishing an empty one. */ +function isWorktreeRetraction( + snapshot: RuntimeMobileSessionTabsResult +): snapshot is RuntimeMobileSessionTabsRemovedResult { + return (snapshot as Partial).removed === true +} + export function applyStructuredSessionTabSnapshots( snapshots: readonly RuntimeMobileSessionTabsResult[], owner = LOCAL_STRUCTURED_SESSION_OWNER @@ -104,7 +114,7 @@ export function applyLocalStructuredSessionTabSnapshots< } ) next = patch === next ? next : ({ ...next, ...patch } as State) - if (snapshot.removed === true) { + if (isWorktreeRetraction(snapshot)) { // A retraction was applied above — the mirrored rows must go — but it is not a publication // to fence later frames against. Recording it would retire the renderer's own epoch, which // is one string for the whole process lifetime, and every republication afterwards would be