from __future__ import annotations import json import sys from pathlib import Path import scripts.runtime.materials as materials from reportlab.pdfgen import canvas REPO_ROOT = Path(__file__).resolve().parents[1] if str(REPO_ROOT) not in sys.path: sys.path.insert(0, str(REPO_ROOT)) from scripts.runtime.phase1 import create_project, render_framework def make_text_pdf(path: Path, text: str) -> None: c = canvas.Canvas(str(path)) c.drawString(72, 720, text) c.save() def test_init_ingests_pdf_material_into_phase0(tmp_path: Path) -> None: pdf = tmp_path / "audit.pdf" make_text_pdf(pdf, "GMP audit finding: deviation management is incomplete.") project = create_project( topic="白帆生物 GMP 与运营诊断", slug="baifan-test", projects_dir=tmp_path / "projects", method_key="gmp_quality_operations_diagnosis", input_materials=[str(pdf), "补充说明:运营团队需要同步诊断"], ) manifest = json.loads((project / "manifest.json").read_text(encoding="utf-8")) inventory = manifest["material_inventory"] assert inventory[0]["kind"] == "pdf" assert inventory[0]["copied_to"] == "phase0/inputs/audit.pdf" assert inventory[0]["extracted_to"] == "phase0/extracted/audit.md" assert inventory[0]["ocr_required"] is False assert "deviation management" in (project / "phase0/extracted/audit.md").read_text(encoding="utf-8") assert inventory[1]["kind"] == "note" material_brief = project / "phase1" / "material_brief.md" assert material_brief.exists() assert "Phase 0 材料简报" in material_brief.read_text(encoding="utf-8") assert "待用户确认" in material_brief.read_text(encoding="utf-8") assert manifest["phase1"]["requires_user_interview"] is True def test_framework_mentions_ingested_materials(tmp_path: Path) -> None: pdf = tmp_path / "audit.pdf" make_text_pdf(pdf, "Quality system audit.") project = create_project( topic="白帆生物 GMP 与运营诊断", slug="baifan-test", projects_dir=tmp_path / "projects", method_key="gmp_quality_operations_diagnosis", input_materials=[str(pdf)], ) render_framework(project, method_key="gmp_quality_operations_diagnosis") framework = (project / "phase1/framework.md").read_text(encoding="utf-8") research_brief_md = project / "phase1" / "research_brief.md" research_brief_json = project / "phase1" / "research_brief.json" brief = json.loads(research_brief_json.read_text(encoding="utf-8")) assert "phase0/extracted/audit.md" in framework assert "NMPA、FDA、EMA、ICH、WHO" in framework assert "请先确认 `phase1/material_brief.md`" in framework assert research_brief_md.exists() assert "任务切分原则" in research_brief_md.read_text(encoding="utf-8") assert brief["research_method"] == "gmp_quality_operations_diagnosis" assert brief["work_language"] == "zh" assert brief["task_planning"]["required_skills"] assert brief["task_planning"]["search_routes_by_axis"]["counter"] == ["scholar", "general"] assert brief["phase2_inputs"]["framework_path"] == "phase1/framework.md" def test_pdf_requiring_ocr_uses_firered_and_records_result(tmp_path: Path, monkeypatch) -> None: pdf = tmp_path / "scan.pdf" c = canvas.Canvas(str(pdf)) c.showPage() c.save() def fake_ocr_pdf(*, pdf_path: Path, output_dir: Path, endpoint: str, max_pages: int) -> materials.OcrResult: assert pdf_path == pdf assert endpoint == materials.DEFAULT_FIRERED_OCR_ENDPOINT out = output_dir / "scan.ocr.md" out.write_text("# OCR\n\n扫描审计发现:偏差管理未闭环。\n", encoding="utf-8") return materials.OcrResult(text="扫描审计发现:偏差管理未闭环。", pages_processed=1, output_path=out) monkeypatch.setattr(materials, "ocr_pdf_with_firered", fake_ocr_pdf) project = create_project( topic="白帆生物 GMP 与运营诊断", slug="baifan-test", projects_dir=tmp_path / "projects", method_key="gmp_quality_operations_diagnosis", input_materials=[str(pdf)], ) manifest = json.loads((project / "manifest.json").read_text(encoding="utf-8")) item = manifest["material_inventory"][0] assert item["ocr_required"] is True assert item["ocr_status"] == "completed" assert item["ocr_text_chars"] > 0 assert item["ocr_extracted_to"] == "phase0/extracted/scan.ocr.md" assert "扫描审计发现" in (project / "phase0/extracted/scan.md").read_text(encoding="utf-8")