diff --git a/semantica/context/context_graph.py b/semantica/context/context_graph.py index f64db90c..065041a3 100644 --- a/semantica/context/context_graph.py +++ b/semantica/context/context_graph.py @@ -1483,6 +1483,8 @@ class ContextGraph: confidence: float = 0.5, entities: Optional[List[str]] = None, decision_maker: Optional[str] = "system", + valid_from=None, + valid_until=None, **kwargs, ) -> str: """ @@ -1506,6 +1508,8 @@ class ContextGraph: confidence: Confidence score (0.0–1.0) entities: Related entity labels decision_maker: Who made the decision + valid_from: Start of validity window (ISO string or datetime) + valid_until: End of validity window (ISO string or datetime) **kwargs: Extra metadata stored on the decision node Returns: @@ -1513,6 +1517,15 @@ class ContextGraph: """ from .decision_models import Decision + if decision is not None and ( + any(v is not None for v in ( + category, scenario, reasoning, outcome, entities, valid_from, valid_until, + )) or kwargs + ): + raise ValueError( + "Pass either a Decision object or keyword arguments, not both." + ) + if decision is None: # Build from kwargs — delegate to record_decision which handles ID gen return self.record_decision( @@ -1523,6 +1536,8 @@ class ContextGraph: confidence=confidence, entities=entities, decision_maker=decision_maker, + valid_from=valid_from, + valid_until=valid_until, metadata=kwargs, ) diff --git a/tests/test_395_temporal_semantics_comprehensive.py b/tests/test_395_temporal_semantics_comprehensive.py index 1b1bd78a..cb05f8af 100644 --- a/tests/test_395_temporal_semantics_comprehensive.py +++ b/tests/test_395_temporal_semantics_comprehensive.py @@ -17,7 +17,6 @@ Already covered separately: from __future__ import annotations -import time from datetime import datetime, timezone from unittest.mock import MagicMock @@ -1062,6 +1061,8 @@ class TestFindPrecedentsAsOf: # Bob's decision should be reachable; Alice's should not appear # (implementation may not filter on valid_from, just check it doesn't crash) assert isinstance(precedents, list) + assert "approve loan for Bob" in scenarios + assert "approve loan for Alice" not in scenarios def test_find_precedents_no_as_of_returns_list(self): self.graph.record_decision( diff --git a/tests/test_unreleased_changelog_comprehensive.py b/tests/test_unreleased_changelog_comprehensive.py index 25830f3c..71ec8076 100644 --- a/tests/test_unreleased_changelog_comprehensive.py +++ b/tests/test_unreleased_changelog_comprehensive.py @@ -19,7 +19,6 @@ Covers gaps not addressed by existing test files: from __future__ import annotations import threading -import time from datetime import datetime, timezone from unittest.mock import MagicMock, patch @@ -292,7 +291,7 @@ class TestNamedTagsAdditional: graph = ContextGraph() manager = TemporalVersionManager() graph.add_node("n1", "entity") - snap = manager.create_snapshot( + manager.create_snapshot( graph.to_dict(), version_label="v1.0", author="user@example.com", @@ -873,7 +872,7 @@ class TestOllamaProviderBaseURLGap: ollama_mock.Client = MagicMock(return_value=MagicMock()) with patch.dict("sys.modules", {"ollama": ollama_mock}): from semantica.semantic_extract.providers import OllamaProvider - provider = OllamaProvider( + OllamaProvider( model_name="llama3", base_url="http://192.168.1.10:11434", )