From 2eda8d3bdd8186169fafeb4c3cab2a91c134227a Mon Sep 17 00:00:00 2001 From: hyungi Date: Thu, 18 Jun 2026 17:22:01 +0900 Subject: [PATCH] =?UTF-8?q?feat(presegment):=20G2=20=EC=9D=B8=EC=A0=9C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=AC=ED=99=9C=EC=84=B1=20=E2=80=94=20?= =?UTF-8?q?=ED=9B=84=EB=B3=B4=20A=20e2e=20=EA=B2=80=EC=A6=9D=20PASS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 합성 번들 e2e PASS(자식 3개 합성 file_path·range, uq 위반 0 + 자식 extract range-clamp 1110자 range_ok) 후 인제스트 presegment 재활성(documents.py upload + file_watcher 3곳). 非PDF/단일=통과. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/api/documents.py | 6 +++--- app/workers/file_watcher.py | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/api/documents.py b/app/api/documents.py index 3dec397..f9fc615 100644 --- a/app/api/documents.py +++ b/app/api/documents.py @@ -1167,9 +1167,9 @@ async def upload_document( canonical.duplicate_count = (canonical.duplicate_count or 0) + 1 # document + processing_queue 는 단일 트랜잭션으로 묶어 원자적 정리. - # ★ G2 presegment 인제스트 비활성 (2026-06-18): Option A(자식이 부모 file_path 공유)가 - # uq_documents_file_path UNIQUE 제약과 충돌 — 자식파일 전략 재설계 후 재활성. 현재=직접 extract. - await enqueue_stage(session, doc.id, "extract") + # G2: 첫 stage=presegment (extract 前 번들 PDF 분할, 후보 A 검증완료 2026-06-18). + # 非PDF/단일은 presegment 가 무변 통과 → extract. 번들 PDF 만 N 자식 분할(worker-side gating). + await enqueue_stage(session, doc.id, "presegment") await session.commit() except Exception: # DB 예외 시 session 은 get_session 컨텍스트 종료로 자동 rollback. diff --git a/app/workers/file_watcher.py b/app/workers/file_watcher.py index 6c7c9d9..a96e9df 100644 --- a/app/workers/file_watcher.py +++ b/app/workers/file_watcher.py @@ -118,18 +118,18 @@ def _route_media(path: Path, expected_category: str | None) -> tuple[str | None, if expected_category == "library": # 외부 작성 학습 자료 (KGS Code, 시행규칙 등). 문서 확장자만 수락. # frontmatter 해석은 classify_worker (옵션 C) 가 담당. file_watcher 는 라우팅만. - # ★ G2 presegment 인제스트 비활성(2026-06-18, uq_documents_file_path 충돌) → 직접 extract. + # G2: 첫 stage=presegment (후보 A 검증완료). 非PDF/단일 통과, 번들 PDF 만 분할. if ext in LIBRARY_DOC_EXTS: - return ("library", False, "extract") + return ("library", False, "presegment") if ext in AUDIO_EXTS or ext in VIDEO_DIRECT_EXTS or ext in VIDEO_QUARANTINE_EXTS: return (None, False, None) # audio/video 잘못 들어오면 skip return (None, False, None) # 기타 알 수 없는 확장자 skip # Inbox: 문서 파이프 (기존). audio/video 확장자가 실수로 여기 들어오면 skip. - # ★ G2 presegment 인제스트 비활성(2026-06-18, uq_documents_file_path 충돌) → 직접 extract. + # G2: 첫 stage=presegment (후보 A 검증완료). 非PDF/단일 통과, 번들 PDF 만 분할. if ext in AUDIO_EXTS or ext in VIDEO_DIRECT_EXTS or ext in VIDEO_QUARANTINE_EXTS: return (None, False, None) - return (None, False, "extract") + return (None, False, "presegment") # ─── Web/Blog ingest (devonagent 트랙) 헬퍼 ────────────────────────────────── @@ -228,8 +228,8 @@ async def _ingest_web_file(session, file_path: Path, rel_path: str) -> tuple[int ) session.add(doc) await session.flush() - # ★ G2 presegment 인제스트 비활성(2026-06-18, uq_documents_file_path 충돌) → 직접 extract. - await enqueue_stage(session, doc.id, "extract") + # G2: 첫 stage=presegment (후보 A 검증완료). HTML(非PDF)은 presegment 가 무변 통과 → extract. + await enqueue_stage(session, doc.id, "presegment") return (1, 0)