Files
aios/tests/test_convergence_contracts.py
T

158 lines
5.1 KiB
Python

from __future__ import annotations
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "active-runtime" / "app"))
from aios_convergence_contracts import (
AcceptanceCriterion,
AcceptanceDecision,
AcceptanceInvariant,
AcceptanceVector,
ContinuationManifest,
ContinuationStopReason,
ConvergenceContractError,
DesiredState,
EvidenceState,
ObservedHealth,
ObservedState,
ReconciliationState,
StateOwnership,
evaluate_acceptance,
ownership_index,
plan_reconciliation,
validate_state_ownership,
)
def test_acceptance_never_promotes_required_unknown():
vector = AcceptanceVector(
subject_type="goal",
subject_id="goal-1",
subject_revision=1,
criteria=(
AcceptanceCriterion(
criterion_id="runtime",
required=True,
state=EvidenceState.UNKNOWN,
verifier_id="runtime-proof",
),
),
)
result = evaluate_acceptance(vector)
assert result.decision == AcceptanceDecision.UNKNOWN
assert result.reasons == ("criterion_unknown:runtime",)
def test_acceptance_rejects_failed_invariant():
vector = AcceptanceVector(
subject_type="release",
subject_id="V2R2C2",
subject_revision=1,
criteria=(
AcceptanceCriterion("tests", True, EvidenceState.PASS, "pytest"),
),
invariants=(
AcceptanceInvariant("protected-ref", EvidenceState.FAIL),
),
)
assert evaluate_acceptance(vector).decision == AcceptanceDecision.REJECT
def test_acceptance_blocks_on_unresolved_blocker():
vector = AcceptanceVector(
subject_type="goal",
subject_id="goal-1",
subject_revision=1,
criteria=(AcceptanceCriterion("code", True, EvidenceState.PASS, "ci"),),
unresolved_blockers=("blocker-1",),
)
assert evaluate_acceptance(vector).decision == AcceptanceDecision.BLOCKED
def test_state_ownership_is_unique_and_final_writer_is_enforced():
custom = (
StateOwnership(
object_type="goal",
authoritative_service="goal-kernel",
authoritative_store="goal-store",
final_writer="goal-kernel",
),
)
validate_state_ownership("goal", "goal-kernel", custom, final_state=True)
with pytest.raises(ConvergenceContractError, match="STATE_OWNERSHIP_VIOLATION"):
validate_state_ownership("goal", "worker", custom, final_state=True)
with pytest.raises(ConvergenceContractError, match="duplicate_state_owner"):
ownership_index(custom + custom)
def test_missing_or_unknown_observation_never_converges():
desired = DesiredState("contract:gpt", "external_projection", 2, {"hash": "abc"})
missing = plan_reconciliation(desired, None)
assert missing.state == ReconciliationState.OBSERVING
assert missing.observation_required is True
unknown = ObservedState(
resource_id="contract:gpt",
observed_generation=None,
observed_spec={},
health=ObservedHealth.UNKNOWN,
source_identity="gpt-action",
observed_at="2026-08-25T00:00:00Z",
)
result = plan_reconciliation(desired, unknown)
assert result.state == ReconciliationState.OBSERVING
def test_equal_healthy_observation_converges_and_key_is_stable():
desired = DesiredState("worker:a", "worker_binding", 3, {"build": "x"})
observed = ObservedState(
resource_id="worker:a",
observed_generation=3,
observed_spec={"build": "x"},
health=ObservedHealth.HEALTHY,
source_identity="worker-registry",
observed_at="2026-08-25T00:00:00Z",
)
one = plan_reconciliation(desired, observed)
two = plan_reconciliation(desired, observed)
assert one.state == ReconciliationState.CONVERGED
assert one.idempotency_key == two.idempotency_key
def test_drift_is_diff_found_not_auto_applied():
desired = DesiredState("projection:openapi", "external_projection", 4, {"hash": "new"})
observed = ObservedState(
resource_id="projection:openapi",
observed_generation=3,
observed_spec={"hash": "old"},
health=ObservedHealth.HEALTHY,
source_identity="published-openapi",
observed_at="2026-08-25T00:00:00Z",
)
result = plan_reconciliation(desired, observed)
assert result.state == ReconciliationState.DIFF_FOUND
assert result.observation_required is False
def test_continuation_manifest_is_durable_and_hashable():
manifest = ContinuationManifest(
trace_id="trace-1",
goal_id="goal-1",
goal_revision=1,
task_id="task-1",
run_id="run-1",
current_node_id="node-4",
acceptance_vector_ref="acceptance:goal-1:1",
next_action="resume node-4",
stop_reason=ContinuationStopReason.CONTEXT_BOUNDARY,
checkpoint_ref="checkpoint-9",
unresolved_blocker_refs=("blocker-a",),
)
assert manifest.as_dict()["stop_reason"] == "context_boundary"
assert manifest.content_hash.startswith("sha256:")