187 lines
7.2 KiB
Python
187 lines
7.2 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
import pytest
|
|
|
|
from src.services.ai_agent_deployment_layout import (
|
|
load_latest_ai_agent_deployment_layout,
|
|
)
|
|
|
|
|
|
def test_load_latest_ai_agent_deployment_layout_reads_committed_snapshot():
|
|
data = load_latest_ai_agent_deployment_layout()
|
|
|
|
assert data["schema_version"] == "ai_agent_deployment_layout_v1"
|
|
assert data["program_status"]["read_only_mode"] is True
|
|
assert data["program_status"]["deployment_authority"] == "layout_only_no_runtime_deploy"
|
|
assert data["rollups"]["total_targets"] == len(data["deployment_targets"]) == 42
|
|
assert data["rollups"]["by_primary_agent"]["openclaw"] == 17
|
|
assert data["rollups"]["by_primary_agent"]["hermes"] == 23
|
|
assert data["rollups"]["by_primary_agent"]["nemotron"] == 2
|
|
assert data["rollups"]["blocked_target_ids"] == [
|
|
"host_120",
|
|
"nemotron_replay_pipeline",
|
|
]
|
|
assert data["approval_boundaries"]["telegram_direct_send_allowed"] is False
|
|
assert data["approval_boundaries"]["production_routing_allowed"] is False
|
|
assert data["collaboration_contract"]["frontend_redaction"]["operator_conversation_display_allowed"] is False
|
|
|
|
nemotron_targets = [
|
|
target for target in data["deployment_targets"] if target["primary_agent"] == "nemotron"
|
|
]
|
|
assert {target["automation_level"] for target in nemotron_targets} <= {"observe_only", "blocked"}
|
|
|
|
|
|
def test_load_latest_ai_agent_deployment_layout_rejects_runtime_authority(tmp_path):
|
|
snapshot = _snapshot()
|
|
snapshot["approval_boundaries"]["production_routing_allowed"] = True
|
|
(tmp_path / "ai_agent_deployment_layout_2026-06-11.json").write_text(
|
|
json.dumps(snapshot),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="approval boundaries"):
|
|
load_latest_ai_agent_deployment_layout(tmp_path)
|
|
|
|
|
|
def test_load_latest_ai_agent_deployment_layout_rejects_rollup_mismatch(tmp_path):
|
|
snapshot = _snapshot()
|
|
snapshot["rollups"]["by_primary_agent"]["openclaw"] = 99
|
|
(tmp_path / "ai_agent_deployment_layout_2026-06-11.json").write_text(
|
|
json.dumps(snapshot),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="by_primary_agent"):
|
|
load_latest_ai_agent_deployment_layout(tmp_path)
|
|
|
|
|
|
def test_load_latest_ai_agent_deployment_layout_rejects_nemotron_runtime(tmp_path):
|
|
snapshot = _snapshot()
|
|
snapshot["deployment_targets"][0]["primary_agent"] = "nemotron"
|
|
snapshot["deployment_targets"][0]["automation_level"] = "hitl_execute_after_approval"
|
|
snapshot["rollups"]["by_primary_agent"] = {"nemotron": 1}
|
|
(tmp_path / "ai_agent_deployment_layout_2026-06-11.json").write_text(
|
|
json.dumps(snapshot),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
with pytest.raises(ValueError, match="Nemotron targets"):
|
|
load_latest_ai_agent_deployment_layout(tmp_path)
|
|
|
|
|
|
def _snapshot() -> dict:
|
|
return {
|
|
"schema_version": "ai_agent_deployment_layout_v1",
|
|
"generated_at": "2026-06-11T18:20:00+08:00",
|
|
"program_status": {
|
|
"overall_completion_percent": 10,
|
|
"current_priority": "P1",
|
|
"current_task_id": "P1-401",
|
|
"next_task_id": "P1-402",
|
|
"read_only_mode": True,
|
|
"deployment_authority": "layout_only_no_runtime_deploy",
|
|
},
|
|
"agent_contracts": [
|
|
{
|
|
"agent_id": "openclaw",
|
|
"display_name": "OpenClaw",
|
|
"primary_specialty": "生產仲裁",
|
|
"deployment_lane": "production_decision_core",
|
|
"allowed_autonomy": ["只讀診斷"],
|
|
"must_delegate_to": ["Hermes"],
|
|
"blocked_actions": ["production_write"],
|
|
"learning_scope": ["incident"],
|
|
},
|
|
{
|
|
"agent_id": "hermes",
|
|
"display_name": "Hermes",
|
|
"primary_specialty": "治理",
|
|
"deployment_lane": "governance",
|
|
"allowed_autonomy": ["只讀盤點"],
|
|
"must_delegate_to": ["OpenClaw"],
|
|
"blocked_actions": ["production_write"],
|
|
"learning_scope": ["docs"],
|
|
},
|
|
{
|
|
"agent_id": "nemotron",
|
|
"display_name": "NemoTron",
|
|
"primary_specialty": "離線評估",
|
|
"deployment_lane": "offline_evaluator",
|
|
"allowed_autonomy": ["smoke"],
|
|
"must_delegate_to": ["OpenClaw"],
|
|
"blocked_actions": ["production_route"],
|
|
"learning_scope": ["replay"],
|
|
},
|
|
],
|
|
"domains": [
|
|
{
|
|
"domain_id": "hosts",
|
|
"display_name": "主機",
|
|
"description": "測試主機",
|
|
}
|
|
],
|
|
"deployment_targets": [
|
|
{
|
|
"target_id": "host_110",
|
|
"domain_id": "hosts",
|
|
"display_name": "110",
|
|
"target_type": "host",
|
|
"primary_agent": "openclaw",
|
|
"supporting_agents": ["hermes"],
|
|
"deployment_state": "active_governed",
|
|
"automation_level": "observe_only",
|
|
"capabilities": ["monitor"],
|
|
"telegram_policy": "failure_only",
|
|
"learning_inputs": ["metrics"],
|
|
"communication_channels": ["Prometheus"],
|
|
"approval_gate": "read_only_allowed",
|
|
"evidence_refs": ["infra/ansible/inventory/hosts.yml"],
|
|
"next_action": "觀察。",
|
|
}
|
|
],
|
|
"collaboration_contract": {
|
|
"message_bus": "Redis Streams",
|
|
"audit_trail": "AgentSession",
|
|
"handoff_rules": ["OpenClaw 仲裁"],
|
|
"frontend_redaction": {
|
|
"operator_conversation_display_allowed": False,
|
|
"agent_private_reasoning_display_allowed": False,
|
|
"display_policy": "只顯示摘要。",
|
|
},
|
|
},
|
|
"learning_contract": {
|
|
"event_sources": ["incident"],
|
|
"feedback_loops": ["trust"],
|
|
"growth_metrics": ["precision"],
|
|
"retention_policy": "redacted evidence only",
|
|
},
|
|
"telegram_contract": {
|
|
"primary_gateway": "telegram_gateway.py",
|
|
"bot_roles": ["OpenClaw"],
|
|
"notification_classes": ["failure"],
|
|
"redaction_policy": "redacted",
|
|
"e2e_validation": "ADR-035",
|
|
},
|
|
"rollups": {
|
|
"total_targets": 1,
|
|
"by_domain": {"hosts": 1},
|
|
"by_primary_agent": {"openclaw": 1},
|
|
"by_deployment_state": {"active_governed": 1},
|
|
"by_telegram_policy": {"failure_only": 1},
|
|
"blocked_target_ids": [],
|
|
"approval_required_target_ids": [],
|
|
},
|
|
"approval_boundaries": {
|
|
"sdk_installation_allowed": False,
|
|
"paid_api_call_allowed": False,
|
|
"shadow_or_canary_allowed": False,
|
|
"production_routing_allowed": False,
|
|
"destructive_operation_allowed": False,
|
|
"secret_plaintext_allowed": False,
|
|
"autonomous_host_mutation_allowed": False,
|
|
"telegram_direct_send_allowed": False,
|
|
},
|
|
}
|