generated from coulomb/repo-seed
Implement live-shaped readiness workplan
This commit is contained in:
102
tests/fixtures/public-api-snapshot.json
vendored
Normal file
102
tests/fixtures/public-api-snapshot.json
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"exports": [
|
||||
"ADAPTER_PACK_MANIFEST_SCHEMA",
|
||||
"ActivationPlan",
|
||||
"Diagnostic",
|
||||
"EVALUATION_REPORT_SCHEMA",
|
||||
"ExternalAdapterPack",
|
||||
"FakeExternalEventLog",
|
||||
"FakeExternalGraphStore",
|
||||
"FakeExternalPolicyGateway",
|
||||
"FakeExternalSemanticIndex",
|
||||
"FakeKontextualRuntimeRegistry",
|
||||
"FakeMarkitectPackageCompiler",
|
||||
"FakeTelemetryAuditSink",
|
||||
"LifecycleAction",
|
||||
"LifecycleActionKind",
|
||||
"LifecycleRuleConfig",
|
||||
"LifecycleState",
|
||||
"LiveShapedKontextualEventLog",
|
||||
"LiveShapedKontextualGraphStore",
|
||||
"LiveShapedKontextualRuntimeRegistry",
|
||||
"LiveShapedMarkitectPackageCompiler",
|
||||
"LiveShapedPermissionSemanticIndex",
|
||||
"LiveShapedPolicyGateway",
|
||||
"LiveShapedTelemetryAuditSink",
|
||||
"LocalMarkitectValidator",
|
||||
"LocalServiceRunner",
|
||||
"MARKITECT_PACKAGE_REQUEST_SCHEMA",
|
||||
"MARKITECT_PACKAGE_RESPONSE_SCHEMA",
|
||||
"MemoryEdge",
|
||||
"MemoryEvent",
|
||||
"MemoryGraph",
|
||||
"MemoryKind",
|
||||
"MemoryNode",
|
||||
"MemoryOperation",
|
||||
"MemoryPath",
|
||||
"MemoryPathState",
|
||||
"MemoryPhase",
|
||||
"OptionalMarkitectValidator",
|
||||
"POLICY_OPERATION_POINTS",
|
||||
"PhaseMemoryRuntime",
|
||||
"PhaseTransitionRule",
|
||||
"PolicyDecision",
|
||||
"ProfileExecutionPlan",
|
||||
"ProfileIntent",
|
||||
"READINESS_REPORT_SCHEMA",
|
||||
"RetentionRule",
|
||||
"ReviewDecision",
|
||||
"ReviewRecord",
|
||||
"RuntimeAdapterBundle",
|
||||
"RuntimeConfig",
|
||||
"SERVICE_BINDING_SCHEMA",
|
||||
"ServiceBinding",
|
||||
"ServiceResponse",
|
||||
"WordCountTokenEstimator",
|
||||
"abandon_path",
|
||||
"activation_quality_report",
|
||||
"adapter_pack_manifest",
|
||||
"branch_path",
|
||||
"compact_path",
|
||||
"create_path",
|
||||
"evaluation_threshold_report",
|
||||
"fake_external_adapter_pack",
|
||||
"fake_external_runtime_config",
|
||||
"graph_from_markitect",
|
||||
"health_report",
|
||||
"live_shaped_adapter_pack",
|
||||
"make_review_record",
|
||||
"merge_path",
|
||||
"package_request_from_selection",
|
||||
"package_response_envelope",
|
||||
"path_event",
|
||||
"plan_activation",
|
||||
"plan_compaction",
|
||||
"plan_lifecycle_from_profile",
|
||||
"plan_neighborhood_activation",
|
||||
"plan_phase_transition",
|
||||
"plan_phase_transitions_from_rules",
|
||||
"plan_profile_execution",
|
||||
"plan_refresh",
|
||||
"plan_retention",
|
||||
"plan_retention_from_rules",
|
||||
"profile_from_markitect",
|
||||
"resolve_runtime_adapters",
|
||||
"retrieve_graph_neighborhood",
|
||||
"runtime_from_config",
|
||||
"select_event_path",
|
||||
"service_binding_from_config",
|
||||
"service_contracts",
|
||||
"validate_adapter_pack_manifest"
|
||||
],
|
||||
"service_operations": [
|
||||
"audit.query",
|
||||
"graph.activation.plan",
|
||||
"graph.import",
|
||||
"graph.lifecycle.plan",
|
||||
"health.check",
|
||||
"lifecycle.apply",
|
||||
"package.compile",
|
||||
"profile.plan"
|
||||
]
|
||||
}
|
||||
72
tests/test_audit_operations.py
Normal file
72
tests/test_audit_operations.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from phase_memory.lifecycle import plan_compaction
|
||||
from phase_memory.models import MemoryNode
|
||||
from phase_memory.runtime import PhaseMemoryRuntime
|
||||
|
||||
|
||||
def test_audit_export_traces_policy_denial_package_compile_and_review_apply() -> None:
|
||||
runtime = PhaseMemoryRuntime()
|
||||
graph = {
|
||||
"schema_version": "markitect.memory.graph.v1",
|
||||
"id": "audit.graph",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "node.public",
|
||||
"kind": "knowledge",
|
||||
"text": "Public node.",
|
||||
"policy": {"labels": ["public"], "trust_zone": "local"},
|
||||
},
|
||||
{
|
||||
"id": "node.secret",
|
||||
"kind": "knowledge",
|
||||
"text": "Secret node.",
|
||||
"policy": {"labels": ["restricted"], "secret": True, "trust_zone": "local"},
|
||||
},
|
||||
],
|
||||
"edges": [],
|
||||
"events": [],
|
||||
}
|
||||
|
||||
activation = runtime.plan_activation(
|
||||
graph,
|
||||
max_items=3,
|
||||
max_tokens=30,
|
||||
policy_context={"denied_labels": ["restricted"], "secrets_allowed": False, "trust_zone": "local"},
|
||||
)
|
||||
runtime.compile_package(activation["data"]["package_request"]["selection"])
|
||||
node = runtime.graph_store.save_node(MemoryNode("audit.review", "episode", "Review text"))
|
||||
compact = plan_compaction([node])
|
||||
runtime.apply_lifecycle_actions([compact])
|
||||
runtime.apply_lifecycle_actions([compact], approval_marker="review:audit")
|
||||
|
||||
export = runtime.export_audit_events()
|
||||
operations = [event["operation"] for event in export["batch"]["events"]]
|
||||
|
||||
assert export["valid"] is True
|
||||
assert "graph.activation.plan" in operations
|
||||
assert "package.compile" in operations
|
||||
assert operations.count("lifecycle.apply") == 2
|
||||
assert activation["data"]["policy_denials"][0]["id"] == "node.secret"
|
||||
|
||||
|
||||
def test_audit_retention_plan_identifies_eligible_records() -> None:
|
||||
runtime = PhaseMemoryRuntime()
|
||||
runtime.audit_sink.record(
|
||||
{
|
||||
"schema_version": "phase_memory.audit.event.v1",
|
||||
"operation_id": "op:old",
|
||||
"operation": "manual",
|
||||
"timestamp": "2026-01-01T00:00:00+00:00",
|
||||
"subject": {"kind": "audit_events", "id": "old"},
|
||||
"source": {"ref": "test"},
|
||||
"dry_run": True,
|
||||
"allowed": True,
|
||||
}
|
||||
)
|
||||
|
||||
plan = runtime.audit_retention_plan(retention_days=30, now=datetime(2026, 5, 19, tzinfo=timezone.utc))
|
||||
|
||||
assert plan["valid"] is True
|
||||
assert plan["plan"]["eligible_operation_ids"] == ["op:old"]
|
||||
assert plan["plan"]["eligible_count"] == 1
|
||||
@@ -4,6 +4,7 @@ from pathlib import Path
|
||||
|
||||
from phase_memory.adapters import InMemorySemanticIndex
|
||||
from phase_memory.contracts import graph_from_markitect
|
||||
from phase_memory.evaluation import EVALUATION_REPORT_SCHEMA, evaluation_threshold_report
|
||||
from phase_memory.models import ActivationPlan, MemoryPath
|
||||
from phase_memory.retrieval import activation_quality_report, select_event_path
|
||||
from phase_memory.runtime import PhaseMemoryRuntime
|
||||
@@ -85,6 +86,22 @@ def test_budget_path_and_semantic_hint_scenario_meets_quality_thresholds() -> No
|
||||
assert report["explanation_coverage"] == 1.0
|
||||
|
||||
|
||||
def test_evaluation_threshold_report_summarizes_all_scenarios() -> None:
|
||||
data = json.loads((FIXTURES / "evaluation-scenarios.json").read_text(encoding="utf-8"))
|
||||
|
||||
report = evaluation_threshold_report(data)
|
||||
|
||||
assert report["schema_version"] == EVALUATION_REPORT_SCHEMA
|
||||
assert report["valid"] is True
|
||||
assert report["metrics"]["scenario_count"] == 3
|
||||
assert report["metrics"]["policy_denial_count"] == 1
|
||||
assert report["metrics"]["lifecycle_action_count"] >= 3
|
||||
assert report["metrics"]["path_event_count"] == 1
|
||||
assert report["metrics"]["semantic_hit_count"] == 1
|
||||
assert report["metrics"]["budget_omission_count"] == 1
|
||||
assert report["diagnostics"] == []
|
||||
|
||||
|
||||
def _activation_plan(response):
|
||||
data = response["data"]["activation_plan"]
|
||||
return ActivationPlan(
|
||||
|
||||
@@ -7,6 +7,7 @@ from phase_memory.external_adapters import (
|
||||
adapter_pack_manifest,
|
||||
fake_external_adapter_pack,
|
||||
fake_external_runtime_config,
|
||||
live_shaped_adapter_pack,
|
||||
validate_adapter_pack_manifest,
|
||||
)
|
||||
from phase_memory.service import (
|
||||
@@ -64,6 +65,7 @@ def test_adapter_pack_manifest_reports_missing_capabilities() -> None:
|
||||
capabilities=tuple(capability for capability in pack.capabilities if capability != "telemetry.audit.fake"),
|
||||
ownership_boundaries=pack.ownership_boundaries,
|
||||
required_conformance=pack.required_conformance,
|
||||
capability_requirements=pack.capability_requirements,
|
||||
metadata=pack.metadata,
|
||||
)
|
||||
|
||||
@@ -100,3 +102,32 @@ def test_external_runtime_config_resolves_supplied_fake_pack() -> None:
|
||||
assert fetched["operation"] == "package.compile"
|
||||
assert report["ok"] is True
|
||||
assert report["adapters"]["package_compiler"] == "FakeMarkitectPackageCompiler"
|
||||
|
||||
|
||||
def test_live_shaped_adapter_pack_uses_same_manifest_and_conformance_contract() -> None:
|
||||
config = fake_external_runtime_config()
|
||||
pack = live_shaped_adapter_pack()
|
||||
manifest = adapter_pack_manifest(pack)
|
||||
bundle = resolve_runtime_adapters(config, external_adapters=pack.adapters)
|
||||
runtime = runtime_from_config(config, external_adapters=pack.adapters)
|
||||
|
||||
assert validate_adapter_pack_manifest(pack) == ()
|
||||
assert manifest["metadata"]["network_required"] is False
|
||||
assert manifest["adapters"]["package_compiler"]["required_capabilities"] == ["markitect.package.compile.live-shaped"]
|
||||
assert not [diagnostic for diagnostic in bundle.diagnostics if diagnostic.severity == "error"]
|
||||
|
||||
envelope = runtime.compile_package(
|
||||
{
|
||||
"schema_version": "markitect.memory.selection.v1",
|
||||
"id": "selection.live-shaped",
|
||||
"nodes": ["decision.boundary"],
|
||||
"events": [],
|
||||
}
|
||||
)
|
||||
registry_receipt = bundle.runtime_registry.publish_runtime_envelope(envelope)
|
||||
fetched = bundle.runtime_registry.fetch_runtime_envelope(registry_receipt["reference"])
|
||||
export = runtime.export_audit_events({"operation": "package.compile"})
|
||||
|
||||
assert envelope["data"]["package_response"]["package_ref"].startswith("markitect-live-shaped:")
|
||||
assert fetched["operation"] == "package.compile"
|
||||
assert export["batch"]["retention"]["mode"] == "live_shaped_telemetry"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from phase_memory.adapters import FileBackedMemoryGraphStore, JsonlAuditSink, JsonlMemoryEventLog
|
||||
from phase_memory.adapters import FileBackedMemoryGraphStore, JsonlAuditSink, JsonlMemoryEventLog, LOCAL_STORE_SCHEMA
|
||||
from phase_memory.lifecycle import plan_compaction, plan_retention
|
||||
from phase_memory.models import LifecycleAction, LifecycleActionKind, LifecycleState, MemoryEdge, MemoryEvent, MemoryNode
|
||||
from phase_memory.paths import abandon_path, branch_path, create_path, merge_path, path_event
|
||||
@@ -112,6 +112,55 @@ def test_file_backed_store_reports_migration_needs_and_uses_atomic_json_writes(t
|
||||
assert not list(tmp_path.rglob("*.tmp"))
|
||||
|
||||
|
||||
def test_local_store_migration_apply_updates_metadata_and_audits(tmp_path) -> None:
|
||||
store = FileBackedMemoryGraphStore(tmp_path)
|
||||
runtime = PhaseMemoryRuntime(graph_store=store, event_log=JsonlMemoryEventLog(tmp_path / "events.jsonl"))
|
||||
(tmp_path / "phase-memory.json").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"schema_version": "phase_memory.local_store.v0",
|
||||
"planned_migrations": ["v0-to-v1"],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
planned = runtime.plan_store_migration(source_ref=str(tmp_path))
|
||||
applied = runtime.apply_store_migration(planned["data"]["migration_plan"], actor="pytest", source_ref=str(tmp_path))
|
||||
metadata = store.metadata()
|
||||
audit = runtime.query_audit({"operation": "store.migration.apply", "dry_run": False})
|
||||
|
||||
assert planned["valid"] is True
|
||||
assert [action["action"] for action in planned["data"]["migration_plan"]["actions"]] == [
|
||||
"set_schema_version",
|
||||
"complete_planned_migration",
|
||||
]
|
||||
assert applied["valid"] is True
|
||||
assert applied["data"]["migration_result"]["changed"] is True
|
||||
assert metadata["schema_version"] == LOCAL_STORE_SCHEMA
|
||||
assert metadata["completed_migrations"] == ["v0-to-v1"]
|
||||
assert metadata["last_migration"]["actor"] == "pytest"
|
||||
assert audit["count"] == 1
|
||||
|
||||
|
||||
def test_local_store_migration_noop_and_corrupt_metadata_paths(tmp_path) -> None:
|
||||
store = FileBackedMemoryGraphStore(tmp_path)
|
||||
runtime = PhaseMemoryRuntime(graph_store=store, event_log=JsonlMemoryEventLog(tmp_path / "events.jsonl"))
|
||||
|
||||
noop = runtime.apply_store_migration(source_ref=str(tmp_path))
|
||||
assert noop["valid"] is True
|
||||
assert noop["data"]["migration_result"]["changed"] is False
|
||||
|
||||
(tmp_path / "phase-memory.json").write_text("{not-json}\n", encoding="utf-8")
|
||||
planned = runtime.plan_store_migration(source_ref=str(tmp_path))
|
||||
failed = runtime.apply_store_migration(source_ref=str(tmp_path))
|
||||
|
||||
assert planned["valid"] is False
|
||||
assert planned["diagnostics"][0]["code"] == "corrupt_store_metadata"
|
||||
assert failed["valid"] is False
|
||||
assert failed["data"]["migration_result"]["applied"] is False
|
||||
|
||||
|
||||
def test_repair_diagnostics_distinguish_corrupt_store_records(tmp_path) -> None:
|
||||
store = FileBackedMemoryGraphStore(tmp_path)
|
||||
runtime = PhaseMemoryRuntime(graph_store=store, event_log=JsonlMemoryEventLog(tmp_path / "events.jsonl"))
|
||||
|
||||
21
tests/test_public_api.py
Normal file
21
tests/test_public_api.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import phase_memory
|
||||
from phase_memory.service import LocalServiceRunner, SERVICE_OPERATIONS, service_contracts
|
||||
|
||||
|
||||
FIXTURES = Path(__file__).parent / "fixtures"
|
||||
|
||||
|
||||
def test_public_api_snapshot_is_explicit() -> None:
|
||||
snapshot = json.loads((FIXTURES / "public-api-snapshot.json").read_text(encoding="utf-8"))
|
||||
|
||||
assert sorted(phase_memory.__all__) == snapshot["exports"]
|
||||
assert sorted(SERVICE_OPERATIONS) == snapshot["service_operations"]
|
||||
|
||||
|
||||
def test_service_contract_catalog_matches_local_runner_supported_operations() -> None:
|
||||
declared = set(service_contracts()["operations"])
|
||||
|
||||
assert set(LocalServiceRunner.supported_operations()) == declared
|
||||
58
tests/test_service_binding.py
Normal file
58
tests/test_service_binding.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import json
|
||||
from io import BytesIO
|
||||
|
||||
from phase_memory import LocalServiceRunner, ServiceBinding
|
||||
from phase_memory.service_binding import READINESS_REPORT_SCHEMA
|
||||
|
||||
|
||||
def test_service_binding_exposes_health_readiness_and_contracts_without_listener() -> None:
|
||||
binding = ServiceBinding(LocalServiceRunner())
|
||||
|
||||
health = binding.route("GET", "/health")
|
||||
ready = binding.route("GET", "/ready")
|
||||
contracts = binding.route("GET", "/contracts")
|
||||
|
||||
assert health.status == 200
|
||||
assert ready.status == 200
|
||||
assert ready.body["schema_version"] == READINESS_REPORT_SCHEMA
|
||||
assert ready.body["unsupported_operations"] == []
|
||||
assert "package.compile" in contracts.body["operations"]
|
||||
|
||||
|
||||
def test_service_binding_dispatches_operation_payloads() -> None:
|
||||
binding = ServiceBinding(LocalServiceRunner())
|
||||
selection = {
|
||||
"schema_version": "markitect.memory.selection.v1",
|
||||
"id": "binding.selection",
|
||||
"nodes": [],
|
||||
"events": [],
|
||||
}
|
||||
|
||||
response = binding.route("POST", "/operations/package.compile", {"selection": selection})
|
||||
|
||||
assert response.status == 200
|
||||
assert response.body["operation"] == "package.compile"
|
||||
assert response.body["data"]["package_response"]["package_ref"] == "package:binding.selection"
|
||||
|
||||
|
||||
def test_service_binding_wsgi_adapter_is_callable_without_starting_server() -> None:
|
||||
binding = ServiceBinding(LocalServiceRunner())
|
||||
app = binding.as_wsgi_app()
|
||||
statuses: list[str] = []
|
||||
headers: list[list[tuple[str, str]]] = []
|
||||
|
||||
payload = json.dumps({"operation": "health.check", "payload": {}}).encode("utf-8")
|
||||
result = app(
|
||||
{
|
||||
"REQUEST_METHOD": "POST",
|
||||
"PATH_INFO": "/operations",
|
||||
"CONTENT_LENGTH": str(len(payload)),
|
||||
"wsgi.input": BytesIO(payload),
|
||||
},
|
||||
lambda status, response_headers: (statuses.append(status), headers.append(response_headers)),
|
||||
)
|
||||
|
||||
body = json.loads(b"".join(result).decode("utf-8"))
|
||||
assert statuses == ["200 OK"]
|
||||
assert body["schema_version"] == "phase_memory.health.report.v1"
|
||||
assert ("content-type", "application/json") in headers[0]
|
||||
Reference in New Issue
Block a user