feat(governance): 新增 AI Agent TG canary 批准包
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
AI Agent professional task expansion and Telegram runtime bridge snapshot.
|
||||
|
||||
Loads the latest committed P2-405B read-only contract. The contract expands
|
||||
Loads the latest committed P2-405C read-only contract. The contract expands
|
||||
professional AI Agent work and defines Telegram no-send previews, but it does
|
||||
not write Telegram Gateway queues, send Telegram messages, call the Bot API,
|
||||
read secrets, or execute production changes.
|
||||
@@ -28,6 +28,7 @@ _EXPECTED_NO_SEND_PREVIEW_COUNT = 6
|
||||
_EXPECTED_DEDUP_KEY_COUNT = 6
|
||||
_EXPECTED_RECEIPT_EXPECTATION_COUNT = 6
|
||||
_EXPECTED_CANARY_PACKAGE_COUNT = 1
|
||||
_EXPECTED_CANARY_APPROVAL_PACKET_COUNT = 1
|
||||
_ZERO_ROLLUP_FIELDS = {
|
||||
"current_live_count",
|
||||
"gateway_queue_write_count",
|
||||
@@ -44,6 +45,14 @@ _ZERO_ROLLUP_FIELDS = {
|
||||
"preview_bot_api_call_enabled_count",
|
||||
"receipt_live_write_enabled_count",
|
||||
"canary_live_send_enabled_count",
|
||||
"canary_approval_granted_count",
|
||||
"canary_selected_message_type_count",
|
||||
"canary_approved_time_window_count",
|
||||
"canary_send_execution_enabled_count",
|
||||
"canary_gateway_queue_write_enabled_count",
|
||||
"canary_bot_api_call_enabled_count",
|
||||
"canary_delivery_receipt_write_enabled_count",
|
||||
"canary_secret_read_enabled_count",
|
||||
}
|
||||
_FORBIDDEN_PUBLIC_TERMS = {
|
||||
"work_window_transcript",
|
||||
@@ -91,11 +100,11 @@ def _require_schema(payload: dict[str, Any], label: str) -> None:
|
||||
status = payload.get("program_status") or {}
|
||||
expected = {
|
||||
"current_priority": "P2",
|
||||
"current_task_id": "P2-405B",
|
||||
"next_task_id": "P2-405C",
|
||||
"current_task_id": "P2-405C",
|
||||
"next_task_id": "P2-405D",
|
||||
"read_only_mode": True,
|
||||
"runtime_authority": _RUNTIME_AUTHORITY,
|
||||
"overall_completion_percent": 88,
|
||||
"overall_completion_percent": 92,
|
||||
}
|
||||
mismatches = _mismatches(status, expected)
|
||||
if mismatches:
|
||||
@@ -135,6 +144,7 @@ def _require_telegram_bridge(payload: dict[str, Any], label: str) -> None:
|
||||
|
||||
_require_no_send_previews(bridge, label)
|
||||
_require_receipt_and_canary_package(bridge, label)
|
||||
_require_canary_send_approval_packet(bridge, label)
|
||||
|
||||
|
||||
def _require_no_send_previews(bridge: dict[str, Any], label: str) -> None:
|
||||
@@ -233,6 +243,88 @@ def _require_receipt_and_canary_package(bridge: dict[str, Any], label: str) -> N
|
||||
raise ValueError(f"{label}: canary_approval_package.approval_checklist is required")
|
||||
|
||||
|
||||
def _require_canary_send_approval_packet(bridge: dict[str, Any], label: str) -> None:
|
||||
packet = bridge.get("canary_send_approval_packet") or {}
|
||||
expected_packet = {
|
||||
"packet_ready": True,
|
||||
"approval_required": True,
|
||||
"approval_granted": False,
|
||||
"status": "waiting_explicit_commander_approval",
|
||||
"target_room_env": "SRE_GROUP_CHAT_ID",
|
||||
"target_room_value_visible": False,
|
||||
"selected_message_type": "not_selected",
|
||||
"proposed_time_window": "waiting_commander_input",
|
||||
}
|
||||
mismatches = _mismatches(packet, expected_packet)
|
||||
if mismatches:
|
||||
raise ValueError(f"{label}: canary_send_approval_packet mismatch: {mismatches}")
|
||||
if not packet:
|
||||
raise ValueError(
|
||||
f"{label}: expected {_EXPECTED_CANARY_APPROVAL_PACKET_COUNT} canary send approval packet"
|
||||
)
|
||||
|
||||
message_types = {item.get("message_type") for item in bridge.get("message_types") or []}
|
||||
eligible = set(packet.get("eligible_message_types") or [])
|
||||
if eligible != message_types:
|
||||
raise ValueError(f"{label}: canary send packet must cover every eligible message type")
|
||||
|
||||
fields = packet.get("operator_approval_fields") or []
|
||||
required_field_ids = {
|
||||
"commander_approval",
|
||||
"selected_message_type",
|
||||
"scheduled_window",
|
||||
"target_room_env_ref",
|
||||
"mute_rollback_plan",
|
||||
"receipt_readback_owner",
|
||||
"failure_stop_condition",
|
||||
}
|
||||
field_ids = {field.get("field_id") for field in fields}
|
||||
if field_ids != required_field_ids:
|
||||
raise ValueError(f"{label}: canary send packet approval fields mismatch")
|
||||
for field in fields:
|
||||
field_id = field.get("field_id")
|
||||
if field.get("required") is not True:
|
||||
raise ValueError(f"{label}: {field_id}.required must be true")
|
||||
if field.get("current_value_status") != "waiting_input":
|
||||
raise ValueError(f"{label}: {field_id}.current_value_status must be waiting_input")
|
||||
if field.get("value_display_allowed") is not False:
|
||||
raise ValueError(f"{label}: {field_id}.value_display_allowed must remain false")
|
||||
|
||||
execution_flags = packet.get("execution_flags") or {}
|
||||
expected_execution = {
|
||||
"canary_send_execution_enabled": False,
|
||||
"gateway_queue_write_enabled": False,
|
||||
"bot_api_call_enabled": False,
|
||||
"delivery_receipt_write_enabled": False,
|
||||
"production_write_enabled": False,
|
||||
"secret_read_enabled": False,
|
||||
"paid_api_enabled": False,
|
||||
}
|
||||
mismatches = _mismatches(execution_flags, expected_execution)
|
||||
if mismatches:
|
||||
raise ValueError(f"{label}: canary send execution flags mismatch: {mismatches}")
|
||||
|
||||
rate_limit = packet.get("rate_limit_plan") or {}
|
||||
if rate_limit.get("max_messages") != 1:
|
||||
raise ValueError(f"{label}: canary send max_messages must be 1")
|
||||
if rate_limit.get("live_rate_limit_write_enabled") is not False:
|
||||
raise ValueError(f"{label}: live_rate_limit_write_enabled must remain false")
|
||||
|
||||
receipt_plan = packet.get("receipt_readback_plan") or {}
|
||||
if receipt_plan.get("production_receipt_write_enabled") is not False:
|
||||
raise ValueError(f"{label}: production_receipt_write_enabled must remain false")
|
||||
if receipt_plan.get("receipt_readback_enabled_before_send") is not False:
|
||||
raise ValueError(f"{label}: receipt_readback_enabled_before_send must remain false")
|
||||
if not receipt_plan.get("required_checks"):
|
||||
raise ValueError(f"{label}: receipt_readback_plan.required_checks is required")
|
||||
if not packet.get("stop_conditions"):
|
||||
raise ValueError(f"{label}: canary send packet stop_conditions are required")
|
||||
if not packet.get("mute_rollback_plan"):
|
||||
raise ValueError(f"{label}: canary send packet mute_rollback_plan is required")
|
||||
if packet.get("approval_decision_log") != []:
|
||||
raise ValueError(f"{label}: canary send approval_decision_log must remain empty")
|
||||
|
||||
|
||||
def _require_professional_tasks(payload: dict[str, Any], label: str) -> None:
|
||||
domains = payload.get("professional_task_domains") or []
|
||||
if len(domains) != _EXPECTED_DOMAIN_COUNT:
|
||||
@@ -326,6 +418,26 @@ def _require_rollups(payload: dict[str, Any], label: str) -> None:
|
||||
"canary_approval_package_count": 1
|
||||
if bridge.get("canary_approval_package")
|
||||
else 0,
|
||||
"canary_send_approval_packet_count": 1
|
||||
if bridge.get("canary_send_approval_packet")
|
||||
else 0,
|
||||
"canary_operator_approval_field_count": len(
|
||||
(bridge.get("canary_send_approval_packet") or {}).get("operator_approval_fields")
|
||||
or []
|
||||
),
|
||||
"canary_stop_condition_count": len(
|
||||
(bridge.get("canary_send_approval_packet") or {}).get("stop_conditions") or []
|
||||
),
|
||||
"canary_rollback_mute_step_count": len(
|
||||
(bridge.get("canary_send_approval_packet") or {}).get("mute_rollback_plan") or []
|
||||
),
|
||||
"canary_receipt_readback_check_count": len(
|
||||
(
|
||||
(bridge.get("canary_send_approval_packet") or {}).get("receipt_readback_plan")
|
||||
or {}
|
||||
).get("required_checks")
|
||||
or []
|
||||
),
|
||||
}
|
||||
mismatches = _mismatches(rollups, expected)
|
||||
if mismatches:
|
||||
|
||||
@@ -18,9 +18,9 @@ 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-405B"
|
||||
assert snapshot["program_status"]["next_task_id"] == "P2-405C"
|
||||
assert snapshot["program_status"]["overall_completion_percent"] == 88
|
||||
assert snapshot["program_status"]["current_task_id"] == "P2-405C"
|
||||
assert snapshot["program_status"]["next_task_id"] == "P2-405D"
|
||||
assert snapshot["program_status"]["overall_completion_percent"] == 92
|
||||
assert snapshot["program_status"]["runtime_authority"] == (
|
||||
"professional_task_expansion_and_telegram_bridge_read_only_no_send"
|
||||
)
|
||||
@@ -42,6 +42,10 @@ def test_load_latest_ai_agent_professional_task_expansion_snapshot() -> None:
|
||||
assert bridge["queue_preview_readback"]["write_enabled"] is False
|
||||
assert bridge["canary_approval_package"]["status"] == "blocked_until_explicit_approval"
|
||||
assert bridge["canary_approval_package"]["live_send_enabled"] is False
|
||||
assert bridge["canary_send_approval_packet"]["status"] == "waiting_explicit_commander_approval"
|
||||
assert bridge["canary_send_approval_packet"]["approval_granted"] is False
|
||||
assert bridge["canary_send_approval_packet"]["selected_message_type"] == "not_selected"
|
||||
assert bridge["canary_send_approval_packet"]["proposed_time_window"] == "waiting_commander_input"
|
||||
|
||||
rollups = snapshot["rollups"]
|
||||
assert rollups["professional_task_count"] == 24
|
||||
@@ -72,6 +76,19 @@ def test_load_latest_ai_agent_professional_task_expansion_snapshot() -> None:
|
||||
assert rollups["preview_bot_api_call_enabled_count"] == 0
|
||||
assert rollups["receipt_live_write_enabled_count"] == 0
|
||||
assert rollups["canary_live_send_enabled_count"] == 0
|
||||
assert rollups["canary_send_approval_packet_count"] == 1
|
||||
assert rollups["canary_operator_approval_field_count"] == 7
|
||||
assert rollups["canary_stop_condition_count"] == 6
|
||||
assert rollups["canary_rollback_mute_step_count"] == 5
|
||||
assert rollups["canary_receipt_readback_check_count"] == 6
|
||||
assert rollups["canary_approval_granted_count"] == 0
|
||||
assert rollups["canary_selected_message_type_count"] == 0
|
||||
assert rollups["canary_approved_time_window_count"] == 0
|
||||
assert rollups["canary_send_execution_enabled_count"] == 0
|
||||
assert rollups["canary_gateway_queue_write_enabled_count"] == 0
|
||||
assert rollups["canary_bot_api_call_enabled_count"] == 0
|
||||
assert rollups["canary_delivery_receipt_write_enabled_count"] == 0
|
||||
assert rollups["canary_secret_read_enabled_count"] == 0
|
||||
|
||||
|
||||
def test_professional_tasks_cover_required_agents_and_reporting() -> None:
|
||||
@@ -146,6 +163,39 @@ def test_receipts_and_canary_package_remain_no_send() -> None:
|
||||
assert canary["production_write_enabled"] is False
|
||||
|
||||
|
||||
def test_canary_send_approval_packet_waits_for_explicit_approval() -> None:
|
||||
snapshot = load_latest_ai_agent_professional_task_expansion()
|
||||
bridge = snapshot["telegram_runtime_bridge"]
|
||||
packet = bridge["canary_send_approval_packet"]
|
||||
|
||||
assert packet["packet_ready"] is True
|
||||
assert packet["approval_required"] is True
|
||||
assert packet["approval_granted"] is False
|
||||
assert packet["target_room_env"] == "SRE_GROUP_CHAT_ID"
|
||||
assert packet["target_room_value_visible"] is False
|
||||
assert packet["selected_message_type"] == "not_selected"
|
||||
assert packet["proposed_time_window"] == "waiting_commander_input"
|
||||
assert set(packet["eligible_message_types"]) == {
|
||||
message_type["message_type"] for message_type in bridge["message_types"]
|
||||
}
|
||||
assert len(packet["operator_approval_fields"]) == 7
|
||||
assert len(packet["stop_conditions"]) == 6
|
||||
assert len(packet["mute_rollback_plan"]) == 5
|
||||
assert len(packet["receipt_readback_plan"]["required_checks"]) == 6
|
||||
assert packet["approval_decision_log"] == []
|
||||
|
||||
for field in packet["operator_approval_fields"]:
|
||||
assert field["required"] is True
|
||||
assert field["current_value_status"] == "waiting_input"
|
||||
assert field["value_display_allowed"] is False
|
||||
|
||||
assert packet["rate_limit_plan"]["max_messages"] == 1
|
||||
assert packet["rate_limit_plan"]["live_rate_limit_write_enabled"] is False
|
||||
assert packet["receipt_readback_plan"]["production_receipt_write_enabled"] is False
|
||||
assert packet["receipt_readback_plan"]["receipt_readback_enabled_before_send"] is False
|
||||
assert all(value is False for value in packet["execution_flags"].values())
|
||||
|
||||
|
||||
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
|
||||
@@ -194,6 +244,39 @@ def test_rejects_canary_live_send_enabled(tmp_path: Path) -> None:
|
||||
load_latest_ai_agent_professional_task_expansion(tmp_path)
|
||||
|
||||
|
||||
def test_rejects_canary_send_approval_granted(tmp_path: Path) -> None:
|
||||
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
|
||||
packet = snapshot["telegram_runtime_bridge"]["canary_send_approval_packet"]
|
||||
packet["approval_granted"] = True
|
||||
snapshot["rollups"]["canary_approval_granted_count"] = 1
|
||||
_write_snapshot(tmp_path, snapshot)
|
||||
|
||||
with pytest.raises(ValueError, match="canary_send_approval_packet mismatch"):
|
||||
load_latest_ai_agent_professional_task_expansion(tmp_path)
|
||||
|
||||
|
||||
def test_rejects_canary_send_execution_enabled(tmp_path: Path) -> None:
|
||||
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
|
||||
packet = snapshot["telegram_runtime_bridge"]["canary_send_approval_packet"]
|
||||
packet["execution_flags"]["canary_send_execution_enabled"] = True
|
||||
snapshot["rollups"]["canary_send_execution_enabled_count"] = 1
|
||||
_write_snapshot(tmp_path, snapshot)
|
||||
|
||||
with pytest.raises(ValueError, match="canary send execution flags mismatch"):
|
||||
load_latest_ai_agent_professional_task_expansion(tmp_path)
|
||||
|
||||
|
||||
def test_rejects_selected_canary_message_type_without_approval(tmp_path: Path) -> None:
|
||||
snapshot = copy.deepcopy(load_latest_ai_agent_professional_task_expansion())
|
||||
packet = snapshot["telegram_runtime_bridge"]["canary_send_approval_packet"]
|
||||
packet["selected_message_type"] = "daily_agent_workload_digest"
|
||||
snapshot["rollups"]["canary_selected_message_type_count"] = 1
|
||||
_write_snapshot(tmp_path, snapshot)
|
||||
|
||||
with pytest.raises(ValueError, match="canary_send_approval_packet mismatch"):
|
||||
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")
|
||||
|
||||
@@ -17,9 +17,9 @@ def test_ai_agent_professional_task_expansion_endpoint() -> None:
|
||||
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-405B"
|
||||
assert payload["program_status"]["next_task_id"] == "P2-405C"
|
||||
assert payload["program_status"]["overall_completion_percent"] == 88
|
||||
assert payload["program_status"]["current_task_id"] == "P2-405C"
|
||||
assert payload["program_status"]["next_task_id"] == "P2-405D"
|
||||
assert payload["program_status"]["overall_completion_percent"] == 92
|
||||
assert payload["program_status"]["runtime_authority"] == (
|
||||
"professional_task_expansion_and_telegram_bridge_read_only_no_send"
|
||||
)
|
||||
@@ -42,6 +42,17 @@ def test_ai_agent_professional_task_expansion_endpoint() -> None:
|
||||
assert payload["rollups"]["receipt_expectation_count"] == 6
|
||||
assert payload["rollups"]["canary_approval_package_count"] == 1
|
||||
assert payload["rollups"]["preview_send_enabled_count"] == 0
|
||||
assert payload["rollups"]["canary_send_approval_packet_count"] == 1
|
||||
assert payload["rollups"]["canary_operator_approval_field_count"] == 7
|
||||
assert payload["rollups"]["canary_approval_granted_count"] == 0
|
||||
assert payload["rollups"]["canary_send_execution_enabled_count"] == 0
|
||||
assert payload["rollups"]["canary_gateway_queue_write_enabled_count"] == 0
|
||||
assert payload["rollups"]["canary_bot_api_call_enabled_count"] == 0
|
||||
assert payload["telegram_runtime_bridge"]["canary_approval_package"]["live_send_enabled"] is False
|
||||
assert payload["telegram_runtime_bridge"]["canary_send_approval_packet"]["approval_granted"] is False
|
||||
assert (
|
||||
payload["telegram_runtime_bridge"]["canary_send_approval_packet"]["selected_message_type"]
|
||||
== "not_selected"
|
||||
)
|
||||
assert len(payload["telegram_runtime_bridge"]["no_send_message_previews"]) == 6
|
||||
assert len(payload["telegram_runtime_bridge"]["receipt_expectations"]) == 6
|
||||
|
||||
Reference in New Issue
Block a user