From fcbd4d7c8cb85e508d9b4637074f3145432ddcb0 Mon Sep 17 00:00:00 2001 From: welsberr Date: Mon, 27 Apr 2026 13:01:52 -0400 Subject: [PATCH] Add pack-ready GroundRecall query bundle export --- src/groundrecall/__init__.py | 2 ++ src/groundrecall/export.py | 25 +++++++++++++++++++++++++ tests/test_groundrecall_export.py | 18 +++++++++++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/groundrecall/__init__.py b/src/groundrecall/__init__.py index d26682f..0e853db 100644 --- a/src/groundrecall/__init__.py +++ b/src/groundrecall/__init__.py @@ -12,6 +12,7 @@ from .query import ( query_provenance, search_claims, ) +from .export import export_groundrecall_query_bundle from .store import GroundRecallStore __all__ = [ @@ -27,6 +28,7 @@ __all__ = [ "query_provenance", "search_claims", "build_query_bundle_for_concept", + "export_groundrecall_query_bundle", "build_query_parser", "query_main", "summarize_store", diff --git a/src/groundrecall/export.py b/src/groundrecall/export.py index 0188e52..dd7161e 100644 --- a/src/groundrecall/export.py +++ b/src/groundrecall/export.py @@ -92,11 +92,28 @@ def export_query_bundle( return payload +def export_groundrecall_query_bundle( + store_dir: str | Path, + concept_ref: str, + out_dir: str | Path, +) -> dict[str, Any]: + target = Path(out_dir) + target.mkdir(parents=True, exist_ok=True) + out_path = target / "groundrecall_query_bundle.json" + payload = export_query_bundle(store_dir, concept_ref, out_path) + return { + "concept_ref": concept_ref, + "bundle_path": str(out_path), + "bundle": payload, + } + + def export_canonical_bundle( store_dir: str | Path, out_dir: str | Path, concept_refs: list[str] | None = None, snapshot_id: str | None = None, + pack_ready_concept: str | None = None, ) -> dict[str, Any]: target = Path(out_dir) target.mkdir(parents=True, exist_ok=True) @@ -107,12 +124,18 @@ def export_canonical_bundle( bundle_path = target / f"query_bundle__{safe_name}.json" export_query_bundle(store_dir, concept_ref, bundle_path) query_bundle_paths.append(str(bundle_path)) + pack_ready_bundle = None + if pack_ready_concept: + pack_ready_bundle = export_groundrecall_query_bundle(store_dir, pack_ready_concept, target) manifest = json.loads((target / "export_manifest.json").read_text(encoding="utf-8")) manifest["query_bundles"] = query_bundle_paths + if pack_ready_bundle is not None: + manifest["groundrecall_query_bundle"] = pack_ready_bundle["bundle_path"] _write_json(target / "export_manifest.json", manifest) return { "canonical_outputs": outputs, "query_bundles": query_bundle_paths, + "groundrecall_query_bundle": pack_ready_bundle, } @@ -122,6 +145,7 @@ def build_parser() -> argparse.ArgumentParser: parser.add_argument("out_dir") parser.add_argument("--snapshot-id", default=None) parser.add_argument("--concept", action="append", default=[]) + parser.add_argument("--pack-ready-concept", default=None) return parser @@ -132,5 +156,6 @@ def main() -> None: out_dir=args.out_dir, concept_refs=list(args.concept or []), snapshot_id=args.snapshot_id, + pack_ready_concept=args.pack_ready_concept, ) print(json.dumps(payload, indent=2)) diff --git a/tests/test_groundrecall_export.py b/tests/test_groundrecall_export.py index 4166b8f..b9f480e 100644 --- a/tests/test_groundrecall_export.py +++ b/tests/test_groundrecall_export.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from pathlib import Path -from groundrecall.export import export_canonical_bundle, export_query_bundle +from groundrecall.export import export_canonical_bundle, export_groundrecall_query_bundle, export_query_bundle from groundrecall.models import ( ArtifactRecord, ClaimRecord, @@ -104,6 +104,7 @@ def test_export_canonical_bundle_writes_expected_files(tmp_path: Path) -> None: out_dir=out_dir, concept_refs=["channel-capacity"], snapshot_id="snap_export_001", + pack_ready_concept="channel-capacity", ) assert (out_dir / "groundrecall_snapshot.json").exists() @@ -113,6 +114,7 @@ def test_export_canonical_bundle_writes_expected_files(tmp_path: Path) -> None: assert (out_dir / "provenance_manifest.json").exists() assert (out_dir / "export_manifest.json").exists() assert (out_dir / "query_bundle__channel-capacity.json").exists() + assert (out_dir / "groundrecall_query_bundle.json").exists() snapshot = json.loads((out_dir / "groundrecall_snapshot.json").read_text(encoding="utf-8")) manifest = json.loads((out_dir / "export_manifest.json").read_text(encoding="utf-8")) @@ -120,8 +122,10 @@ def test_export_canonical_bundle_writes_expected_files(tmp_path: Path) -> None: assert snapshot["snapshot_id"] == "snap_export_001" assert manifest["export_kind"] == "canonical" assert len(manifest["query_bundles"]) == 1 + assert manifest["groundrecall_query_bundle"].endswith("groundrecall_query_bundle.json") assert claims[0]["claim_id"] == "clm_001" assert payload["query_bundles"] + assert payload["groundrecall_query_bundle"] is not None def test_export_query_bundle_is_assistant_neutral(tmp_path: Path) -> None: @@ -134,3 +138,15 @@ def test_export_query_bundle_is_assistant_neutral(tmp_path: Path) -> None: assert payload["bundle_kind"] == "groundrecall_query_bundle" forbidden = {"assistant", "codex", "claude", "prompt_text"} assert set(payload).isdisjoint(forbidden) + + +def test_export_groundrecall_query_bundle_uses_pack_ready_filename(tmp_path: Path) -> None: + store = GroundRecallStore(tmp_path / "groundrecall") + _seed_store(store) + + out_dir = tmp_path / "pack-ready" + payload = export_groundrecall_query_bundle(store.base_dir, "channel-capacity", out_dir) + + assert (out_dir / "groundrecall_query_bundle.json").exists() + assert payload["bundle_path"].endswith("groundrecall_query_bundle.json") + assert payload["bundle"]["bundle_kind"] == "groundrecall_query_bundle"