perf: overhaul session loading, caching, and runtime isolation (#2360)

Improve OpenChamber responsiveness under large session workloads while fixing
cache, synchronization, and persistence correctness across runtimes, projects,
directories, and worktrees.

- prioritize selected and visible sessions during bootstrap and defer
  non-critical enrichment work
- reduce redundant message loading, event processing, store publication, and
  hidden sidebar work
- prevent stale session and message requests from overwriting newer
  authoritative state
- preserve existing data when authoritative fetches fail instead of treating
  failures as successful empty responses
- scope session materialization, messages, drafts, queues, todos, pins,
  permissions, folders, tabs, Git state, and pull request data by runtime and
  directory identity
- harden runtime switching, reconnect, cleanup, mutation reconciliation, and
  persisted-state ordering
- preserve live subagent Task linkage when metadata arrives after an older
  message request or while streaming parts are suspended
- coalesce overlapping tail refreshes without losing newer refresh demand
- improve cold-session loading by moving deferrable work out of the critical
  bootstrap path
- isolate URL authentication, mobile credentials, native secrets, and other
  runtime-owned state across endpoint changes
- bound long-lived caches and remove avoidable allocations from event and
  rendering hot paths
- limit virtualization to archive collections where it improves rendering
  without disrupting active sidebar layout
- stabilize session folders, pin ordering, expanded state, and persisted
  sidebar behavior
- open skill files through the same secure editor and outside-workspace grant
  flow used by file navigation, including worktree sessions
- expand regression coverage for stale completions, runtime collisions,
  reconnect behavior, persistence races, authoritative empty results, and
  subagent refresh ordering
- document the updated synchronization, cache ownership, performance, and
  runtime-isolation invariants
This commit is contained in:
Bohdan Triapitsyn
2026-07-21 20:52:20 +03:00
committed by GitHub
parent 485efc7117
commit 85400459e9
197 changed files with 10835 additions and 3400 deletions
+65 -7
View File
@@ -1,6 +1,7 @@
import { beforeEach, describe, expect, test } from 'bun:test';
import type { GitStatus } from '@/lib/api/types';
import { useGitStore } from './useGitStore';
import { getRuntimeKey } from '@/lib/runtime-switch';
type Deferred<T> = {
promise: Promise<T>;
@@ -39,7 +40,7 @@ const createDirectoryState = (status: GitStatus): DirectoryGitState => ({
identity: null,
diffCache: new Map(),
indexRevision: 0,
lastRepoCheckAt: 0,
lastRepoCheckAt: Date.now(),
lastStatusFetch: 0,
lastStatusChange: 0,
lastLogFetch: 0,
@@ -70,13 +71,11 @@ const createGitApi = (getGitStatus: GitAPI['getGitStatus']): GitAPI => ({
describe('useGitStore', () => {
beforeEach(() => {
useGitStore.setState({
directories: new Map(),
activeDirectory: null,
});
useGitStore.getState().resetForRuntimeSwitch(getRuntimeKey());
});
test('does not reuse an in-flight light status request for full status', async () => {
setDirectoryStatus(createStatus());
const requests: Deferred<GitStatus>[] = [];
const statusCalls: Array<{ directory: string; options?: { mode?: 'light' } }> = [];
const git = createGitApi((directory, options) => {
@@ -95,12 +94,18 @@ describe('useGitStore', () => {
{ directory: '/repo', options: undefined },
]);
requests[0].resolve(createStatus());
requests[1].resolve(createStatus({ 'src/index.ts': { insertions: 1, deletions: 0 } }));
await Promise.all([lightPromise, fullPromise]);
await fullPromise;
requests[0].resolve(createStatus());
await lightPromise;
expect(useGitStore.getState().getDirectoryState('/repo')?.status?.diffStats).toEqual({
'src/index.ts': { insertions: 1, deletions: 0 },
});
});
test('reuses an in-flight full status request for light status', async () => {
setDirectoryStatus(createStatus());
const requests: Deferred<GitStatus>[] = [];
const statusCalls: Array<{ directory: string; options?: { mode?: 'light' } }> = [];
const git = createGitApi((directory, options) => {
@@ -121,6 +126,59 @@ describe('useGitStore', () => {
expect(lightResult).toBe(fullResult);
});
test('does not let an older status fetch undo an optimistic mutation', async () => {
const initial = createStatus(undefined, [{ path: 'src/index.ts', index: ' ', working_dir: 'M' }]);
setDirectoryStatus(initial);
const request = createDeferred<GitStatus>();
const git = createGitApi(() => request.promise);
const loading = useGitStore.getState().fetchStatus('/repo', git, { silent: true });
useGitStore.getState().moveStatusPathsOptimistically('/repo', ['src/index.ts'], 'stage');
request.resolve(initial);
await loading;
expect(useGitStore.getState().getDirectoryState('/repo')?.status?.files).toEqual([
{ path: 'src/index.ts', index: 'M', working_dir: ' ' },
]);
});
test('rejects an old runtime completion after reset', async () => {
setDirectoryStatus(createStatus());
const request = createDeferred<GitStatus>();
const git = createGitApi(() => request.promise);
const loading = useGitStore.getState().fetchStatus('/repo', git, { silent: true });
useGitStore.getState().resetForRuntimeSwitch('runtime-b');
request.resolve(createStatus(undefined, [{ path: 'stale.ts', index: 'M', working_dir: ' ' }]));
await loading;
expect(useGitStore.getState().runtimeKey).toBe('runtime-b');
expect(useGitStore.getState().getDirectoryState('/repo')?.status ?? null).toBe(null);
});
test('rejects direct diff commits captured for another runtime', () => {
useGitStore.getState().setDiff('/repo', 'stale.ts', { original: 'a', modified: 'b' }, 'runtime-a');
expect(useGitStore.getState().getDiff('/repo', 'stale.ts')).toBe(null);
});
test('keeps the newest branch request when completions are reversed', async () => {
const requests = [createDeferred<Awaited<ReturnType<GitAPI['getGitBranches']>>>(), createDeferred<Awaited<ReturnType<GitAPI['getGitBranches']>>>()];
let index = 0;
const git = {
...createGitApi(async () => createStatus()),
getGitBranches: () => requests[index++].promise,
};
const first = useGitStore.getState().fetchBranches('/repo', git);
const second = useGitStore.getState().fetchBranches('/repo', git);
requests[1].resolve({ all: ['new'], current: 'new', branches: {} });
await second;
requests[0].resolve({ all: ['old'], current: 'old', branches: {} });
await first;
expect(useGitStore.getState().getDirectoryState('/repo')?.branches?.current).toBe('new');
});
test('optimistically stages modified files and preserves untouched file references', () => {
const target = { path: 'src/index.ts', index: ' ', working_dir: 'M' };
const untouched = { path: 'README.md', index: ' ', working_dir: 'M' };