65 lines
1.9 KiB
Python
65 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Deterministic, local-only fault injection for Task Plane recovery."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import time
|
|
from unittest import mock
|
|
|
|
from app.task_plane.api import TaskPlaneService
|
|
from app.task_plane.policy import PolicyEngine
|
|
from app.task_plane.store import TaskPlaneStore
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--database", required=True)
|
|
args = parser.parse_args()
|
|
store = TaskPlaneStore(args.database)
|
|
service = TaskPlaneService(
|
|
store, policy=PolicyEngine(execution_enabled=True)
|
|
)
|
|
identity = "spiffe://aios/agent/codex/fault-injection"
|
|
service.register_worker(
|
|
{
|
|
"worker_id": "codex-fault-injection",
|
|
"worker_type": "codex",
|
|
"identity": identity,
|
|
"capabilities": ["test.execute"],
|
|
"trust_zone": "isolated-shadow",
|
|
"max_concurrency": 1,
|
|
"heartbeat_interval_seconds": 1,
|
|
"supported_protocols": ["aios-task-v1"],
|
|
}
|
|
)
|
|
task = service.create_task(
|
|
{"task_id": "task-fault-expired-lease", "required_capabilities": ["test.execute"]}
|
|
)
|
|
claim = service.claim(
|
|
task["task_id"],
|
|
{
|
|
"worker_id": "codex-fault-injection",
|
|
"actor_identity": identity,
|
|
"lease_seconds": 1,
|
|
},
|
|
)
|
|
with mock.patch("app.task_plane.store._now", return_value=time.time() + 5):
|
|
recovered = store.recover_expired_claim(
|
|
task["task_id"], claim["claim_id"], probe_confirms_stopped=True
|
|
)
|
|
output = {
|
|
"fault": "expired_lease",
|
|
"recovered_status": recovered.status,
|
|
"event_chain_valid": store.verify_event_chain(task["task_id"]),
|
|
"production_side_effects": False,
|
|
}
|
|
print(json.dumps(output, sort_keys=True))
|
|
store.close()
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|