fix(schema): null/empty title/summary 를 placeholder 로 coerce

gemma4:26b 가 본문 빈 케이스에 title=null/summary=null 반환 → schema throw.
prompt 강화로 부족. schema 단계에서 graceful coerce:
- null/empty title → '(첨부 메모)'
- null/empty summary → '내용을 자동으로 정리하지 못했습니다.'
- 영어 title → '(첨부 메모)' (이전엔 throw)
- malformed/empty due_date → null (이전엔 throw)

raw_text 는 호출자가 보존하므로 사용자 데이터 손실 없음.
사용자가 후에 NoteCard 에서 직접 편집 가능.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
th-kim0823
2026-05-12 14:24:20 +09:00
parent b2be29bd33
commit 218868206b
2 changed files with 49 additions and 13 deletions

View File

@@ -13,10 +13,21 @@ describe('parseAiResponse', () => {
expect(r.tags).toEqual(['api-timeout', 'meeting']);
});
it('rejects title without Korean', () => {
expect(() =>
parseAiResponse({ title: 'English only', summary: 'a\nb\nc', tags: [] })
).toThrow(/korean/i);
it('영어 title → (첨부 메모) placeholder fallback (vision graceful 처리)', () => {
const r = parseAiResponse({ title: 'English only', summary: 'a\nb\nc', tags: [] });
expect(r.title).toBe('(첨부 메모)');
});
it('null title/summary → placeholder coerce (vision 본문 빈 케이스)', () => {
const r = parseAiResponse({ title: null, summary: null, tags: [], due_date: null });
expect(r.title).toBe('(첨부 메모)');
expect(r.summary.startsWith('내용을 자동으로 정리하지 못했습니다')).toBe(true);
});
it('empty string title/summary → placeholder coerce', () => {
const r = parseAiResponse({ title: '', summary: '', tags: [] });
expect(r.title).toBe('(첨부 메모)');
expect(r.summary.length).toBeGreaterThan(0);
});
it('pads short summary to 3 lines', () => {
@@ -82,10 +93,14 @@ describe('parseAiResponse', () => {
expect(r.dueDate).toBeNull();
});
it('rejects malformed due_date string', () => {
expect(() =>
parseAiResponse({ title: '내일', summary: 'a\nb\nc', tags: [], due_date: 'tomorrow' })
).toThrow();
it('malformed due_date string → null coerce (vision graceful 처리)', () => {
const r = parseAiResponse({ title: '내일', summary: 'a\nb\nc', tags: [], due_date: 'tomorrow' });
expect(r.dueDate).toBeNull();
});
it('empty string due_date → null coerce', () => {
const r = parseAiResponse({ title: '내일', summary: 'a\nb\nc', tags: [], due_date: '' });
expect(r.dueDate).toBeNull();
});
it('coerces invalid date that passes regex (e.g. 2026-13-99) to null', () => {