# Task-512 완료 보고서: InsuRo 벡터 검색 통합 + Drive 커넥터 고도화

## SCQA

**S**: InsuRo 서비스에 pgvector 인프라(Phase 1)와 Docling 파싱(Phase 2)이 구현되어 있으며, `POST /api/insuro/search` 엔드포인트가 이미 main.py에 존재한다.

**C**: 금소법 PDF의 자동 인덱싱 파이프라인, 프론트엔드 검색 UI, Google Drive 변경 감지가 미구현 상태로, 실전 서비스에서 벡터 검색을 활용할 수 없었다.

**Q**: Phase 1/2 인프라를 InsuRo 서비스에 실전 통합하여 금소법 검색 기능을 완성할 수 있는가?

**A**: 4개 핵심 모듈을 신규 구현하여 Phase 3을 완성했다. 백엔드 인덱싱 스크립트(ingest_fcpa.py), Drive 동기화(gdrive_sync.py), 인제스트 API 엔드포인트, 프론트엔드 검색 UI 및 관리자 인덱싱 버튼을 모두 구현했다. pytest 34건 전체 통과, pyright 에러 0건.

---

## 구현 내용

### 1. Supabase 마이그레이션
- 상태: **수동 실행 필요** (SQL Editor 또는 psql)
- 파일: `/home/jay/workspace/libs/migrations/001_pgvector_setup.sql` (기존)
- 대상: InsuRo Supabase 인스턴스

### 2. 금소법 PDF 자동 인덱싱 (ingest_fcpa.py)
- **신규 파일**: `/home/jay/projects/InsuRo/server/ingest_fcpa.py` (71줄)
- 동작: 로컬 PDF 읽기 → Docling 파싱 → chunking → embedding → Supabase 저장
- source 태그: `insuro_fcpa`
- 중복 방지: libs/ingest.py의 content_hash 자동 활용
- CLI: `python3 ingest_fcpa.py [--pdf-path PATH]`
- 기본 PDF: `/home/jay/.cokacdir/workspace/autoset/금융소비자_보호에_관한_법률법률제21065호20260102.pdf`

### 3. Google Drive 변경 감지 (gdrive_sync.py)
- **신규 파일**: `/home/jay/projects/InsuRo/server/gdrive_sync.py` (224줄)
- 동작: Drive 폴더 스캔 → 새 PDF 감지/인제스트, 삭제 감지/인덱스 제거
- 동기화 상태: `sync_state.json` 로컬 파일로 관리
- CLI: `python3 gdrive_sync.py [--folder-id ID]`
- 환경변수: INSURO_GOOGLE_CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN, DRIVE_FOLDER_ID

### 4. 인제스트 API 엔드포인트
- **수정 파일**: `/home/jay/projects/InsuRo/server/main.py` (+11줄)
- `POST /api/insuro/ingest` — JWT 인증 필수
- 금소법 PDF 인제스션 트리거, document_id 반환

### 5. 프론트엔드 검색 UI (FcpaGuide.tsx)
- **수정 파일**: `/home/jay/projects/InsuRo/src/pages/FcpaGuide.tsx` (137줄 → 308줄)
- 검색창: 입력 300ms 디바운스 자동 검색 + Enter 즉시 검색
- 결과 표시: 관련도 점수(%), 문서 제목, 텍스트 스니펫(200자)
- 비파괴: 검색어 없을 때 기존 summary + checklist 그대로 표시
- 검색 초기화: X 버튼으로 기존 뷰 복귀

### 6. 관리자 인제스션 UI (AdminFcpa.tsx)
- **수정 파일**: `/home/jay/projects/InsuRo/src/pages/AdminFcpa.tsx` (258줄 → 322줄)
- "금소법 PDF 인덱싱 실행" 버튼 추가
- `POST /api/insuro/ingest` 호출 → 진행 중 spinner → 완료 시 document_id 표시
- toast 알림 (성공/실패)

---

## 생성/수정 파일 목록

| 파일 | 상태 | 설명 |
|------|------|------|
| `/home/jay/projects/InsuRo/server/ingest_fcpa.py` | 신규 | 금소법 PDF 인덱싱 스크립트 |
| `/home/jay/projects/InsuRo/server/gdrive_sync.py` | 신규 | Drive 변경 감지 + 자동 인제스션 |
| `/home/jay/projects/InsuRo/server/main.py` | 수정 | ingest 엔드포인트 추가 |
| `/home/jay/projects/InsuRo/src/pages/FcpaGuide.tsx` | 수정 | 벡터 검색 UI 추가 |
| `/home/jay/projects/InsuRo/src/pages/AdminFcpa.tsx` | 수정 | 인제스션 버튼 추가 |
| `/home/jay/projects/InsuRo/server/tests/test_ingest_fcpa.py` | 신규 | 12개 테스트 |
| `/home/jay/projects/InsuRo/server/tests/test_gdrive_sync.py` | 신규 | 22개 테스트 |

---

## 테스트 결과

- **test_ingest_fcpa.py**: 12/12 PASSED
- **test_gdrive_sync.py**: 22/22 PASSED
- **총합**: 34/34 PASSED (6.39s)
- **pyright**: 0 errors, 0 warnings, 0 informations (3개 파일)

---

## 발견된 이슈

1. **Supabase 마이그레이션 미실행**: 001_pgvector_setup.sql이 아직 InsuRo Supabase에 적용되지 않음. 실제 인덱싱/검색 실행 전 마이그레이션 필수.
2. **기존 테스트 실패**: test_main.py와 test_ai_parser.py에 pre-existing 실패 케이스 존재 (본 작업 범위 외). 본 작업으로 인한 회귀 아님.
3. **Drive 동기화 cron 미설정**: gdrive_sync.py는 1회성 CLI 실행만 구현. 주기적 실행은 별도 cron/스케줄러 설정 필요.

---

## QC 검증 결과

- **overall**: WARN (Gate PASS)
- **file_check**: PASS (6/6 파일 확인)
- **pyright_check**: PASS (0 errors, 0 warnings)
- **tdd_check**: PASS (테스트 2개 + 구현 3개 확인)
- **style_check**: WARN (black/isort 포매팅 적용 완료, QC 환경 차이로 잔여 WARN)
- **data_integrity**: SKIP (타이머 ID 형식 불일치: task-512 vs task-512.1)
- **test_runner**: SKIP (pre-existing 실패 9건 존재, 본 작업 무관)
- **api_health**: SKIP (서버 미기동 상태)
- **.done 파일**: 자동 생성 완료

### 스킵 사유 상세

**test_runner 스킵**: test_ai_parser.py 1건 + test_main.py 8건 pre-existing 실패.
- `test_ai_parser.py::TestAnalyzeFcpaPdf::test_analyze_fcpa_pdf_includes_pdf_text_in_prompt` — prompt 텍스트 assertion 오류
- `test_main.py::TestUploadSuccess` 8건 — JWT JWKS 검증 방식 변경 후 테스트 fixture 미갱신 (401 Unauthorized)
- **본 작업 테스트(34건)는 전원 통과 확인**: `pytest tests/test_ingest_fcpa.py tests/test_gdrive_sync.py → 34/34 PASSED`

**data_integrity 스킵**: dispatch.py가 타이머를 task-512.1로 등록했으나 QC는 task-512로 검색하여 불일치.
