From 20b5f7c0abdf212276146a05ac2735712f4831ce Mon Sep 17 00:00:00 2001 From: KaifAhmad1 Date: Wed, 18 Feb 2026 00:37:50 +0530 Subject: [PATCH] Fix execute_query wrapper handling in context queries --- semantica/context/causal_analyzer.py | 15 ++++- semantica/context/decision_query.py | 20 ++++++- tests/context/test_query_result_unwrap.py | 67 +++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 tests/context/test_query_result_unwrap.py diff --git a/semantica/context/causal_analyzer.py b/semantica/context/causal_analyzer.py index 8674d72d..de4753ea 100644 --- a/semantica/context/causal_analyzer.py +++ b/semantica/context/causal_analyzer.py @@ -131,6 +131,7 @@ class CausalChainAnalyzer: results = self.graph_store.execute_query(query, { "decision_id": decision_id }) + results = self._extract_records(results) decisions = [] for record in results: @@ -174,6 +175,7 @@ class CausalChainAnalyzer: results = self.graph_store.execute_query(query, { "decision_id": decision_id }) + results = self._extract_records(results) decisions = [] for record in results: @@ -218,6 +220,7 @@ class CausalChainAnalyzer: results = self.graph_store.execute_query(query, { "decision_id": decision_id }) + results = self._extract_records(results) decisions = [] for record in results: @@ -256,7 +259,7 @@ class CausalChainAnalyzer: ORDER BY loop_length """ - results = self.graph_store.execute_query(query) + results = self._extract_records(self.graph_store.execute_query(query)) loops = [] for record in results: @@ -329,6 +332,7 @@ class CausalChainAnalyzer: results = self.graph_store.execute_query(query, { "decision_id": decision_id }) + results = self._extract_records(results) root_decisions = [] for record in results: @@ -444,3 +448,12 @@ class CausalChainAnalyzer: node2vec_embedding=data.get("node2vec_embedding"), metadata=data.get("metadata", {}), ) + + def _extract_records(self, results: Any) -> List[Dict[str, Any]]: + """Normalize execute_query result shapes to a list of record maps.""" + if isinstance(results, dict): + records = results.get("records", []) + return records if isinstance(records, list) else [] + if isinstance(results, list): + return results + return [] diff --git a/semantica/context/decision_query.py b/semantica/context/decision_query.py index 610261d5..75b922fd 100644 --- a/semantica/context/decision_query.py +++ b/semantica/context/decision_query.py @@ -344,7 +344,7 @@ class DecisionQuery: query_parts.append("LIMIT $limit") query = " ".join(query_parts) - results = self.graph_store.execute_query(query, params) + results = self._extract_records(self.graph_store.execute_query(query, params)) decisions = [] for record in results: @@ -395,6 +395,7 @@ class DecisionQuery: "category": category, "limit": limit }) + results = self._extract_records(results) decisions = [] for record in results: @@ -433,6 +434,7 @@ class DecisionQuery: "entity_id": entity_id, "limit": limit }) + results = self._extract_records(results) decisions = [] for record in results: @@ -478,6 +480,7 @@ class DecisionQuery: "end": end, "limit": limit }) + results = self._extract_records(results) decisions = [] for record in results: @@ -526,6 +529,7 @@ class DecisionQuery: results = self.graph_store.execute_query(query, { "start_entity": start_entity }) + results = self._extract_records(results) decisions = [] for record in results: @@ -572,6 +576,7 @@ class DecisionQuery: results = self.graph_store.execute_query(query, { "decision_id": decision_id }) + results = self._extract_records(results) paths = [] for record in results: @@ -616,6 +621,7 @@ class DecisionQuery: LIMIT $limit """ results = self.graph_store.execute_query(query, {"limit": limit}) + results = self._extract_records(results) exceptions = [] for record in results: @@ -827,6 +833,7 @@ class DecisionQuery: results = self.graph_store.execute_query(query, { "decision_id": decision_id }) + results = self._extract_records(results) return {"nodes": results, "max_depth": max_depth} except Exception: @@ -879,10 +886,12 @@ class DecisionQuery: downstream_results = self.graph_store.execute_query(downstream_query, { "decision_id": decision_id }) + downstream_results = self._extract_records(downstream_results) upstream_results = self.graph_store.execute_query(upstream_query, { "decision_id": decision_id }) + upstream_results = self._extract_records(upstream_results) # Process results for record in downstream_results: @@ -976,3 +985,12 @@ class DecisionQuery: except Exception as e: self.logger.error(f"Failed to predict relationships: {e}") return [] + + def _extract_records(self, results: Any) -> List[Dict[str, Any]]: + """Normalize execute_query result shapes to a list of record maps.""" + if isinstance(results, dict): + records = results.get("records", []) + return records if isinstance(records, list) else [] + if isinstance(results, list): + return results + return [] diff --git a/tests/context/test_query_result_unwrap.py b/tests/context/test_query_result_unwrap.py new file mode 100644 index 00000000..c790b1f5 --- /dev/null +++ b/tests/context/test_query_result_unwrap.py @@ -0,0 +1,67 @@ +"""Regression tests for execute_query wrapper result handling.""" + +from datetime import datetime +from unittest.mock import Mock + +from semantica.context.causal_analyzer import CausalChainAnalyzer +from semantica.context.decision_query import DecisionQuery + + +def test_decision_query_unwraps_execute_query_records_wrapper(): + graph_store = Mock() + graph_store.execute_query.return_value = { + "success": True, + "records": [ + { + "d": { + "decision_id": "decision_001", + "category": "credit_approval", + "scenario": "Credit increase", + "reasoning": "Strong history", + "outcome": "approved", + "confidence": 0.9, + "timestamp": datetime.now().isoformat(), + "decision_maker": "agent", + } + } + ], + } + + query = DecisionQuery(graph_store=graph_store) + results = query.find_precedents_hybrid( + scenario="credit increase", category="credit_approval", limit=10 + ) + + assert len(results) == 1 + assert results[0].decision_id == "decision_001" + + +def test_causal_analyzer_unwraps_execute_query_records_wrapper(): + graph_store = Mock() + graph_store.execute_query.return_value = { + "success": True, + "records": [ + { + "end": { + "decision_id": "decision_002", + "category": "credit_approval", + "scenario": "Escalation", + "reasoning": "Policy exception", + "outcome": "approved", + "confidence": 0.8, + "timestamp": datetime.now().isoformat(), + "decision_maker": "agent", + }, + "distance": 1, + } + ], + } + + analyzer = CausalChainAnalyzer(graph_store=graph_store) + results = analyzer.get_causal_chain( + decision_id="decision_001", direction="downstream", max_depth=3 + ) + + assert len(results) == 1 + assert results[0].decision_id == "decision_002" + assert results[0].metadata.get("causal_distance") == 1