generated from coulomb/repo-seed
feat(memory): add lifecycle operations
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user