documents_md_status_check 제약은 {pending/processing/success/partial/failed/skipped}
만 허용. extract_worker 의 web HTML 분기가 'ready' 박아서 CheckViolationError
로 3회 실패. plan/docs/메모리에 'ready' 로 잘못 표기됐던 것 수정.
19668 (첫 sample doc) 검증 중 발견. fix 후 queue 'failed' 행 reset 으로 재실행.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
스캔 PDF/이미지 자동 OCR 트리거 + 결과 품질 검증 + 1회 제한.
- extract_meta JSONB 컬럼 추가 (migration 134)
ocr_attempted, ocr_reason, ocr_skip_reason, ocr_terminal, ocr_chars
- PDF OCR 트리거: total_chars < 300 또는 avg < 80 && total < 3000
- 이미지 자동 OCR: jpg/png/tiff/webp 등
- 품질 차등: 이미지 50자, PDF 200자 또는 페이지당 30자
- 상한: pages > 200 또는 file_size > 150MB → 스킵
- OCR 1회 제한: extract_meta.ocr_attempted로 재시도 방지
- extractor_version은 도구명만 (surya_ocr/pymupdf/kordoc)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
kordoc은 PDF 전체를 메모리에 올려 파싱 → 이미지 PDF에서 OOM.
PyMuPDF는 페이지 단위 스트리밍으로 40MB+ PDF도 수백 MB 내 처리.
- kordoc 시도 → 실패(OOM/timeout/422) → PDF면 PyMuPDF fallback
- PyMuPDF도 텍스트 레이어 없으면 로그 경고 (스캔 전용 PDF)
- HWP/HWPX는 kordoc 전용 (fallback 없음)
- extractor_version으로 어떤 경로로 추출됐는지 추적
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
25MB 파일 크기 제한은 텍스트 PDF(18MB 성공)까지 차단하는 문제.
실제 원인은 이미지 스캔 PDF의 in-memory 파싱 시 메모리 폭발.
- extract_worker: 25MB 파일 크기 제한 삭제
- docker-compose: kordoc-service mem_limit 4g + memswap_limit 4g
- 텍스트 PDF → 크기 무관 정상 파싱
- 이미지 PDF → 4GiB 초과 시 Docker OOM-kill → 재시작 → 3회 실패 후 failed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
38.2MB PDF에서 kordoc이 22.8GiB 메모리 사용 후 OOM 크래시 확인.
컨테이너 재시작으로 다른 문서 처리까지 차단되는 문제 방지.
- 25MB 초과 파일: kordoc 호출 없이 스킵 (extractor_version에 크기 기록)
- 25MB 이하 파일: 기존 adaptive timeout으로 정상 처리
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- extract_worker: LibreOffice 15000자 절단 제거 (full text 저장 원칙)
- classify_worker/summarize_worker: 요약 입력 15000→50000자 확대
- client.py: 길이 기반 Claude 자동전환 제거 (require_explicit_trigger 정책 준수)
_call_chat의 primary→fallback(exaone3.5) 체인은 유지
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
대형 PDF(14~40MB)에서 kordoc 파싱 timeout(60초) 실패하던 문제.
10MB당 60초 추가, 최소 60초 최대 300초로 조정.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
embed_worker:
- extracted_text[:6000] → title + ai_summary + tags(top 5) metadata 입력
- 500k자 문서의 표지+목차가 임베딩되는 구조적 버그 해결
- Ollama 기본 context 안전 (~1500자 이하), num_ctx 조정 불필요
- ai_summary < 50자 시 본문 800자 fallback
- ai_domain 은 초기 제외 (taxonomy 노이즈 방지)
extract_worker:
- kordoc / 직접 읽기 / LibreOffice 3 경로 모두 \x00 strip
- asyncpg CharacterNotInRepertoireError 재발 방지
queue_consumer:
- str(e) or repr(e) or type(e).__name__ fallback
- 빈 메시지 예외(24건 발생) 다음부터 클래스명이라도 기록
plan: ~/.claude/plans/quiet-meandering-nova.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- original_path/format/hash + conversion_status 필드 추가 (migration 007)
- extract_worker: 텍스트 추출 후 xlsx→ods, docx→odt 등 ODF 변환
- 변환본은 .derived/{doc_id}.ods 에 저장
- 원본 메타 보존 (original_path/format/hash)
- file_watcher: .derived/ .preview/ 디렉토리 제외
- DocumentViewer: ODF 포맷이면 편집 버튼 자동 표시
- edit_url 있으면 "편집", 없으면 "Synology Drive에서 열기"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- xlsx, docx, pptx, odt, ods, odp, odoc, osheet 지원
- LibreOffice --convert-to txt로 텍스트 추출 (60s timeout)
- 추가 의존성 없음 (Docker에 이미 설치된 LibreOffice 사용)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Implement kordoc /parse endpoint (HWP/HWPX/PDF via kordoc lib,
text files direct read, images flagged for OCR)
- Add queue consumer with APScheduler (1min interval, stage chaining
extract→classify→embed, stale item recovery, retry logic)
- Add extract worker (kordoc HTTP call + direct text read)
- Add classify worker (Qwen3.5 AI classification with think-tag
stripping and robust JSON extraction from AI responses)
- Add embed worker (GPU server nomic-embed-text, graceful failure)
- Add DEVONthink migration script with folder mapping for 16 DBs,
dry-run mode, batch commits, and idempotent file_path UNIQUE
- Enhance ai/client.py with strip_thinking() and parse_json_response()
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>