diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index 8d978c4a5e4..1bb3fb0f88f 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -701,12 +701,12 @@ "oracle": "Assert unchanged JSON through final flush and maintenance, failure propagation before quit, missing-database refusal after marker publication, archived SQLite and latest committed JSON from inactive-profile conversion, unchanged active database/index/HTTP marker, and zero feed/check calls for incompatible pinned/local builds.", "commands": [ "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/persistence/profile-state src/main/persistence/loading-store src/main/orca-profiles src/main/startup/profile-state-recovery-preflight.test.ts src/main/startup/main-window-core-services.test.ts src/main/ipc/orca-profiles-switch-persistence.test.ts src/main/updater-sqlite-profile-downgrade.test.ts src/main/updater.build-channel-selection.test.ts src/cli/handlers/profile-state.test.ts src/cli/handlers/profile-state-recovery-admission.test.ts src/cli/specs/profile-state.test.ts src/cli/runtime/profile-state-recovery-launch.test.ts src/shared/profile-state-recovery-command.test.ts src/shared/profile-state-build-compatibility.test.ts", - "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/persistence/loading-store/profile-state-update-quit.test.ts src/main/persistence/loading-store/profile-state-maintenance-compatibility.test.ts src/main/persistence/profile-state/profile-state-authority-marker.test.ts src/main/persistence/profile-state/profile-state-selected-profile-recovery.test.ts src/main/persistence/profile-state/profile-state-current-sqlite-command.test.ts src/main/updater-sqlite-profile-downgrade.test.ts src/main/persistence/loading-store/profile-state-checkpoints.test.ts src/main/startup/main-window-core-services.test.ts", + "ORCA_BACKGROUND_LAUNCH=1 pnpm test src/main/persistence/loading-store/profile-state-update-quit.test.ts src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts src/main/persistence/profile-state/profile-state-authority-marker.test.ts src/main/persistence/profile-state/profile-state-selected-profile-recovery.test.ts src/main/persistence/profile-state/profile-state-current-sqlite-command.test.ts src/main/updater-sqlite-profile-downgrade.test.ts src/main/persistence/loading-store/profile-state-checkpoints.test.ts src/main/startup/main-window-core-services.test.ts", "ORCA_BACKGROUND_LAUNCH=1 pnpm exec playwright test tests/e2e/profile-state-terminal-restart-persistence.spec.ts tests/e2e/orchestration-legacy-worker-restart-recovery.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1" ], "testFiles": [ "src/main/persistence/loading-store/profile-state-update-quit.test.ts", - "src/main/persistence/loading-store/profile-state-maintenance-compatibility.test.ts", + "src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts", "src/main/persistence/profile-state/profile-state-authority-marker.test.ts", "src/main/persistence/profile-state/profile-state-selected-profile-recovery.test.ts", "src/main/persistence/profile-state/profile-state-current-sqlite-command.test.ts", @@ -716,6 +716,13 @@ "tests/e2e/profile-state-terminal-restart-persistence.spec.ts" ], "assertionRefs": [ + { + "file": "src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts", + "assertions": [ + "checkpoints SQL without publishing JSON or rewriting explicit exports", + "preserves the existing SQL state and publishes no JSON during a recovery pause" + ] + }, { "file": "src/main/persistence/profile-state/profile-state-selected-profile-recovery.test.ts", "assertions": [ diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index e272fa27418..1b3023f720b 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -3796,7 +3796,6 @@ "src/main/persistence/loading-store/profile-state-checkpoints.test.ts": 1815, "src/main/persistence/loading-store/profile-state-direct-flush.test.ts": 1619, "src/main/persistence/loading-store/profile-state-import-lifetime.test.ts": 1535, - "src/main/persistence/loading-store/profile-state-maintenance-compatibility.test.ts": 1904, "src/main/persistence/loading-store/profile-state-maintenance-final-failure.test.ts": 1809, "src/main/persistence/loading-store/profile-state-maintenance-recovery.test.ts": 2380, "src/main/persistence/loading-store/profile-state-maintenance.test.ts": 2759, diff --git a/src/main/persistence/loading-store/profile-state-maintenance-compatibility.test.ts b/src/main/persistence/loading-store/profile-state-maintenance-compatibility.test.ts deleted file mode 100644 index 42e6b6150ae..00000000000 --- a/src/main/persistence/loading-store/profile-state-maintenance-compatibility.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { existsSync, readFileSync } from 'node:fs' -import { describe, expect, it, vi } from 'vitest' -import { createWorkerMaintenanceFixture } from './profile-state-maintenance-fixture' -import { profileStateJsonExportPaths } from '../profile-state/legacy-json/profile-state-export-path' - -vi.mock('../../telemetry/client', () => ({ track: vi.fn() })) -vi.mock('../../telemetry/cohort-classifier', () => ({ - getCohortAtEmit: () => ({ nth_repo_added: 2 }) -})) -vi.mock('../../ssh/config/ssh-config-parser', () => ({ - loadUserSshConfig: () => ({ hosts: [] }), - sshConfigHostsToTargets: () => [] -})) - -describe('profile maintenance without compatibility snapshots', () => { - it('checkpoints SQL without publishing JSON or rewriting explicit exports', async () => { - const { store, dataFile, readState } = await createWorkerMaintenanceFixture() - await store.writeLatestProfileStateJsonExportAsync() - const retainedPaths = profileStateJsonExportPaths(dataFile) - const retainedBytes = retainedPaths.map((path) => readFileSync(path, 'utf8')) - store.updateSettings({ theme: 'dark' }) - store.getWorkspaceSession().activeTabId = 'latest-tab' - - const maintenance = await store.beginProfileMaintenance() - - expect(readState()).toMatchObject({ - settings: { theme: 'dark' }, - workspaceSession: { activeTabId: 'latest-tab' } - }) - expect(existsSync(dataFile)).toBe(false) - expect(profileStateJsonExportPaths(dataFile)).toEqual(retainedPaths) - expect(retainedPaths.map((path) => readFileSync(path, 'utf8'))).toEqual(retainedBytes) - await maintenance.resume() - await store.runDurableMutation(() => { - store.updateSettings({ theme: 'light' }) - return { value: undefined } - }) - expect(readState().settings.theme).toBe('light') - }) - - it('preserves the existing SQL state and publishes no JSON during a recovery pause', async () => { - const { store, dataFile, readState } = await createWorkerMaintenanceFixture() - const before = readState() - store.updateSettings({ theme: 'dark' }) - - await store.beginProfileMaintenance({ flush: false }) - - expect(readState()).toEqual(before) - expect(existsSync(dataFile)).toBe(false) - expect(profileStateJsonExportPaths(dataFile)).toEqual([]) - }) -}) diff --git a/src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts b/src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts index 23a329b99ab..f66d2369aa5 100644 --- a/src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts +++ b/src/main/persistence/loading-store/profile-state-maintenance-contracts.test.ts @@ -3,7 +3,10 @@ import { registerDurableSettingsWriteTests } from './durable-settings-write.spec import { registerProfileStateCallerCancellationTests } from './profile-state-caller-cancellation.spec' import { registerProfileStateMaintenanceFinalFailureTests } from './profile-state-maintenance-final-failure.spec' import { registerProfileStateMaintenanceRecoveryTests } from './profile-state-maintenance-recovery.spec' -import { registerProfileStateMaintenanceTests } from './profile-state-maintenance.spec' +import { + registerProfileStateMaintenanceCompatibilityTests, + registerProfileStateMaintenanceTests +} from './profile-state-maintenance.spec' import { registerProfileStatePtyRetirementFinalizationTests } from './profile-state-pty-retirement-finalization.spec' vi.mock('../../telemetry/client', () => ({ track: vi.fn() })) @@ -27,3 +30,8 @@ describe( 'profile-state-pty-retirement-finalization', registerProfileStatePtyRetirementFinalizationTests ) + +describe( + 'profile maintenance without compatibility snapshots', + registerProfileStateMaintenanceCompatibilityTests +) diff --git a/src/main/persistence/loading-store/profile-state-maintenance.spec.ts b/src/main/persistence/loading-store/profile-state-maintenance.spec.ts index baacfec0d3f..e1efc1d8332 100644 --- a/src/main/persistence/loading-store/profile-state-maintenance.spec.ts +++ b/src/main/persistence/loading-store/profile-state-maintenance.spec.ts @@ -1,9 +1,10 @@ import { ProfileStateSqliteAuthority } from '../profile-state/profile-state-sqlite-authority' -import { readFileSync } from 'node:fs' +import { existsSync, readFileSync } from 'node:fs' import { describe, expect, it, vi } from 'vitest' import { ActiveViewPreference, getActiveViewPreferenceFile } from '../../active-view-preference' import * as backupWorker from '../profile-state/profile-state-backup-worker' import { profileStateDatabaseBackups } from '../profile-state/profile-state-backup-path' +import { profileStateJsonExportPaths } from '../profile-state/legacy-json/profile-state-export-path' import { createSqliteMaintenanceFixture, createWorkerMaintenanceFixture, @@ -295,3 +296,42 @@ export function registerProfileStateMaintenanceTests(): void { }) }) } + +export function registerProfileStateMaintenanceCompatibilityTests(): void { + it('checkpoints SQL without publishing JSON or rewriting explicit exports', async () => { + const { store, dataFile, readState } = await createWorkerMaintenanceFixture() + await store.writeLatestProfileStateJsonExportAsync() + const retainedPaths = profileStateJsonExportPaths(dataFile) + const retainedBytes = retainedPaths.map((path) => readFileSync(path, 'utf8')) + store.updateSettings({ theme: 'dark' }) + store.getWorkspaceSession().activeTabId = 'latest-tab' + + const maintenance = await store.beginProfileMaintenance() + + expect(readState()).toMatchObject({ + settings: { theme: 'dark' }, + workspaceSession: { activeTabId: 'latest-tab' } + }) + expect(existsSync(dataFile)).toBe(false) + expect(profileStateJsonExportPaths(dataFile)).toEqual(retainedPaths) + expect(retainedPaths.map((path) => readFileSync(path, 'utf8'))).toEqual(retainedBytes) + await maintenance.resume() + await store.runDurableMutation(() => { + store.updateSettings({ theme: 'light' }) + return { value: undefined } + }) + expect(readState().settings.theme).toBe('light') + }) + + it('preserves the existing SQL state and publishes no JSON during a recovery pause', async () => { + const { store, dataFile, readState } = await createWorkerMaintenanceFixture() + const before = readState() + store.updateSettings({ theme: 'dark' }) + + await store.beginProfileMaintenance({ flush: false }) + + expect(readState()).toEqual(before) + expect(existsSync(dataFile)).toBe(false) + expect(profileStateJsonExportPaths(dataFile)).toEqual([]) + }) +}