From 41614b78ef82d56c0d085a1ae938affa2794e922 Mon Sep 17 00:00:00 2001 From: CC Worker Date: Thu, 2 Jul 2026 21:22:54 +0000 Subject: [PATCH] FX-3: project image-only papers to Neo4j after auto-map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the born-digital fast path enqueued project_template_safe; the async OCR job (_run_auto_map_job) — where image-only papers, R3's primary target, are routed — never projected, so those papers never reached the graph after auto-map. Project at the end of the async job too. Adds test_auto_map_ocr_path_projects_to_neo4j. Co-Authored-By: Claude Opus 4.8 --- routers/exam/templates.py | 3 +++ tests/test_exam_templates.py | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/routers/exam/templates.py b/routers/exam/templates.py index ae7b2f9..af39881 100644 --- a/routers/exam/templates.py +++ b/routers/exam/templates.py @@ -634,6 +634,9 @@ def _run_auto_map_job(job_id: str, ctx: ExamContext, template_id: str, pdf_bytes _set_auto_map_status(job_id, {"status": "running", "template_id": template_id}) try: rows = _run_auto_map_merge(ctx, template_id, pdf_bytes, source_label) + # Project to Neo4j like the born-digital fast path does — otherwise image-only papers (R3's + # primary target, routed here because they need OCR) never reach the graph after auto-map. + project_template_safe(template_id) _set_auto_map_status(job_id, {"status": "completed", "template_id": template_id, "counts": {k: len(v) for k, v in rows.items()}}) except Exception as exc: logger.exception(f"auto-map job failed for template {template_id}: {exc}") diff --git a/tests/test_exam_templates.py b/tests/test_exam_templates.py index 37e38d2..e316986 100644 --- a/tests/test_exam_templates.py +++ b/tests/test_exam_templates.py @@ -718,4 +718,16 @@ def test_auto_map_ocr_returns_job_id_and_status_completes(monkeypatch): body = status.json() assert body["status"] == "completed" assert body["counts"]["questions"] >= 2 + + +def test_auto_map_ocr_path_projects_to_neo4j(monkeypatch, _stub_projection): + # Image-only papers route through the async OCR job; regression: that path must project to Neo4j + # like the born-digital fast path, or the graph is never built for the primary target. + store = _template_with_source() + client, store = make_client(store=store) + _patch_auto_map(monkeypatch, store, fast=False) + resp = client.post("/api/exam/templates/t1/auto-map") + assert resp.status_code == 202 + # the BackgroundTask runs after the response under TestClient + assert "t1" in _stub_projection assert body["template"]["layout"]