From d48ad29aa29403c8f91a32836f3affcc4a650211 Mon Sep 17 00:00:00 2001 From: welsberr Date: Mon, 27 Apr 2026 11:51:11 -0400 Subject: [PATCH] Expose review candidates in GroundRecall queries --- src/groundrecall/query.py | 9 +++++++++ tests/test_groundrecall_query.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/groundrecall/query.py b/src/groundrecall/query.py index a992b0f..a1c29e2 100644 --- a/src/groundrecall/query.py +++ b/src/groundrecall/query.py @@ -41,6 +41,7 @@ def query_concept(store_dir: str | Path, concept_ref: str) -> dict[str, Any] | N ] artifacts = {item.artifact_id: item for item in store.list_artifacts()} observations = {item.observation_id: item for item in store.list_observations()} + review_candidates = store.list_review_candidates() supporting_observations = [] for claim in claims: @@ -71,6 +72,12 @@ def query_concept(store_dir: str | Path, concept_ref: str) -> dict[str, Any] | N for artifact in artifacts.values() if artifact.artifact_id in set(concept.source_artifact_ids) ] + related_review_candidates = [ + item.model_dump() + for item in review_candidates + if item.candidate_id == concept.concept_id + or (item.candidate_type == "claim" and any(claim.claim_id == item.candidate_id for claim in claims)) + ] return { "query_type": "concept", @@ -80,6 +87,7 @@ def query_concept(store_dir: str | Path, concept_ref: str) -> dict[str, Any] | N "related_concepts": related_concepts, "supporting_observations": supporting_observations, "source_artifacts": source_artifacts, + "review_candidates": related_review_candidates, } @@ -156,6 +164,7 @@ def build_query_bundle_for_concept(store_dir: str | Path, concept_ref: str) -> d "relevant_claims": claims, "supporting_observations": payload["supporting_observations"], "related_concepts": payload["related_concepts"], + "review_candidates": payload["review_candidates"], "contradictions": contradictions, "supersessions": supersessions, "suggested_next_actions": [ diff --git a/tests/test_groundrecall_query.py b/tests/test_groundrecall_query.py index f405a5f..d2e5276 100644 --- a/tests/test_groundrecall_query.py +++ b/tests/test_groundrecall_query.py @@ -9,6 +9,7 @@ from groundrecall.models import ( ObservationRecord, ProvenanceRecord, RelationRecord, + ReviewCandidateRecord, ) from groundrecall.query import ( build_query_bundle_for_concept, @@ -102,6 +103,30 @@ def _seed_store(store: GroundRecallStore) -> None: current_status="promoted", ) ) + store.save_review_candidate( + ReviewCandidateRecord( + review_candidate_id="rq_concept_channel", + candidate_type="concept", + candidate_id="concept::channel-capacity", + triage_lane="conflict_resolution", + priority=12, + finding_codes=["bridge_concept"], + rationale="Channel Capacity | lane=conflict_resolution | priority=12 | graph=bridge_concept", + current_status="reviewed", + ) + ) + store.save_review_candidate( + ReviewCandidateRecord( + review_candidate_id="rq_claim_channel", + candidate_type="claim", + candidate_id="clm_001", + triage_lane="knowledge_capture", + priority=20, + finding_codes=["claim_missing_concept"], + rationale="Channel capacity bounds reliable communication rate. | lane=knowledge_capture | priority=20", + current_status="reviewed", + ) + ) def test_query_concept_returns_neighborhood_and_support(tmp_path: Path) -> None: @@ -115,6 +140,9 @@ def test_query_concept_returns_neighborhood_and_support(tmp_path: Path) -> None: assert len(payload["relations"]) == 1 assert any(item["concept_id"] == "concept::shannon-entropy" for item in payload["related_concepts"]) assert payload["supporting_observations"][0]["origin_path"] == "wiki/channel-capacity.md" + assert len(payload["review_candidates"]) == 2 + assert any(item["candidate_id"] == "concept::channel-capacity" for item in payload["review_candidates"]) + assert any("graph=bridge_concept" in item["rationale"] for item in payload["review_candidates"]) def test_search_claims_matches_text_and_concept_titles(tmp_path: Path) -> None: @@ -143,6 +171,7 @@ def test_build_query_bundle_for_concept_is_assistant_neutral(tmp_path: Path) -> assert payload is not None assert payload["bundle_kind"] == "groundrecall_query_bundle" assert payload["concept"]["concept_id"] == "concept::channel-capacity" + assert len(payload["review_candidates"]) == 2 assert isinstance(payload["suggested_next_actions"], list) forbidden = {"assistant", "codex", "claude", "prompt_text"} assert set(payload).isdisjoint(forbidden)