diff --git a/src/main/crash-reporting/crash-breadcrumb-store.test.ts b/src/main/crash-reporting/crash-breadcrumb-store.test.ts index fd7b1f074da..7690a01ff27 100644 --- a/src/main/crash-reporting/crash-breadcrumb-store.test.ts +++ b/src/main/crash-reporting/crash-breadcrumb-store.test.ts @@ -49,48 +49,6 @@ describe('crash breadcrumb store', () => { expect(snapshot.at(-1)?.data).toEqual({ index: 31 }) }) - it('retains the newest coalesced parking census across later activity', () => { - vi.useFakeTimers() - vi.setSystemTime(new Date('2026-08-15T12:00:00.000Z')) - recordCrashBreadcrumb('renderer_memory_highwater', { - rendererSurface: 'main', - thresholdPct: 80 - }) - recordCoalescedCrashBreadcrumb({ - name: 'terminal_parking_pass', - data: { managers: 49, panes: 60, sampledAtMs: Date.now() }, - coalesceKey: 'terminal_parking_pass', - minIntervalMs: 30_000 - }) - vi.advanceTimersByTime(1_000) - recordCoalescedCrashBreadcrumb({ - name: 'terminal_parking_pass', - data: { managers: 28, panes: 34, sampledAtMs: Date.now() }, - coalesceKey: 'terminal_parking_pass', - minIntervalMs: 30_000 - }) - for (let index = 0; index < 32; index += 1) { - recordCrashBreadcrumb(`later_event_${index}`, { index }) - } - - const snapshot = getCrashBreadcrumbSnapshot() - const parkingPasses = snapshot.filter( - (breadcrumb) => breadcrumb.name === 'terminal_parking_pass' - ) - - expect(snapshot).toHaveLength(30) - expect(parkingPasses).toHaveLength(1) - expect(snapshot.some((breadcrumb) => breadcrumb.name === 'renderer_memory_highwater')).toBe( - true - ) - expect(parkingPasses[0]?.data).toEqual({ - managers: 28, - panes: 34, - sampledAtMs: Date.now(), - suppressedSinceLast: 1 - }) - }) - it('caps retained high-water profiles', () => { for (let index = 0; index < 5; index += 1) { recordCrashBreadcrumb('renderer_memory_highwater', { @@ -104,41 +62,6 @@ describe('crash breadcrumb store', () => { ).toEqual(['surface-1', 'surface-2', 'surface-3', 'surface-4']) }) - it('keeps memory profiles and parking census from starving each other', () => { - recordCrashBreadcrumb('terminal_parking_pass', { managers: 1, panes: 1 }) - for (let index = 0; index < 12; index += 1) { - recordCrashBreadcrumb('renderer_memory_highwater', { - rendererSurface: `surface-${index}`, - thresholdPct: 80 - }) - } - - expect( - getCrashBreadcrumbSnapshot().filter( - (breadcrumb) => breadcrumb.name === 'terminal_parking_pass' - ) - ).toHaveLength(1) - - for (let index = 0; index < 12; index += 1) { - recordCrashBreadcrumb('terminal_parking_pass', { managers: index, panes: index + 1 }) - } - - const snapshot = getCrashBreadcrumbSnapshot() - const memoryProfiles = snapshot.filter( - (breadcrumb) => breadcrumb.name === 'renderer_memory_highwater' - ) - - expect(memoryProfiles.map((breadcrumb) => breadcrumb.data?.rendererSurface)).toEqual([ - 'surface-8', - 'surface-9', - 'surface-10', - 'surface-11' - ]) - expect(snapshot.filter((breadcrumb) => breadcrumb.name === 'terminal_parking_pass')).toEqual([ - expect.objectContaining({ data: { managers: 11, panes: 12 } }) - ]) - }) - it('redacts sensitive breadcrumb fields before they can be snapshotted', () => { recordCrashBreadcrumb('workspace_opened', { path: '/Users/alice/project', diff --git a/src/main/crash-reporting/crash-breadcrumb-store.ts b/src/main/crash-reporting/crash-breadcrumb-store.ts index ed66864718d..e5f96e8f05e 100644 --- a/src/main/crash-reporting/crash-breadcrumb-store.ts +++ b/src/main/crash-reporting/crash-breadcrumb-store.ts @@ -6,10 +6,8 @@ import { } from '../../shared/crash-reporting' const MAX_BREADCRUMBS = 30 -// Why: preserve four memory highwaters and one named singleton within the 30-entry snapshot. -const MAX_RETAINED_BREADCRUMBS = 5 -const MAX_RETAINED_MEMORY_BREADCRUMBS = 4 -const RETAINED_SINGLETON_BREADCRUMB_NAMES = new Set(['terminal_parking_pass']) +// Why: retain two thresholds for each renderer surface without growing the ring. +const MAX_RETAINED_BREADCRUMBS = 4 // Why: coalesceKey embeds an open-string agentType (length-trimmed only, never // enum-checked), so the key space is unbounded over a long multi-agent/SSH session. // Bound the coalesce map the same way ProcessGoneDedupe bounds its key map. @@ -39,9 +37,6 @@ let retainedBreadcrumbs = new Map() let coalescedBreadcrumbs = new Map() function retainedBreadcrumbKey(breadcrumb: CrashReportBreadcrumb): string | null { - if (RETAINED_SINGLETON_BREADCRUMB_NAMES.has(breadcrumb.name)) { - return breadcrumb.name - } if (breadcrumb.name !== 'renderer_memory_highwater') { return null } @@ -70,15 +65,6 @@ export function recordCrashBreadcrumb( if (retainedKey) { retainedBreadcrumbs.delete(retainedKey) retainedBreadcrumbs.set(retainedKey, breadcrumb) - const memoryKeys = [...retainedBreadcrumbs.entries()] - .filter(([, retained]) => retained.name === 'renderer_memory_highwater') - .map(([key]) => key) - while (memoryKeys.length > MAX_RETAINED_MEMORY_BREADCRUMBS) { - const oldestMemoryKey = memoryKeys.shift() - if (oldestMemoryKey) { - retainedBreadcrumbs.delete(oldestMemoryKey) - } - } while (retainedBreadcrumbs.size > MAX_RETAINED_BREADCRUMBS) { const oldestKey = retainedBreadcrumbs.keys().next() if (oldestKey.done) {