From 28beab0df76849269a0e026886171f44bce894e2 Mon Sep 17 00:00:00 2001 From: ogt Date: Thu, 9 Jul 2026 17:47:29 +0800 Subject: [PATCH] fix(crawler): relocate pixelrag receipt file paths --- .../pixelrag_crawler_integration_service.py | 28 ++++++++++++++++++- ...st_pixelrag_crawler_integration_service.py | 23 +++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/services/pixelrag_crawler_integration_service.py b/services/pixelrag_crawler_integration_service.py index 31e3d9e..647e284 100644 --- a/services/pixelrag_crawler_integration_service.py +++ b/services/pixelrag_crawler_integration_service.py @@ -538,6 +538,32 @@ def _receipt_candidates( return sorted(search_root.glob(pattern), key=lambda path: path.stat().st_mtime, reverse=True) +def _portable_receipt_file_path(receipt_path: Path, raw_path: Any, kind: Any) -> Path: + path = Path(str(raw_path or "")) + if path.exists(): + return path + receipt_dir = receipt_path.parent + basename = path.name + if not basename: + return path + if kind == "tile": + tile_path = receipt_dir / "tiles" / basename + if tile_path.exists(): + return tile_path + sibling_path = receipt_dir / basename + if sibling_path.exists(): + return sibling_path + parts = path.parts + if receipt_dir.name in parts: + index = parts.index(receipt_dir.name) + suffix = parts[index + 1:] + if suffix: + relocated = receipt_dir.joinpath(*suffix) + if relocated.exists(): + return relocated + return path + + def build_pixelrag_visual_evidence_readback( *, artifact_root: str | Path | None = None, @@ -594,7 +620,7 @@ def build_pixelrag_visual_evidence_readback( missing_file_count = 0 tile_file_count = 0 for item in files: - path = Path(str(item.get("path") or "")) + path = _portable_receipt_file_path(latest_path, item.get("path"), item.get("kind")) exists = path.exists() if not exists: missing_file_count += 1 diff --git a/tests/test_pixelrag_crawler_integration_service.py b/tests/test_pixelrag_crawler_integration_service.py index 6491aa0..f2a386c 100644 --- a/tests/test_pixelrag_crawler_integration_service.py +++ b/tests/test_pixelrag_crawler_integration_service.py @@ -314,6 +314,29 @@ def test_pixelrag_visual_evidence_readback_warns_when_missing(tmp_path): assert payload["next_machine_action"] == "run_pixelrag_visual_capture_worker" +def test_pixelrag_visual_evidence_readback_relocates_copied_receipt_paths(tmp_path): + from services.pixelrag_crawler_integration_service import build_pixelrag_visual_evidence_readback + + receipt_path = _write_capture_receipt(tmp_path, platform="pchome", manifest_id="copied") + receipt = json.loads(receipt_path.read_text(encoding="utf-8")) + receipt["files"] = [ + {"kind": "fullpage_screenshot", "path": "/host/runtime/fullpage.png"}, + {"kind": "tile", "path": "/host/runtime/tiles/tile_000.png"}, + {"kind": "tile", "path": "/host/runtime/tiles/tile_001.png"}, + ] + receipt_path.write_text(json.dumps(receipt), encoding="utf-8") + + payload = build_pixelrag_visual_evidence_readback( + artifact_root=tmp_path, + platform="pchome", + manifest_id="copied", + ) + + assert payload["status"] == "ok" + assert payload["summary"]["missing_file_count"] == 0 + assert all(item["exists"] for item in payload["latest_receipt"]["files"]) + + def test_pixelrag_visual_evidence_readback_route_returns_payload(tmp_path, monkeypatch): from flask import Flask from routes import system_public_routes as routes