import { describe, expect, it } from 'vitest' import type { CompletionResult } from './chat-client.js' import { captureWork, parseCaptureArgs } from './capture-work.js' describe('parseCaptureArgs', () => { it('validates issues and keeps only real titles + valid labels', () => { const p = parseCaptureArgs({ issues: [ { title: 'Fix token refresh', body: 'dies silently', estimate: 'est/2d', priority: 'p/1' }, { title: ' ', body: 'blank title dropped' }, { title: 'Docs', estimate: 'est/9d', priority: 'urgent' }, // invalid labels → dropped to undefined ], consequence: 'Beta slips a day', }) expect(p.issues).toHaveLength(2) expect(p.issues[0]).toEqual({ title: 'Fix token refresh', body: 'dies silently', estimate: 'est/2d', priority: 'p/1' }) expect(p.issues[1]).toEqual({ title: 'Docs', body: '', estimate: undefined, priority: undefined }) expect(p.consequence).toBe('Beta slips a day') }) it('tolerates a missing/!array issues field', () => { expect(parseCaptureArgs({}).issues).toEqual([]) expect(parseCaptureArgs({ issues: 'nope' }).issues).toEqual([]) }) }) describe('captureWork', () => { it('forces propose_issues and returns the validated set', async () => { const result: CompletionResult = { content: '', toolCalls: [ { id: 'c1', name: 'propose_issues', arguments: JSON.stringify({ issues: [{ title: 'Retry token refresh with backoff', body: '', estimate: 'est/2d', priority: 'p/2' }], consequence: 'no material shift', }), }, ], } let sawTool = '' const proposal = await captureWork(async (_m, tools) => { sawTool = tools?.[0]?.name ?? '' return result }, 'auth is flaky, token refresh dies') expect(sawTool).toBe('propose_issues') expect(proposal.issues[0].title).toBe('Retry token refresh with backoff') expect(proposal.consequence).toBe('no material shift') }) it('returns an empty set when the model answers without the tool', async () => { const proposal = await captureWork(async () => ({ content: 'I need more detail.', toolCalls: [] }), 'vague') expect(proposal.issues).toEqual([]) }) it('survives malformed tool arguments', async () => { const proposal = await captureWork( async () => ({ content: '', toolCalls: [{ id: 'c1', name: 'propose_issues', arguments: '{not json' }] }), 'x', ) expect(proposal.issues).toEqual([]) }) })