Files
aios/tests/test_online_agent_plan_store.py
T

61 lines
2.6 KiB
Python

from pathlib import Path
import sys
import pytest
ROOT=Path(__file__).resolve().parents[1]
sys.path.insert(0,str(ROOT/"active-runtime/app"))
from aios_online_agent_execution import GovernedExecutionBinding
from aios_online_agent_plan_store import ExecutionPlanStore, ExecutionPlanError
BASE="a642b045775b9154a00ae78543037fbef4fb447b"
HEAD="71523aef6e48b1e2fa516c456ca189b7a039104b"
def binding(head=HEAD):
return GovernedExecutionBinding.from_mapping({
"task_id":"task-plan-a","job_id":"job-plan-a","repository":"aios/aios","base_oid":BASE,
"expected_branch_oid":head,"target_branch":"agent/task-plan-a","branch_mode":"CONTINUE_EXISTING",
"generation":1,"idempotency_key":"governed-plan-a",
})
def request():
return {
"schema":"aios.online-agent.plan.v1","task_id":"task-plan-a","job_id":"job-plan-a",
"source_head_oid":HEAD,"generation":1,"idempotency_key":"plan-task-a-v1",
"execution":{
"action":"deterministic",
"change_set":[{"path":"x.py","operation":"write_file","content":"x=1\n"}],
"verification":[{"label":"compile","argv":["/usr/bin/python3","-m","py_compile","x.py"],"cwd":".","timeout_seconds":30}],
"capability_scope":["git.read","git.test"],
}
}
def test_plan_register_and_resolve(tmp_path):
store=ExecutionPlanStore(tmp_path)
created=store.register(binding(),request())
assert created["idempotent"] is False
resolved=store.resolve(binding())
assert resolved["plan_digest"]==created["plan_digest"]
assert resolved["execution"]["action"]=="deterministic"
def test_plan_is_idempotent(tmp_path):
store=ExecutionPlanStore(tmp_path); req=request()
first=store.register(binding(),req); second=store.register(binding(),req)
assert second["idempotent"] is True
assert first["plan_digest"]==second["plan_digest"]
def test_plan_source_head_drift_denied(tmp_path):
store=ExecutionPlanStore(tmp_path); store.register(binding(),request())
with pytest.raises(ExecutionPlanError,match="SOURCE_HEAD_DRIFT"):
store.resolve(binding("b"*40))
def test_plan_replacement_requires_cas(tmp_path):
store=ExecutionPlanStore(tmp_path); first=store.register(binding(),request())
changed=request(); changed["idempotency_key"]="plan-task-a-v2"
changed["execution"]["change_set"][0]["content"]="x=2\n"
with pytest.raises(ExecutionPlanError,match="REPLACEMENT_CAS_MISMATCH"):
store.register(binding(),changed)
changed["expected_previous_plan_digest"]=first["plan_digest"]
second=store.register(binding(),changed)
assert second["plan_digest"]!=first["plan_digest"]