2afd1ac589
신뢰성 코어 (P1~P2): - Requirement Graph: 업무 유형(회의록/시장조사/업무조사/일정) 필수 요소 주입 + 커버리지 hook - Confidence Engine(0~100 결정론적) / Escalation Engine(검토 요청) / Epistemic Guard(모름·추정·확실 3분류) - Provenance: citationTrace 에 출처 수정일·오래됨 경고 - Critic Loop: 문제 신호 turn 만 LLM 검수 1회 + 보완 카드 성장 루프 (P3): - Gap Detector(Requirement-Knowledge) / Need Engine(30/25/20/15/10 공식) / Knowledge Inventory - Learning Queue(proposed 전용 병합 — 승인은 사람만) / Decision Journal / Reflection 기록 - 반복 누락 요소(3회+)는 다음 turn 체크리스트에 자동 강조 (T5 루프) 지식 운영 (P4) + 기억 (P5) + 학습 실행 (P6): - Knowledge Validation + Belief Revision(중복 reject·충돌 시 update/add 권고) - Knowledge Decay(분야별 반감기 감사) / Knowledge Debt(blocked x impact) - Organizational Memory(.astra/organization.md 상시 주입) - Research Agent(approved 큐 -> 조사 브리프+추정 라벨 초안+Validation 게이트 -> proposals/) - Skill Score(전/후반 추세) + Success Pattern DB(전요소충족+확신도90+ 자동 적재) 병렬 트랙: - 캘린더 충돌 게이트: conflictCheck + 구조화 이벤트 캐시 + create_calendar_event 차단(force 는 사용자 승인 후) - Task Eval Harness: 회의록 골든셋 자동 채점 명령 + 성장 리포트/학습 큐/노후 점검 명령 신규 모듈 17종(src/intelligence/), VS Code 명령 5종, 설정 11종, 테스트 +89건(전체 508 통과). 설계 문서: docs/SELF_EVOLVING_OS_MASTER_PLAN.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
66 lines
2.8 KiB
TypeScript
66 lines
2.8 KiB
TypeScript
/**
|
|
* Schedule Conflict Check (Self-Evolving OS Track 6-2/6-3) 테스트.
|
|
*/
|
|
import { findScheduleConflicts, formatConflictReport, CachedCalEvent } from '../src/features/calendar/conflictCheck';
|
|
import { _parseCalEventAttrs } from '../src/agent/attrParsers';
|
|
|
|
// 로컬 ISO (timezone 없음) — 실제 캐시도 로컬 자정 기준 all-day 를 담으므로
|
|
// 테스트를 실행 머신 timezone 과 무관하게 만든다.
|
|
const EXISTING: CachedCalEvent[] = [
|
|
{ summary: '주간회의', startIso: '2026-06-12T14:00:00', endIso: '2026-06-12T15:00:00', allDay: false, location: '회의실 A' },
|
|
{ summary: '워크숍', startIso: '2026-06-13T00:00:00', allDay: true },
|
|
];
|
|
|
|
describe('findScheduleConflicts', () => {
|
|
it('구간이 겹치면 충돌', () => {
|
|
const c = findScheduleConflicts(EXISTING, { startIso: '2026-06-12T14:30:00', durationMinutes: 60 });
|
|
expect(c.length).toBe(1);
|
|
expect(c[0].summary).toBe('주간회의');
|
|
});
|
|
|
|
it('경계 접촉(끝=시작)은 충돌 아님', () => {
|
|
const c = findScheduleConflicts(EXISTING, { startIso: '2026-06-12T15:00:00', durationMinutes: 60 });
|
|
expect(c.length).toBe(0);
|
|
});
|
|
|
|
it('endIso 없으면 기본 60분으로 판정', () => {
|
|
const c = findScheduleConflicts(EXISTING, { startIso: '2026-06-12T13:30:00' });
|
|
expect(c.length).toBe(1); // 13:30~14:30 vs 14:00~15:00
|
|
});
|
|
|
|
it('종일 일정과 그 날짜의 시간 일정은 충돌', () => {
|
|
const c = findScheduleConflicts(EXISTING, { startIso: '2026-06-13T10:00:00', durationMinutes: 30 });
|
|
expect(c.some((e) => e.summary === '워크숍')).toBe(true);
|
|
});
|
|
|
|
it('잘못된 날짜 입력은 보수적으로 충돌 없음 (생성 단계에서 실패)', () => {
|
|
expect(findScheduleConflicts(EXISTING, { startIso: 'not-a-date' })).toEqual([]);
|
|
expect(findScheduleConflicts([{ summary: 'x', startIso: 'broken', allDay: false }], { startIso: '2026-06-12T14:00:00' })).toEqual([]);
|
|
});
|
|
|
|
it('빈 캐시면 충돌 없음', () => {
|
|
expect(findScheduleConflicts([], { startIso: '2026-06-12T14:00:00' })).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('formatConflictReport', () => {
|
|
it('충돌 목록 + force 안내 포함', () => {
|
|
const msg = formatConflictReport([EXISTING[0]]);
|
|
expect(msg).toContain('주간회의');
|
|
expect(msg).toContain('force="true"');
|
|
expect(msg).toContain('보류');
|
|
});
|
|
});
|
|
|
|
describe('_parseCalEventAttrs force 속성', () => {
|
|
it('force="true" 파싱', () => {
|
|
const attrs = _parseCalEventAttrs(' title="미팅" start="2026-06-12T14:00" force="true"');
|
|
expect(attrs.force).toBe(true);
|
|
});
|
|
|
|
it('미지정이면 undefined (기본 차단 동작)', () => {
|
|
const attrs = _parseCalEventAttrs(' title="미팅" start="2026-06-12T14:00"');
|
|
expect(attrs.force).toBeUndefined();
|
|
});
|
|
});
|