/** * Regression guard for the /meet prompt policy. * * These 4 rules were added after a real meeting record showed the failure modes: * 1) anonymous/numbered speakers assigned as action owners (fake accountability) * 2) content-empty deictic quotes ("이렇게 이렇게") passed off as 근거 * 3) deadlines mentioned in risks/discussion not reflected in action 기한 * 4) speakers in the body who aren't in the attendee list * * Prompts can't be unit-tested for model behavior, but we CAN guard that the * policy text doesn't silently get dropped in a future refactor. */ import { buildMeetPrompt, buildMeetExtractPrompt, buildMeetReducePrompt, } from '../src/features/datacollect/prompts/meetPrompt'; const transcript = '참석자 1: 이거는 이렇게 이렇게 해주세요. 효희 팀장: 네 수정할게요.'; const metadata = '회의명: 테스트'; describe('/meet prompt — accountability & grounding policy', () => { // The OUTPUT_FORMAT block is shared by the single-shot and reduce paths, so // both must carry the policy. const sharedFormatBuilders: Array<[string, string]> = [ ['buildMeetPrompt', buildMeetPrompt(transcript, metadata)], ['buildMeetReducePrompt', buildMeetReducePrompt('## 액션\n- [미지정] 작업', metadata)], ]; test.each(sharedFormatBuilders)('%s forbids assigning anonymous speakers as owners', (_name, prompt) => { expect(prompt).toContain('[미지정-확인필요]'); expect(prompt).toMatch(/익명·번호 화자/); }); test.each(sharedFormatBuilders)('%s rejects content-empty deictic quotes', (_name, prompt) => { expect(prompt).toContain('[내용 확인필요]'); expect(prompt).toMatch(/이렇게 이렇게/); }); test.each(sharedFormatBuilders)('%s cross-references deadlines into action 기한', (_name, prompt) => { expect(prompt).toMatch(/기한 역참조/); }); test.each(sharedFormatBuilders)('%s flags speakers missing from the attendee list', (_name, prompt) => { expect(prompt).toMatch(/명단 외 화자|참석자 명단 정합성/); }); test('extract (map) stage also avoids anonymous owner assignment & empty quotes', () => { const p = buildMeetExtractPrompt('참석자 1: 이거 이렇게요', metadata, 1, 3); expect(p).toContain('[미지정]'); expect(p).toContain('[내용 확인필요]'); }); test('final checklist references the new gates', () => { const prompt = buildMeetPrompt(transcript, metadata); expect(prompt).toMatch(/익명·번호 화자를 담당으로 확정하지 않고/); expect(prompt).toMatch(/빈 인용을 근거로 달지 않았는가/); }); });