generated from coulomb/repo-seed
feat(memory): add agent safe APIs
This commit is contained in:
@@ -8,10 +8,13 @@ from kontextual_engine import (
|
||||
LifecycleState,
|
||||
MemoryCompactionRequest,
|
||||
MemoryGraphImportResult,
|
||||
MemoryNodeUpdateInstruction,
|
||||
MemoryPackageExportRequest,
|
||||
MemoryRefreshRequest,
|
||||
MemoryRetentionRequest,
|
||||
MemoryQueryRequest,
|
||||
MemoryRuntimeService,
|
||||
MemoryUpdateRequest,
|
||||
OperationContext,
|
||||
PolicyDecision,
|
||||
ValidationError,
|
||||
@@ -197,6 +200,89 @@ def test_memory_compaction_creates_summary_preserves_spans_and_retires_sources()
|
||||
assert {node.lifecycle for node in source_nodes} == {LifecycleState.RETIRED}
|
||||
|
||||
|
||||
def test_agent_safe_memory_update_plans_dry_run_and_requires_review_before_write() -> None:
|
||||
repo = InMemoryMemoryGraphRepository()
|
||||
service = MemoryRuntimeService(repo)
|
||||
summary = service.import_markitect_graph(_graph_contract())
|
||||
context = operation_context()
|
||||
|
||||
plan = service.plan_memory_update(
|
||||
MemoryUpdateRequest(
|
||||
graph_id=summary.graph_id,
|
||||
instructions=(
|
||||
MemoryNodeUpdateInstruction(
|
||||
contract_node_id="claim.agent-safe-update",
|
||||
kind="claim",
|
||||
text="Agent-safe update is planned before durable write.",
|
||||
source_spans=(
|
||||
{
|
||||
"path": "docs/memory-agent-safe.md",
|
||||
"unit_kind": "section",
|
||||
"selector": "sections[heading=Agent safe]",
|
||||
"engine": "selector",
|
||||
},
|
||||
),
|
||||
policy={"labels": ["public"]},
|
||||
),
|
||||
),
|
||||
require_review=True,
|
||||
reason="capture implementation decision",
|
||||
),
|
||||
context,
|
||||
)
|
||||
pending = service.apply_memory_update(plan, context)
|
||||
|
||||
assert plan.success is True
|
||||
assert plan.dry_run is True
|
||||
assert plan.review_required is True
|
||||
assert plan.planned_updates[0].action == "create_node"
|
||||
assert plan.planned_updates[0].source_explanation[0]["path"] == "docs/memory-agent-safe.md"
|
||||
assert pending.success is False
|
||||
assert pending.review_required is True
|
||||
assert repo.list_memory_nodes(graph_id=summary.graph_id, kind="claim") == []
|
||||
approved = service.apply_memory_update(plan, context, review_decision="approved")
|
||||
assert approved.success is True
|
||||
assert approved.appended_events[0].kind == "updated"
|
||||
assert repo.list_memory_nodes(graph_id=summary.graph_id, kind="claim")[0].contract_node_id == (
|
||||
"claim.agent-safe-update"
|
||||
)
|
||||
|
||||
|
||||
def test_memory_package_export_emits_markitect_context_package_inputs_without_denied_content() -> None:
|
||||
repo = InMemoryMemoryGraphRepository()
|
||||
service = MemoryRuntimeService(repo, policy_gateway=DenyInternalMemoryPolicy())
|
||||
graph = _graph_contract()
|
||||
graph["nodes"].append(
|
||||
{
|
||||
"id": "claim.internal-secret",
|
||||
"kind": "claim",
|
||||
"text": "secret memory text must not leak",
|
||||
"policy": {"labels": ["internal"]},
|
||||
}
|
||||
)
|
||||
summary = service.import_markitect_graph(graph)
|
||||
|
||||
export = service.export_context_package_inputs(
|
||||
MemoryPackageExportRequest(
|
||||
query=MemoryQueryRequest(graph_id=summary.graph_id, text_contains="memory"),
|
||||
title="Memory Package Input",
|
||||
intent="Export allowed runtime memories for Markitect packaging.",
|
||||
namespace={"project": "kontextual-engine"},
|
||||
budget={"max_items": 3},
|
||||
),
|
||||
operation_context(),
|
||||
)
|
||||
|
||||
assert export.success is True
|
||||
assert export.package_input["schema_version"] == "markitect.context-package.input.v1"
|
||||
assert export.package_input["retrieval_recipes"][0]["kind"] == "memory-runtime-query"
|
||||
assert export.package_input["items"][0]["source"]["path"] == "workplans/MKTT-WP-0016.md"
|
||||
assert export.package_input["metadata"]["permission_filtered_count"] == 1
|
||||
assert "secret memory text must not leak" not in str(export.to_dict())
|
||||
assert export.audit_event is not None
|
||||
assert export.audit_event.operation == "memory.package.export"
|
||||
|
||||
|
||||
def test_memory_runtime_service_rejects_invalid_edge_contracts() -> None:
|
||||
repo = InMemoryMemoryGraphRepository()
|
||||
service = MemoryRuntimeService(repo)
|
||||
|
||||
Reference in New Issue
Block a user