# InsuWiki AI 노드 자동 연결 — Phase 0 + Phase 1-A 구현

## 개요
InsuWiki 문서 간 관련 노드를 자동으로 연결하는 기능 구현.
이번 위임 범위: Phase 0 (보안 기초) + Phase 1-A (정적 매칭).

## 프로젝트 경로
- InsuWiki: `/home/jay/projects/insuwiki/`
- 계획서: `/home/jay/workspace/memory/plans/insuwiki-ai-linking/plan.md`
- 체크리스트: `/home/jay/workspace/memory/plans/insuwiki-ai-linking/checklist.md`
- 맥락노트: `/home/jay/workspace/memory/plans/insuwiki-ai-linking/context-notes.md`
- 미팅 기록: `/home/jay/workspace/memory/meetings/2026-03-22-insuwiki-ai-auto-linking.md`

⚠️ 반드시 계획서/체크리스트/맥락노트를 읽고 시작하세요. 모든 설계 결정의 근거가 담겨 있습니다.

---

## Phase 0: 보안 기초 (선행 필수)

### 0-1. links 스키마 확정
기존 links 컬렉션에 아래 필드를 추가하는 스키마를 확정:
```
{
  sourceId: string,
  targetId: string,
  method: "manual" | "static" | "embedding" | "semantic",
  confidence: number (0-100),
  createdBy: "user" | "system" | "ai",
  status: "active" | "pending",
  explanation: string (선택),
  createdAt: timestamp,
  updatedAt: timestamp
}
```

### 0-2. Firestore Rules 강화
- links 컬렉션 write validation 추가:
  - confidence: 0-100 범위 밖이면 write 거부
  - method: 허용값("manual"|"static"|"embedding"|"semantic") 외이면 거부
  - createdBy: 필수 필드 검증
  - status: "active" 또는 "pending"만 허용
- 기존 Rules를 깨뜨리지 않도록 주의

### 0-3. 기존 데이터 백필
- 기존 links 문서에 `method: "manual"`, `createdBy: "user"`, `status: "active"` 백필
- 백필 스크립트 작성 (1회성, Cloud Function 또는 스크립트)

### 0-4. 완료 기준
- 잘못된 스키마로 write 시 거부되는지 테스트
- 기존 기능(WikiLink [[]] 등) 정상 동작 확인

---

## Phase 1-A: 정적 매칭

### 1A-1. 정규화 테이블 (normalizeMap)
보험 용어 공백/띄어쓰기 변형 처리용 테이블:
```javascript
const normalizeMap = {
  "종신 보험": "종신보험",
  "CI 보험": "CI보험",
  "씨아이보험": "CI보험",
  // ... 50-100개
};
```
- Firestore `config/normalizeMap` 문서에 저장
- 초기 데이터는 `insurance_terms` 컬렉션의 `commonAliases` 기반으로 자동 생성
- 부족한 부분은 TODO 코멘트 (제이회장님 검수 예정)

### 1A-2. Cloud Function 정적 매칭 로직
- Firestore `onWrite` 트리거: 문서(documents 컬렉션) 저장 시 자동 실행
- insurance_terms 메모리 캐싱 (TTL 1시간)
- 매칭 순서:
  1. exact match (Set lookup, O(1)) → confidence: 100
  2. alias match (commonAliases 기반) → confidence: 90
  3. 공백 제거 후 match → confidence: 85
  4. substring 포함 체크 → confidence: 70
- 결과를 `documents/{docId}/ai_suggestions` 서브컬렉션에 저장
- 매칭 결과에 method: "static", createdBy: "system", status: "pending" 기록

### 1A-3. 사이드바 추천 UI
- 문서 편집/보기 화면 우측에 **"관련 문서 추천"** 사이드바 컴포넌트
- ai_suggestions 서브컬렉션에서 추천 목록 로드
- confidence 내림차순 정렬
- 각 추천에 표시:
  - 문서 제목 (클릭 시 이동)
  - confidence 수치 또는 바
  - method 뱃지 ("용어 매칭")
  - 승인/거부 버튼
- 승인 시: links 컬렉션에 새 문서 생성 (status: "active")
- 거부 시: ai_suggestions에서 해당 추천 `dismissed: true` 마킹
- 최대 5개 표시 (기본값, config 외부화)

### 1A-4. 기존 기능 공존
- 기존 WikiLink `[[]]` 자동 감지 Cloud Function과 충돌 없도록
- 기존 수동 링크는 method: "manual"로 구분
- 정적 매칭 추천이 기존 수동 링크와 중복되면 자동 제외

### 1A-5. config 외부화
신뢰도 임계값 등 설정을 Firestore `config/aiLinking` 문서에 저장:
```javascript
{
  maxSuggestions: 5,
  minConfidence: 70,
  autoApproveThreshold: 95, // Phase 1-A에서는 자동 승인 안 함 (향후용)
  termsCacheTTL: 3600, // 1시간
  enabled: true
}
```

### 1A-6. 완료 기준
- 기존 문서 10건 대상 정적 매칭 실행 → 정확도 90%+ 확인
- 사이드바 UI에 추천 표시 정상 동작
- 승인/거부 플로우 정상 동작
- 기존 WikiLink 기능 회귀 없음

---

## 기술 스택 참고
- Next.js (기존 InsuWiki)
- Firebase Firestore
- Firebase Cloud Functions
- insurance_terms 컬렉션: term, definition, commonAliases[], icdCodes[]
- documents 컬렉션: outgoingLinks[], outgoingLinkIds[], incomingLinkCount
- links 컬렉션: source→target 백링크

## 주의사항
1. 기존 InsuWiki 기능을 깨뜨리지 마세요
2. Phase 1-B~3 관련 코드는 이번에 구현하지 마세요 (향후 확장 가능하도록 구조만)
3. 한국어 형태소 분석기 사용 금지 (ROI 부적합 — 맥락노트 참조)
4. links 스키마에 method, confidence 등 필드를 처음부터 넣되, Phase 1-A에서는 "static"만 사용
5. 정규화 테이블 초기 데이터가 부족할 수 있음 — commonAliases 기반으로 최대한 자동 생성하고, 나머지는 TODO
6. InsuWiki git repo: `/home/jay/projects/insuwiki/` — 반드시 이 경로에서 작업

## 완료 후
- 보고서: `memory/reports/task-820.1.md`
- task-timer end 호출
