mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +00:00
Prevent deleted workspace browser snapshot resurrection
This commit is contained in:
@@ -52,6 +52,33 @@ describe('buildMobileSessionTabSnapshots', () => {
|
||||
expect(restored.snapshotVersion).toBeGreaterThan(initial.snapshotVersion)
|
||||
})
|
||||
|
||||
it('publishes a new instance identity when unchanged content is recreated', () => {
|
||||
const worktree = {
|
||||
id: 'wt-1',
|
||||
instanceId: 'old-instance',
|
||||
repoId: 'repo-1'
|
||||
}
|
||||
const base = makeState({
|
||||
worktreesByRepo: { 'repo-1': [worktree] } as unknown as AppState['worktreesByRepo'],
|
||||
tabsByWorktree: {
|
||||
'wt-1': [{ id: 'term-1', title: 'Terminal 1' }]
|
||||
} as unknown as AppState['tabsByWorktree']
|
||||
})
|
||||
const initial = buildMobileSessionTabSnapshots(base)[0]!
|
||||
const recreated = {
|
||||
...base,
|
||||
worktreesByRepo: {
|
||||
'repo-1': [{ ...worktree, instanceId: 'new-instance' }]
|
||||
} as unknown as AppState['worktreesByRepo']
|
||||
}
|
||||
|
||||
const next = buildMobileSessionTabSnapshots(recreated)[0]!
|
||||
|
||||
expect(initial.worktreeInstanceId).toBe('old-instance')
|
||||
expect(next.worktreeInstanceId).toBe('new-instance')
|
||||
expect(next.snapshotVersion).toBeGreaterThan(initial.snapshotVersion)
|
||||
})
|
||||
|
||||
it('publishes browser and editor color + pin state from unified tabs', () => {
|
||||
const fileId = '/repo/README.md'
|
||||
const state = makeState({
|
||||
|
||||
@@ -157,6 +157,7 @@ export function canReuseMobileSessionSnapshot(
|
||||
): boolean {
|
||||
return (
|
||||
previous.worktreeId === next.worktreeId &&
|
||||
previous.worktreeInstanceId === next.worktreeInstanceId &&
|
||||
previous.terminalTabs === next.terminalTabs &&
|
||||
previous.browserWorkspaces === next.browserWorkspaces &&
|
||||
previous.unifiedTabs === next.unifiedTabs &&
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { AppState } from '@/store/types'
|
||||
import { parsePaneKey, makePaneKey } from '../../../../shared/stable-pane-id'
|
||||
import { nativeChatLaunchAgentForLeaf } from '../../components/native-chat/native-chat-leaf-routing'
|
||||
import { getIndexedWorktreesById } from '@/store/worktree-repo-index'
|
||||
import {
|
||||
EMPTY_NARROWED_BY_KEY,
|
||||
EMPTY_WORKTREE_BROWSER_WORKSPACES,
|
||||
@@ -146,6 +147,9 @@ export function buildMobileSessionWorktreeInputs(
|
||||
const activeTabId = state.activeTabId
|
||||
return {
|
||||
worktreeId,
|
||||
worktreeInstanceId: getIndexedWorktreesById(state.worktreesByRepo, worktreeId).find(
|
||||
(worktree) => worktree.instanceId !== undefined
|
||||
)?.instanceId,
|
||||
terminalTabs,
|
||||
browserWorkspaces,
|
||||
unifiedTabs: state.unifiedTabsByWorktree[worktreeId] ?? EMPTY_WORKTREE_UNIFIED_TABS,
|
||||
|
||||
@@ -208,16 +208,29 @@ export function buildMobileSessionTabSnapshots(
|
||||
}
|
||||
const candidateVersion = ++graphState.mobileSessionSnapshotVersion
|
||||
if (cached && jsonContentEquals(cached.content, content)) {
|
||||
const snapshot =
|
||||
cached.snapshot.worktreeInstanceId === inputs.worktreeInstanceId
|
||||
? cached.snapshot
|
||||
: {
|
||||
worktree: worktreeId,
|
||||
...(inputs.worktreeInstanceId
|
||||
? { worktreeInstanceId: inputs.worktreeInstanceId }
|
||||
: {}),
|
||||
publicationEpoch: mobilePublicationEpoch,
|
||||
snapshotVersion: candidateVersion,
|
||||
...content
|
||||
}
|
||||
graphState.mobileSessionSnapshotCacheByWorktree.set(worktreeId, {
|
||||
inputs,
|
||||
content,
|
||||
snapshot: cached.snapshot
|
||||
snapshot
|
||||
})
|
||||
snapshots.push(cached.snapshot)
|
||||
snapshots.push(snapshot)
|
||||
continue
|
||||
}
|
||||
const snapshot: RuntimeMobileSessionTabsSnapshot = {
|
||||
worktree: worktreeId,
|
||||
...(inputs.worktreeInstanceId ? { worktreeInstanceId: inputs.worktreeInstanceId } : {}),
|
||||
publicationEpoch: mobilePublicationEpoch,
|
||||
snapshotVersion: candidateVersion,
|
||||
...content
|
||||
|
||||
@@ -107,6 +107,7 @@ export type MountedTerminalSurfaceCapture = {
|
||||
*/
|
||||
export type MobileSessionWorktreeInputs = {
|
||||
worktreeId: string
|
||||
worktreeInstanceId: string | undefined
|
||||
terminalTabs: AppState['tabsByWorktree'][string]
|
||||
browserWorkspaces: AppState['browserTabsByWorktree'][string]
|
||||
unifiedTabs: AppState['unifiedTabsByWorktree'][string]
|
||||
|
||||
@@ -215,6 +215,8 @@ export const UNPUBLISHED_WORKTREE_PUBLICATION_EPOCH = 'none'
|
||||
|
||||
export type RuntimeMobileSessionTabsSnapshot = {
|
||||
worktree: string
|
||||
/** Immutable catalog identity used to fence snapshots across path reuse. */
|
||||
worktreeInstanceId?: string
|
||||
publicationEpoch: string
|
||||
snapshotVersion: number
|
||||
activeGroupId: string | null
|
||||
|
||||
Reference in New Issue
Block a user