import type { GeneratedRun, StoreGeneratedRunResult, } from '@devrunbook/application' import { describe, expect, it } from 'vitest' import { assertGeneratedRunPersistenceIntegrity, decodeGeneratedRunCursor, DrizzleGeneratedRunStore, encodeGeneratedRunCursor, type GeneratedRunTransaction, type GeneratedRunTransactionRunner, } from './generated-run-store' function run(overrides: Partial = {}): GeneratedRun { return { id: '00000000-0000-4000-8000-000000000101', workspaceId: '00000000-0000-4000-8000-000000000102', generatedBy: '00000000-0000-4000-8000-000000000103', sourceDraftId: null, playbookVersionId: '00000000-0000-4000-8000-000000000104', snapshots: { playbook: { slug: 'root-cause-bugfix' }, repositoryProfile: null, normalizedInput: { problem: 'broken result' }, policy: { autonomy: 'verify' }, provenance: [], }, lint: { exportReadiness: 'ready', findings: [] }, renderedPrompt: '# Task\n', renderDigest: 'a'.repeat(64), idempotencyKey: 'request-1', generatedAt: '2026-07-27T12:00:00.000Z', ...overrides, } } class MemoryGeneratedRunRunner implements GeneratedRunTransactionRunner { stored: GeneratedRun | null = null locks: string[] = [] audits: GeneratedRun[] = [] async run( work: (transaction: GeneratedRunTransaction) => Promise, ): Promise { const transaction: GeneratedRunTransaction = { acquireIdempotencyLock: async (workspaceId, key) => { this.locks.push(`${workspaceId}:${key}`) }, findByIdempotencyKey: async (workspaceId, key) => this.stored?.workspaceId === workspaceId && this.stored.idempotencyKey === key ? this.stored : null, insert: async (candidate) => { this.stored = candidate return candidate }, appendCreationAudit: async (candidate) => { this.audits.push(candidate) }, } return work(transaction) } } describe('DrizzleGeneratedRunStore', () => { it('serializes creation and returns an exact retry without inserting again', async () => { const runner = new MemoryGeneratedRunRunner() const store = new DrizzleGeneratedRunStore(runner) const candidate = run() await expect(store.createIdempotently(candidate)).resolves.toEqual({ run: candidate, created: true, } satisfies StoreGeneratedRunResult) await expect(store.createIdempotently(candidate)).resolves.toEqual({ run: candidate, created: false, } satisfies StoreGeneratedRunResult) expect(runner.locks).toHaveLength(2) expect(runner.audits).toEqual([candidate]) }) it('rejects reuse of the key for different immutable input', async () => { const runner = new MemoryGeneratedRunRunner() const store = new DrizzleGeneratedRunStore(runner) await store.createIdempotently(run()) await expect( store.createIdempotently( run({ snapshots: { ...run().snapshots, policy: { autonomy: 'repair' } }, }), ), ).rejects.toMatchObject({ code: 'generated_run_idempotency_conflict' }) }) it.each([ ['digest', { renderDigest: '0'.repeat(64) }], ['idempotency key', { idempotencyKey: '' }], [ 'snapshot JSON', { snapshots: { ...run().snapshots, normalizedInput: { invalid: undefined }, }, }, ], [ 'lint JSON', { lint: { exportReadiness: 'ready', findings: [{ severity: 'error' }] }, }, ], [ 'repository snapshot identity', { snapshots: { ...run().snapshots, repositoryProfile: { repositoryId: '00000000-0000-4000-8000-000000000105', }, }, }, ], ])('rejects corrupt persisted %s', (_, changes) => { expect(() => assertGeneratedRunPersistenceIntegrity({ ...run(), ...(changes as Partial), }), ).toThrowError( expect.objectContaining({ code: 'generated_run_persistence_corrupt' }), ) }) it('round-trips the stable generatedAt and ID cursor', () => { const cursor = { generatedAt: '2026-07-27T12:00:00.000Z', id: '00000000-0000-4000-8000-000000000101', } expect(decodeGeneratedRunCursor(encodeGeneratedRunCursor(cursor))).toEqual( cursor, ) }) it.each([ '', 'not-base64-json', Buffer.from('{}').toString('base64url'), Buffer.from( JSON.stringify({ generatedAt: 'invalid', id: run().id }), ).toString('base64url'), Buffer.from( JSON.stringify({ generatedAt: run().generatedAt, id: 'not-a-uuid' }), ).toString('base64url'), ])('rejects malformed history cursor %s', (cursor) => { expect(() => decodeGeneratedRunCursor(cursor)).toThrowError( expect.objectContaining({ code: 'generated_run_cursor_invalid' }), ) }) it('rejects invalid history limits and filters before database access', async () => { const store = new DrizzleGeneratedRunStore(new MemoryGeneratedRunRunner()) await expect( store.listForWorkspace(run().workspaceId, { limit: 0 }), ).rejects.toMatchObject({ code: 'generated_run_list_limit_invalid' }) await expect( store.listForWorkspace(run().workspaceId, { playbookSlug: '../other' }), ).rejects.toMatchObject({ code: 'generated_run_filter_invalid' }) await expect( store.listForWorkspace(run().workspaceId, { repositoryId: 'not-a-uuid', }), ).rejects.toMatchObject({ code: 'generated_run_filter_invalid' }) await expect( store.listForWorkspace(run().workspaceId, { cursor: 'invalid' }), ).rejects.toMatchObject({ code: 'generated_run_cursor_invalid' }) }) })