perf(sidebar): index session ownership and narrow live subscriptions

Replace repeated project-by-session directory matching across sidebar hooks with a shared ownership index that resolves each unique directory once and exposes direct project and folder-scope buckets.

Gate destructive folder reconciliation on authoritative session data and topology readiness, preserve last-known worktrees after discovery failures, and retain nested-project, VS Code, active/archive dedupe, and Windows drive-root semantics.

Narrow cross-directory subscriptions to session and status slices so streaming deltas no longer trigger global aggregation. Reuse a cached session ID index for permission lineage checks instead of rebuilding it on every session switch.

On the reported 15-project, 67-worktree, 14,561-session shape, ownership indexing averages 3.81 ms versus roughly 450 ms for the cache-only hotfix.

Validation: 28 targeted tests, UI type-check, UI lint, and dead-code analysis.
This commit is contained in:
Bohdan Triapitsyn
2026-07-13 23:18:12 +03:00
parent 799904f0f4
commit b36afbf5ee
19 changed files with 619 additions and 511 deletions
@@ -1,7 +1,5 @@
import { describe, expect, test } from 'bun:test';
import type { Session } from '@opencode-ai/sdk/v2';
import { isPathWithinProject, isSessionRelatedToProject } from './utils';
import { isPathWithinProject } from './utils';
describe('isPathWithinProject', () => {
test('matches child directories for root projects', () => {
@@ -28,86 +26,3 @@ describe('isPathWithinProject', () => {
expect(isPathWithinProject('/workspace/app/sub/dir', '/workspace/app')).toBe(true);
});
});
describe('isSessionRelatedToProject', () => {
test('prefers the most specific project root for archived session directories', () => {
const session = {
id: 'ses_parent_child',
directory: '/home/user/proj/foo/src',
} as unknown as Session;
const knownProjectDirectories = new Set(['/home/user', '/home/user/proj/foo']);
expect(
isSessionRelatedToProject(session, '/home/user', new Set(['/home/user']), knownProjectDirectories),
).toBe(false);
expect(
isSessionRelatedToProject(
session,
'/home/user/proj/foo',
new Set(['/home/user/proj/foo']),
knownProjectDirectories,
),
).toBe(true);
});
test('prefers the most specific project worktree when session directory is missing', () => {
const session = {
id: 'ses_project_worktree',
project: {
worktree: '/home/user/proj/foo',
},
} as unknown as Session;
const knownProjectDirectories = new Set(['/home/user', '/home/user/proj/foo']);
expect(
isSessionRelatedToProject(session, '/home/user', new Set(['/home/user']), knownProjectDirectories),
).toBe(false);
expect(
isSessionRelatedToProject(
session,
'/home/user/proj/foo',
new Set(['/home/user/proj/foo']),
knownProjectDirectories,
),
).toBe(true);
});
test('prefers explicit session directory over broader project worktree metadata', () => {
const session = {
id: 'ses_directory_beats_worktree',
directory: '/home/user/proj/foo/src',
project: {
worktree: '/home/user',
},
} as unknown as Session;
const knownProjectDirectories = new Set(['/home/user', '/home/user/proj/foo']);
expect(
isSessionRelatedToProject(session, '/home/user', new Set(['/home/user']), knownProjectDirectories),
).toBe(false);
expect(
isSessionRelatedToProject(
session,
'/home/user/proj/foo',
new Set(['/home/user/proj/foo']),
knownProjectDirectories,
),
).toBe(true);
});
test('keeps descendant sessions on the broad project when no child project matches', () => {
const session = {
id: 'ses_home_misc',
directory: '/home/user/misc/sandbox',
} as unknown as Session;
const knownProjectDirectories = new Set(['/home/user', '/home/user/proj/foo']);
expect(
isSessionRelatedToProject(session, '/home/user', new Set(['/home/user']), knownProjectDirectories),
).toBe(true);
});
});