233 lines
8.0 KiB
Python
233 lines
8.0 KiB
Python
"""Agent OS integration validation suite."""
|
|
|
|
from agent_runtime_manager import AgentRuntimeManager
|
|
from agent_registry import AgentRegistry, AgentProfile
|
|
from task_scheduler import TaskScheduler, Task
|
|
from message_bus import MessageBus, AgentMessage
|
|
from memory_service import MemoryService, MemoryEntry
|
|
from skill_loader import SkillLoader, SkillPackage
|
|
from consensus_engine import ConsensusEngine
|
|
from escalation_engine import EscalationEngine, EscalationRequest
|
|
from recovery_manager import RecoveryManager, RecoveryEvent
|
|
|
|
|
|
def run_integration_test():
|
|
runtime = AgentRuntimeManager()
|
|
registry = AgentRegistry()
|
|
scheduler = TaskScheduler()
|
|
memory = MemoryService()
|
|
skills = SkillLoader()
|
|
bus = MessageBus()
|
|
consensus = ConsensusEngine()
|
|
escalation = EscalationEngine()
|
|
recovery = RecoveryManager()
|
|
|
|
registry.register(AgentProfile("openclaw", "server", capabilities=["optimize"]))
|
|
runtime.register("openclaw")
|
|
scheduler.register_agent("openclaw", ["optimize"])
|
|
|
|
scheduler.submit(Task("task-1", "optimize"))
|
|
assigned = scheduler.dispatch()[0].assigned_agent
|
|
|
|
skills.register(SkillPackage("optimization", "1.0", ["optimize"]))
|
|
memory.save(MemoryEntry("mem-1", "openclaw", "experience", {"task": "task-1"}))
|
|
bus.send(AgentMessage("openclaw", "hermes", "task_complete", {}))
|
|
|
|
decision = consensus.decide([
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
])
|
|
|
|
escalation.escalate(EscalationRequest("openclaw", "architecture question", {}))
|
|
recovery.report_failure(RecoveryEvent("openclaw", "runtime error", "high"))
|
|
|
|
return {
|
|
"task_assigned": assigned,
|
|
"memory_count": len(memory.query("openclaw")),
|
|
"messages": len(bus.consume()),
|
|
"decision": decision,
|
|
"escalations": len(escalation.list_requests()),
|
|
"recoveries": len(recovery.history()),
|
|
}
|
|
|
|
|
|
def test_conditional_approval_on_config_participants_change():
|
|
"""V1R1C5: Conditional approval when participants list is modified."""
|
|
consensus = ConsensusEngine()
|
|
|
|
# Simulate votes where approve wins, but participants changed
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
]
|
|
result = consensus.conditional_decide(
|
|
votes,
|
|
config_participants_changed=True,
|
|
)
|
|
assert result == "conditional_approval", (
|
|
f"Expected conditional_approval, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_conditional_approval_on_config_modes_change():
|
|
"""V1R1C5: Conditional approval when modes list is modified."""
|
|
consensus = ConsensusEngine()
|
|
|
|
# Simulate votes where approve wins, but modes changed
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
]
|
|
result = consensus.conditional_decide(
|
|
votes,
|
|
config_modes_changed=True,
|
|
)
|
|
assert result == "conditional_approval", (
|
|
f"Expected conditional_approval, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_conditional_approval_on_config_disabled():
|
|
"""V1R1C5: Conditional approval when consensus is disabled."""
|
|
consensus = ConsensusEngine()
|
|
|
|
# Simulate votes where approve wins, but consensus is disabled
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
]
|
|
result = consensus.conditional_decide(
|
|
votes,
|
|
config_disabled=True,
|
|
)
|
|
assert result == "conditional_approval", (
|
|
f"Expected conditional_approval, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_conditional_approval_on_weights_adjusted():
|
|
"""V1R1C5: Conditional approval when weights are significantly adjusted."""
|
|
consensus = ConsensusEngine()
|
|
|
|
# Simulate votes where approve wins, but weights were adjusted
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "reject"},
|
|
]
|
|
result = consensus.conditional_decide(
|
|
votes,
|
|
config_weights_adjusted=True,
|
|
)
|
|
# Here approve=2, reject=1 so approve wins, but conditional due to weight changes
|
|
assert result == "conditional_approval", (
|
|
f"Expected conditional_approval, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_conditional_approval_unrelated_change_approves():
|
|
"""V1R1C5: Unrelated changes should still get full approval."""
|
|
consensus = ConsensusEngine()
|
|
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
]
|
|
result = consensus.conditional_decide(
|
|
votes,
|
|
config_participants_changed=False,
|
|
config_modes_changed=False,
|
|
config_disabled=False,
|
|
config_weights_adjusted=False,
|
|
)
|
|
assert result == "approve", (
|
|
f"Expected approve when no config changes, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_reject_on_majority_reject():
|
|
"""Reject when majority votes reject, even without config changes."""
|
|
consensus = ConsensusEngine()
|
|
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "reject"},
|
|
{"agent_type": "server_agent", "decision": "reject"},
|
|
]
|
|
result = consensus.conditional_decide(
|
|
votes,
|
|
config_participants_changed=True, # even with changes
|
|
)
|
|
assert result == "review", (
|
|
f"Expected review when majority rejects, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_conditional_vote_in_vote_payload():
|
|
"""V1R1C5: A vote with condition=True triggers conditional approval."""
|
|
consensus = ConsensusEngine()
|
|
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve", "condition": True},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
]
|
|
result = consensus.decide(votes)
|
|
assert result == "conditional_approval", (
|
|
f"Expected conditional_approval for conditional vote, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def test_no_conditional_vote_approves_normally():
|
|
"""Without any conditional votes, approval proceeds normally."""
|
|
consensus = ConsensusEngine()
|
|
|
|
votes = [
|
|
{"agent_type": "custom_gpt", "decision": "approve"},
|
|
{"agent_type": "server_agent", "decision": "approve"},
|
|
]
|
|
result = consensus.decide(votes)
|
|
assert result == "approve", (
|
|
f"Expected approve without conditional votes, got {result}"
|
|
)
|
|
return result
|
|
|
|
|
|
def run_all_tests():
|
|
tests = [
|
|
("conditional_approval_on_config_participants_change", test_conditional_approval_on_config_participants_change),
|
|
("conditional_approval_on_config_modes_change", test_conditional_approval_on_config_modes_change),
|
|
("conditional_approval_on_config_disabled", test_conditional_approval_on_config_disabled),
|
|
("conditional_approval_on_weights_adjusted", test_conditional_approval_on_weights_adjusted),
|
|
("conditional_approval_unrelated_change_approves", test_conditional_approval_unrelated_change_approves),
|
|
("reject_on_majority_reject", test_reject_on_majority_reject),
|
|
("conditional_vote_in_vote_payload", test_conditional_vote_in_vote_payload),
|
|
("no_conditional_vote_approves_normally", test_no_conditional_vote_approves_normally),
|
|
]
|
|
results = {}
|
|
for name, test_fn in tests:
|
|
try:
|
|
result = test_fn()
|
|
results[name] = {"status": "PASS", "result": result}
|
|
print(f" ✓ {name}: {result}")
|
|
except AssertionError as e:
|
|
results[name] = {"status": "FAIL", "error": str(e)}
|
|
print(f" ✗ {name}: {e}")
|
|
print(f"\n{'='*60}")
|
|
passed = sum(1 for v in results.values() if v["status"] == "PASS")
|
|
total = len(tests)
|
|
print(f"V1R1C5 Conditional Approval Tests: {passed}/{total} passed")
|
|
return results
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("Integration Test Suite\n" + "=" * 60)
|
|
result = run_integration_test()
|
|
print(f"\nBase Integration Test Result: {result}")
|
|
print("\n--- V1R1C5 Conditional Approval Tests ---")
|
|
run_all_tests()
|