feat(governance): 新增 AI Agent 專業任務擴展
All checks were successful
Code Review / ai-code-review (push) Successful in 15s
CD Pipeline / tests (push) Successful in 1m38s
CD Pipeline / build-and-deploy (push) Successful in 6m8s
CD Pipeline / post-deploy-checks (push) Successful in 1m40s

This commit is contained in:
Your Name
2026-06-15 14:19:23 +08:00
parent a923e89017
commit e101931efb
15 changed files with 1453 additions and 3 deletions

View File

@@ -0,0 +1,126 @@
from __future__ import annotations
import copy
import json
import os
from pathlib import Path
import pytest
os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://test:test@localhost/test")
from src.services.ai_agent_professional_task_expansion import (
load_latest_ai_agent_professional_task_expansion,
)
def test_load_latest_ai_agent_professional_task_expansion_snapshot() -> None:
snapshot = load_latest_ai_agent_professional_task_expansion()
assert snapshot["schema_version"] == "ai_agent_professional_task_expansion_v1"
assert snapshot["program_status"]["current_task_id"] == "P2-405A"
assert snapshot["program_status"]["next_task_id"] == "P2-405B"
assert snapshot["program_status"]["overall_completion_percent"] == 82
assert snapshot["program_status"]["runtime_authority"] == (
"professional_task_expansion_and_telegram_bridge_read_only_no_send"
)
bridge = snapshot["telegram_runtime_bridge"]
assert bridge["canonical_room"] == "AwoooI SRE 戰情室"
assert bridge["canonical_room_env"] == "SRE_GROUP_CHAT_ID"
assert bridge["no_send_preview_ready"] is True
assert bridge["queue_preview_readback_ready"] is True
assert bridge["direct_bot_api_allowed"] is False
assert bridge["bot_api_call_enabled"] is False
assert bridge["gateway_queue_write_enabled"] is False
assert bridge["telegram_send_enabled"] is False
assert len(bridge["stages"]) == 5
assert len(bridge["message_types"]) == 6
rollups = snapshot["rollups"]
assert rollups["professional_task_count"] == 24
assert rollups["domain_count"] == 8
assert rollups["telegram_stage_count"] == 5
assert rollups["telegram_message_type_count"] == 6
assert rollups["approval_required_count"] == 19
assert rollups["low_risk_task_count"] == 3
assert rollups["medium_risk_task_count"] == 10
assert rollups["high_risk_task_count"] == 6
assert rollups["critical_risk_task_count"] == 5
assert rollups["current_live_count"] == 0
assert rollups["gateway_queue_write_count"] == 0
assert rollups["telegram_send_count"] == 0
assert rollups["bot_api_call_count"] == 0
assert rollups["delivery_receipt_write_count"] == 0
assert rollups["production_write_count"] == 0
assert rollups["secret_read_count"] == 0
assert rollups["paid_api_call_count"] == 0
assert rollups["host_write_count"] == 0
assert rollups["kubectl_action_count"] == 0
def test_professional_tasks_cover_required_agents_and_reporting() -> None:
snapshot = load_latest_ai_agent_professional_task_expansion()
owners = {task["owner_agent"] for task in snapshot["professional_tasks"]}
assert {
"openclaw",
"hermes",
"nemotron",
"telegram_ops_liaison",
"security_sentinel",
"sre_sentinel",
"devops_commander",
}.issubset(owners)
assert snapshot["reporting_contract"]["daily"]["required"] is True
assert snapshot["reporting_contract"]["weekly"]["required"] is True
assert snapshot["reporting_contract"]["monthly"]["required"] is True
assert snapshot["reporting_contract"]["action_required"]["required"] is True
assert snapshot["redaction_contract"]["conversation_transcript_display_allowed"] is False
assert snapshot["redaction_contract"]["raw_prompt_display_allowed"] is False
assert snapshot["redaction_contract"]["private_reasoning_display_allowed"] is False
assert snapshot["redaction_contract"]["secret_value_display_allowed"] is False
def test_rejects_telegram_send_enabled(tmp_path: Path) -> None:
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
snapshot["telegram_runtime_bridge"]["telegram_send_enabled"] = True
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="telegram_runtime_bridge mismatch"):
load_latest_ai_agent_professional_task_expansion(tmp_path)
def test_rejects_gateway_queue_write_count(tmp_path: Path) -> None:
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
snapshot["rollups"]["gateway_queue_write_count"] = 1
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="must remain zero"):
load_latest_ai_agent_professional_task_expansion(tmp_path)
def test_rejects_high_risk_without_approval(tmp_path: Path) -> None:
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
high_task = next(task for task in snapshot["professional_tasks"] if task["risk_tier"] == "high")
high_task["approval_required"] = False
snapshot["rollups"]["approval_required_count"] -= 1
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="high/critical tasks must require approval"):
load_latest_ai_agent_professional_task_expansion(tmp_path)
def test_rejects_forbidden_public_terms_outside_policy_list(tmp_path: Path) -> None:
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
snapshot["professional_tasks"][0]["title"] = "raw prompt leakage candidate"
_write_snapshot(tmp_path, snapshot)
with pytest.raises(ValueError, match="forbidden public terms leaked"):
load_latest_ai_agent_professional_task_expansion(tmp_path)
def _write_snapshot(directory: Path, payload: dict) -> None:
path = directory / "ai_agent_professional_task_expansion_2099-01-01.json"
path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")

View File

@@ -0,0 +1,39 @@
from __future__ import annotations
import os
from fastapi.testclient import TestClient
os.environ.setdefault("DATABASE_URL", "postgresql+asyncpg://test:test@localhost/test")
from src.main import app
def test_ai_agent_professional_task_expansion_endpoint() -> None:
client = TestClient(app)
response = client.get("/api/v1/agents/agent-professional-task-expansion")
assert response.status_code == 200
payload = response.json()
assert payload["schema_version"] == "ai_agent_professional_task_expansion_v1"
assert payload["program_status"]["current_task_id"] == "P2-405A"
assert payload["program_status"]["next_task_id"] == "P2-405B"
assert payload["program_status"]["overall_completion_percent"] == 82
assert payload["program_status"]["runtime_authority"] == (
"professional_task_expansion_and_telegram_bridge_read_only_no_send"
)
assert payload["telegram_runtime_bridge"]["canonical_room"] == "AwoooI SRE 戰情室"
assert payload["telegram_runtime_bridge"]["direct_bot_api_allowed"] is False
assert payload["telegram_runtime_bridge"]["gateway_queue_write_enabled"] is False
assert payload["telegram_runtime_bridge"]["telegram_send_enabled"] is False
assert payload["telegram_runtime_bridge"]["bot_api_call_enabled"] is False
assert payload["rollups"]["professional_task_count"] == 24
assert payload["rollups"]["domain_count"] == 8
assert payload["rollups"]["approval_required_count"] == 19
assert payload["rollups"]["high_risk_task_count"] == 6
assert payload["rollups"]["critical_risk_task_count"] == 5
assert payload["rollups"]["gateway_queue_write_count"] == 0
assert payload["rollups"]["telegram_send_count"] == 0
assert payload["rollups"]["bot_api_call_count"] == 0
assert payload["rollups"]["production_write_count"] == 0