generated from coulomb/repo-seed
feat(memory): add graph runtime import store
This commit is contained in:
153
tests/test_memory_graph_runtime.py
Normal file
153
tests/test_memory_graph_runtime.py
Normal file
@@ -0,0 +1,153 @@
|
||||
import pytest
|
||||
|
||||
from kontextual_engine import (
|
||||
Actor,
|
||||
ActorType,
|
||||
DuplicateResourceError,
|
||||
InMemoryMemoryGraphRepository,
|
||||
MemoryGraphImportResult,
|
||||
MemoryRuntimeService,
|
||||
OperationContext,
|
||||
ValidationError,
|
||||
)
|
||||
|
||||
|
||||
def test_markitect_memory_graph_import_preserves_contract_identity_and_spans() -> None:
|
||||
imported = MemoryGraphImportResult.from_markitect_contract(
|
||||
_graph_contract(),
|
||||
profile_contract=_profile_contract(),
|
||||
)
|
||||
second_import = MemoryGraphImportResult.from_markitect_contract(_graph_contract())
|
||||
|
||||
assert imported.graph_id == second_import.graph_id
|
||||
assert imported.contract_graph_id == "markitect-memory-decisions"
|
||||
assert imported.profile is not None
|
||||
assert imported.profile.contract_profile_id == "local-agent-memory"
|
||||
assert imported.nodes[0].contract_node_id == "decision.contract-boundary"
|
||||
assert imported.nodes[0].node_id == second_import.nodes[0].node_id
|
||||
assert imported.nodes[0].source_spans[0].path == "workplans/MKTT-WP-0016.md"
|
||||
assert imported.edges[0].source_node_id == imported.nodes[1].node_id
|
||||
assert imported.events[0].package_refs == ("memory:package:example",)
|
||||
|
||||
|
||||
def test_in_memory_memory_repository_persists_graph_and_append_only_events() -> None:
|
||||
repo = InMemoryMemoryGraphRepository()
|
||||
imported = MemoryGraphImportResult.from_markitect_contract(_graph_contract())
|
||||
|
||||
for node in imported.nodes:
|
||||
repo.save_memory_node(node)
|
||||
repo.save_memory_edge(imported.edges[0])
|
||||
repo.append_memory_event(imported.events[0])
|
||||
|
||||
assert repo.list_memory_nodes(graph_id=imported.graph_id, kind="decision") == [imported.nodes[0]]
|
||||
assert repo.list_memory_edges(source_node_id=imported.nodes[1].node_id) == [imported.edges[0]]
|
||||
assert repo.list_memory_events(graph_id=imported.graph_id, kind="recorded") == [imported.events[0]]
|
||||
with pytest.raises(DuplicateResourceError):
|
||||
repo.append_memory_event(imported.events[0])
|
||||
|
||||
|
||||
def test_memory_runtime_service_imports_contracts_and_reports_audit_context() -> None:
|
||||
repo = InMemoryMemoryGraphRepository()
|
||||
service = MemoryRuntimeService(repo)
|
||||
actor = Actor.create(ActorType.AI_AGENT, actor_id="agent-codex", display_name="Codex")
|
||||
context = OperationContext.create(actor, correlation_id="corr-memory")
|
||||
|
||||
summary = service.import_markitect_graph(
|
||||
_graph_contract(),
|
||||
profile_contract=_profile_contract(),
|
||||
context=context,
|
||||
)
|
||||
|
||||
assert summary.imported_nodes == 2
|
||||
assert summary.imported_edges == 1
|
||||
assert summary.appended_events == 1
|
||||
assert summary.audit_event is not None
|
||||
assert summary.audit_event.actor_id == "agent-codex"
|
||||
assert summary.audit_event.correlation_id == "corr-memory"
|
||||
assert repo.get_memory_profile(summary.profile_id).memory_kinds == (
|
||||
"reasoning",
|
||||
"knowledge",
|
||||
"package",
|
||||
)
|
||||
|
||||
|
||||
def test_memory_runtime_service_rejects_invalid_edge_contracts() -> None:
|
||||
repo = InMemoryMemoryGraphRepository()
|
||||
service = MemoryRuntimeService(repo)
|
||||
graph = _graph_contract()
|
||||
graph["edges"][0]["target"] = "missing-node"
|
||||
|
||||
with pytest.raises(ValidationError) as exc:
|
||||
service.import_markitect_graph(graph)
|
||||
|
||||
assert "unknown node" in str(exc.value)
|
||||
|
||||
|
||||
def _profile_contract() -> dict:
|
||||
return {
|
||||
"schema_version": "markitect.memory.profile.v1",
|
||||
"id": "local-agent-memory",
|
||||
"title": "Local Agent Memory",
|
||||
"intent": "Runtime import fixture.",
|
||||
"memory_kinds": ["reasoning", "knowledge", "package"],
|
||||
"stores": {
|
||||
"reasoning": "local-event-log",
|
||||
"knowledge": "local-graph-store",
|
||||
"package": "markitect-context-registry",
|
||||
},
|
||||
"activation": {"max_items": 6, "max_tokens": 1800},
|
||||
"policy": {"required_labels": ["public"]},
|
||||
}
|
||||
|
||||
|
||||
def _graph_contract() -> dict:
|
||||
return {
|
||||
"schema_version": "markitect.memory.graph.v1",
|
||||
"id": "markitect-memory-decisions",
|
||||
"title": "Markitect Memory Decisions",
|
||||
"intent": "Preserve memory boundary decisions for runtime import.",
|
||||
"namespace": {"project": "markitect-tool", "task": "MKTT-WP-0016"},
|
||||
"nodes": [
|
||||
{
|
||||
"id": "decision.contract-boundary",
|
||||
"kind": "decision",
|
||||
"text": "Markitect compiles memory graph selections into context packages.",
|
||||
"source_spans": [
|
||||
{
|
||||
"path": "workplans/MKTT-WP-0016.md",
|
||||
"unit_kind": "section",
|
||||
"selector": "tasks[id=P16.5]",
|
||||
"engine": "selector",
|
||||
}
|
||||
],
|
||||
"metadata": {"title": "Contract boundary decision"},
|
||||
},
|
||||
{
|
||||
"id": "constraint.no-runtime-services",
|
||||
"kind": "constraint",
|
||||
"text": "Runtime persistence belongs in kontextual-engine.",
|
||||
"policy": {"labels": ["public"]},
|
||||
},
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "edge.boundary-support",
|
||||
"kind": "supports",
|
||||
"source": "constraint.no-runtime-services",
|
||||
"target": "decision.contract-boundary",
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"id": "event.initial-contract",
|
||||
"kind": "recorded",
|
||||
"timestamp": "2026-05-15T00:00:00Z",
|
||||
"actor": "agent-codex",
|
||||
"task": "KONT-WP-0017",
|
||||
"package_refs": ["memory:package:example"],
|
||||
"node_updates": [
|
||||
{"node_id": "decision.contract-boundary", "operation": "import"}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
Reference in New Issue
Block a user