diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-restore-without-import.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-restore-without-import.test.ts index b19f2a49d77..0cf019e7239 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-restore-without-import.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-restore-without-import.test.ts @@ -196,7 +196,6 @@ async function writeLegacyChat( await mkdir(dirname(path), { recursive: true }) const db = new Database(path) try { - db.pragma('journal_mode = WAL') db.exec(` CREATE TABLE journal_rows (session_id TEXT NOT NULL, epoch TEXT NOT NULL, seq INTEGER NOT NULL, ts INTEGER NOT NULL, row_json TEXT NOT NULL, PRIMARY KEY (session_id, epoch, seq)); diff --git a/src/main/native-chat/transcript-watch-test-subscriptions.ts b/src/main/native-chat/transcript-watch-test-subscriptions.ts deleted file mode 100644 index 313c5f32b42..00000000000 --- a/src/main/native-chat/transcript-watch-test-subscriptions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { subscribeNativeChatTranscript } from './transcript-watch' -import type { NativeChatTranscriptSubscription } from './transcript-watch-contract' - -const subscriptions = new Set() - -export async function subscribeNativeChatTranscriptForTest( - ...args: Parameters -): Promise { - const subscription = await subscribeNativeChatTranscript(...args) - subscriptions.add(subscription) - return subscription -} - -export function closeNativeChatTestSubscriptions(): void { - for (const subscription of subscriptions) { - subscription.unsubscribe() - } - subscriptions.clear() -} diff --git a/src/main/native-chat/transcript-watch.test.ts b/src/main/native-chat/transcript-watch.test.ts index cff7de1be71..21189d8127b 100644 --- a/src/main/native-chat/transcript-watch.test.ts +++ b/src/main/native-chat/transcript-watch.test.ts @@ -3,20 +3,31 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' import type { NativeChatMessage, NativeChatTurnLifecycle } from '../../shared/native-chat-types' -import { getActiveNativeChatWatcherCount, readNativeChatTranscriptTail } from './transcript-watch' +import type { NativeChatTranscriptSubscription } from './transcript-watch-contract' import { - closeNativeChatTestSubscriptions, - subscribeNativeChatTranscriptForTest as subscribeNativeChatTranscript -} from './transcript-watch-test-subscriptions' + getActiveNativeChatWatcherCount, + readNativeChatTranscriptTail, + subscribeNativeChatTranscript as subscribeTranscript +} from './transcript-watch' +const subscriptions = new Set() let tempRoots: string[] = [] +async function subscribeNativeChatTranscript(...args: Parameters) { + const subscription = await subscribeTranscript(...args) + subscriptions.add(subscription) + return subscription +} + beforeEach(() => { tempRoots = [] }) afterEach(async () => { - closeNativeChatTestSubscriptions() + for (const subscription of subscriptions) { + subscription.unsubscribe() + } + subscriptions.clear() await Promise.all(tempRoots.map((root) => rm(root, { recursive: true, force: true }))) tempRoots = [] }) diff --git a/src/renderer/src/components/sidebar/WorktreeList.group-headers.test.ts b/src/renderer/src/components/sidebar/WorktreeList.group-headers.test.ts index 092faad697a..2be1d1654c7 100644 --- a/src/renderer/src/components/sidebar/WorktreeList.group-headers.test.ts +++ b/src/renderer/src/components/sidebar/WorktreeList.group-headers.test.ts @@ -1,7 +1,6 @@ import { beforeAll, describe, expect, it, vi } from 'vitest' import type { ProjectGroup } from '../../../../shared/project-group-types' import type { Repo } from '../../../../shared/repo-types' -import { getPinnedWorktreeRevealCollapsedGroupKeys } from './worktree-list/navigation/reveal-ancestors' import { createAppStoreModuleMock, createDropdownMenuModuleMock, @@ -20,8 +19,7 @@ import { import { makeFolderWorkspacePathStatusMockState, makeFolderWorkspacePathStatusState, - makeRepo, - makeWorktree + makeRepo } from './worktree-list-lineage-card-test-fixtures' import { setLineageFixtureState } from './worktree-list-lineage-store-state' import { setPinnedFixtureState } from './worktree-list-pinned-store-state' @@ -152,42 +150,6 @@ describe('WorktreeList lineage child card renderer', () => { expect(markup).not.toContain('data-repo-header-collapse-affordance=""') }) - it('uncollapses pinned reveal for a descendant that only lives under a pinned parent', () => { - const child = makeWorktree({ - id: 'child-of-pinned', - instanceId: 'child-of-pinned-instance', - displayName: 'Child of pinned', - branch: 'child', - sortOrder: 2 - }) - - expect( - getPinnedWorktreeRevealCollapsedGroupKeys({ - worktree: child, - collapsedGroups: new Set(['pinned', 'all']), - inPinnedSection: true - }) - ).toEqual(['pinned']) - }) - - it('uncollapses pinned reveal through the pinned section after host expansion', () => { - const worktree = makeWorktree({ - id: 'pinned-ssh', - instanceId: 'pinned-ssh-instance', - displayName: 'Pinned SSH workspace', - branch: 'pinned-ssh', - sortOrder: 1 - }) - worktree.isPinned = true - - expect( - getPinnedWorktreeRevealCollapsedGroupKeys({ - worktree, - collapsedGroups: new Set(['host:ssh:builder-1', 'pinned', 'done']) - }) - ).toEqual(['pinned']) - }) - it('renders a collapse chevron on status group headers with worktrees', async () => { setLineageFixtureState('workspace-status') const markup = await renderWorktreeListMarkup() diff --git a/src/renderer/src/components/sidebar/agent-send-picker-collapse.test.tsx b/src/renderer/src/components/sidebar/agent-send-picker-collapse.test.tsx index d96ead14e19..8567c66f9cb 100644 --- a/src/renderer/src/components/sidebar/agent-send-picker-collapse.test.tsx +++ b/src/renderer/src/components/sidebar/agent-send-picker-collapse.test.tsx @@ -178,7 +178,7 @@ for (const hostId of ['local', 'ssh:builder', 'runtime:builder'] as const) { }) } -it('opens a filtered parent chain and owning lane, then restores the saved set on close', () => { +it.each([true, false])('reveals ancestors with pinned parent visible=%s', (visible) => { const { local, remote, repoMap } = setup('ssh:builder') const root = { ...remote, instanceId: 'root-instance', isPinned: true } const parent = { ...remote, id: 'parent', instanceId: 'parent-instance', isPinned: false } @@ -213,7 +213,7 @@ it('opens a filtered parent chain and owning lane, then restores the saved set o groupBy: 'none', pinnedDisplayPolicy: 'single-location', worktrees, - visibleWorktrees: [local, child], + visibleWorktrees: visible ? worktrees : [local, child], repoMap, worktreeMap: new Map(worktrees.map((worktree) => [worktree.id, worktree])), worktreeLineageById: { @@ -230,12 +230,14 @@ it('opens a filtered parent chain and owning lane, then restores the saved set o }), { initialProps } ) - expect([...result.current]).toEqual([ - 'all', - 'pinned:host:ssh:builder', - 'host:local', - 'lineage:local|parent' - ]) + expect([...result.current].sort()).toEqual( + [ + visible ? 'all:host:ssh:builder' : 'pinned:host:ssh:builder', + 'all', + 'host:local', + 'lineage:local|parent' + ].sort() + ) expect(collapsedGroups.size).toBe(8) rerender({ targetId: null }) expect(result.current).toBe(collapsedGroups) diff --git a/src/renderer/src/components/sidebar/worktree-list/navigation/reveal-ancestors.ts b/src/renderer/src/components/sidebar/worktree-list/navigation/reveal-ancestors.ts index 2be2aa92bd2..563387d0b93 100644 --- a/src/renderer/src/components/sidebar/worktree-list/navigation/reveal-ancestors.ts +++ b/src/renderer/src/components/sidebar/worktree-list/navigation/reveal-ancestors.ts @@ -1,7 +1,6 @@ import type { ProjectGroup } from '../../../../../../shared/project-group-types' import type { Repo } from '../../../../../../shared/repo-types' -import type { Worktree } from '../../../../../../shared/worktree/types' -import { PINNED_GROUP_KEY, getProjectGroupHeaderKey } from '../grouping/group-keys' +import { getProjectGroupHeaderKey } from '../grouping/group-keys' import type { ProjectGroupingModel } from '../grouping/project-grouping' function getProjectIdFromHeaderRowKey(rowKey: string): string | null { @@ -89,25 +88,3 @@ export function getSidebarRowRevealAncestorKeys(args: { } return [...keys] } - -export function getPinnedWorktreeRevealCollapsedGroupKeys({ - worktree, - collapsedGroups, - groupKey = PINNED_GROUP_KEY, - inPinnedSection = worktree.isPinned -}: { - worktree: Worktree - collapsedGroups: ReadonlySet - groupKey?: string - inPinnedSection?: boolean -}): string[] { - if (!inPinnedSection) { - return [] - } - const keys: string[] = [] - // Why: the reveal effect already opens this host; re-returning it would toggle it back closed. - if (collapsedGroups.has(groupKey)) { - keys.push(groupKey) - } - return keys -} diff --git a/src/renderer/src/components/sidebar/worktree-list/navigation/worktree-reveal-group-keys.ts b/src/renderer/src/components/sidebar/worktree-list/navigation/worktree-reveal-group-keys.ts index 0cfb7805900..3fe1a15b004 100644 --- a/src/renderer/src/components/sidebar/worktree-list/navigation/worktree-reveal-group-keys.ts +++ b/src/renderer/src/components/sidebar/worktree-list/navigation/worktree-reveal-group-keys.ts @@ -17,7 +17,6 @@ import { getWorktreeLineageGroupKey, PINNED_GROUP_KEY } from '../grouping/group- import type { ProjectGroupingModel } from '../grouping/project-grouping' import type { PinnedWorktreeDisplayPolicy, WorktreeGroupBy } from '../grouping/row-types' import { getGroupKeysForWorktree } from '../grouping/worktree-group-keys' -import { getPinnedWorktreeRevealCollapsedGroupKeys } from './reveal-ancestors' export function getWorktreeRevealCollapsedGroupKeys(args: { worktree: Worktree @@ -65,14 +64,7 @@ export function getWorktreeRevealCollapsedGroupKeys(args: { hostLineage.worktreeMap ) ) { - keys.push( - ...getPinnedWorktreeRevealCollapsedGroupKeys({ - worktree: args.worktree, - groupKey: sectionKey(PINNED_GROUP_KEY), - collapsedGroups: args.collapsedGroups, - inPinnedSection: true - }) - ) + keys.push(sectionKey(PINNED_GROUP_KEY)) } else { keys.push( ...getGroupKeysForWorktree(