feat(memory): add lifecycle operations

This commit is contained in:
2026-05-15 09:30:46 +02:00
parent 876f97c288
commit 1be8019fa1
6 changed files with 710 additions and 2 deletions

View File

@@ -5,7 +5,11 @@ from kontextual_engine import (
ActorType,
DuplicateResourceError,
InMemoryMemoryGraphRepository,
LifecycleState,
MemoryCompactionRequest,
MemoryGraphImportResult,
MemoryRefreshRequest,
MemoryRetentionRequest,
MemoryQueryRequest,
MemoryRuntimeService,
OperationContext,
@@ -134,6 +138,65 @@ def test_memory_query_scope_policy_fail_closed_returns_empty_result() -> None:
assert result.audit_event.outcome.value == "denied"
def test_memory_retention_marks_stale_refresh_clears_and_delete_requests() -> None:
repo = InMemoryMemoryGraphRepository()
service = MemoryRuntimeService(repo)
summary = service.import_markitect_graph(_graph_contract())
context = operation_context()
stale = service.apply_retention(
MemoryRetentionRequest(graph_id=summary.graph_id, stale_after_days=0),
context,
)
stale_node = repo.get_memory_node(stale.updated_nodes[0].node_id)
refreshed = service.refresh_memory(
MemoryRefreshRequest(graph_id=summary.graph_id, node_ids=(stale_node.contract_node_id,)),
context,
)
delete_requested = service.apply_retention(
MemoryRetentionRequest(graph_id=summary.graph_id, delete_after_days=0),
context,
)
assert stale.operation == "memory.retention.apply"
assert stale.appended_events[0].kind == "retention"
assert stale_node.metadata["review_state"] == "review_required"
assert stale_node.freshness["stale"] is True
assert refreshed.appended_events[0].kind == "refreshed"
assert repo.get_memory_node(stale_node.node_id).freshness["stale"] is False
assert all(update.after_lifecycle == LifecycleState.DELETE_REQUESTED.value for update in delete_requested.updated_nodes)
assert delete_requested.appended_events[0].kind == "retention"
def test_memory_compaction_creates_summary_preserves_spans_and_retires_sources() -> None:
repo = InMemoryMemoryGraphRepository()
service = MemoryRuntimeService(repo)
summary = service.import_markitect_graph(_graph_contract())
compacted = service.compact_memory(
MemoryCompactionRequest(
graph_id=summary.graph_id,
node_ids=("decision.contract-boundary", "constraint.no-runtime-services"),
summary_contract_node_id="compaction.boundary-summary",
),
operation_context(),
)
summary_node = compacted.created_nodes[0]
assert compacted.operation == "memory.compact"
assert summary_node.contract_node_id == "compaction.boundary-summary"
assert summary_node.kind == "memory"
assert summary_node.source_spans[0].path == "workplans/MKTT-WP-0016.md"
assert "decision.contract-boundary" in summary_node.metadata["compaction"]["source_contract_node_ids"]
assert compacted.appended_events[0].kind == "compacted"
source_nodes = [
repo.get_memory_node(update.node_id)
for update in compacted.updated_nodes
if update.action == "compacted_retired"
]
assert {node.lifecycle for node in source_nodes} == {LifecycleState.RETIRED}
def test_memory_runtime_service_rejects_invalid_edge_contracts() -> None:
repo = InMemoryMemoryGraphRepository()
service = MemoryRuntimeService(repo)