feat(governance): 新增 AI Agent TG canary delivery gate
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
AI Agent professional task expansion and Telegram runtime bridge snapshot.
|
||||
|
||||
Loads the latest committed P2-405C read-only contract. The contract expands
|
||||
Loads the latest committed P2-405D 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.
|
||||
@@ -29,6 +29,7 @@ _EXPECTED_DEDUP_KEY_COUNT = 6
|
||||
_EXPECTED_RECEIPT_EXPECTATION_COUNT = 6
|
||||
_EXPECTED_CANARY_PACKAGE_COUNT = 1
|
||||
_EXPECTED_CANARY_APPROVAL_PACKET_COUNT = 1
|
||||
_EXPECTED_CANARY_DELIVERY_GATE_COUNT = 1
|
||||
_ZERO_ROLLUP_FIELDS = {
|
||||
"current_live_count",
|
||||
"gateway_queue_write_count",
|
||||
@@ -53,6 +54,14 @@ _ZERO_ROLLUP_FIELDS = {
|
||||
"canary_bot_api_call_enabled_count",
|
||||
"canary_delivery_receipt_write_enabled_count",
|
||||
"canary_secret_read_enabled_count",
|
||||
"canary_delivery_approved_count",
|
||||
"canary_delivery_attempt_allowed_count",
|
||||
"canary_delivery_live_send_enabled_count",
|
||||
"canary_delivery_gateway_queue_write_enabled_count",
|
||||
"canary_delivery_bot_api_call_enabled_count",
|
||||
"canary_delivery_receipt_write_enabled_count",
|
||||
"canary_delivery_secret_read_enabled_count",
|
||||
"canary_delivery_paid_api_enabled_count",
|
||||
}
|
||||
_FORBIDDEN_PUBLIC_TERMS = {
|
||||
"work_window_transcript",
|
||||
@@ -100,11 +109,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-405C",
|
||||
"next_task_id": "P2-405D",
|
||||
"current_task_id": "P2-405D",
|
||||
"next_task_id": "P2-405E",
|
||||
"read_only_mode": True,
|
||||
"runtime_authority": _RUNTIME_AUTHORITY,
|
||||
"overall_completion_percent": 92,
|
||||
"overall_completion_percent": 96,
|
||||
}
|
||||
mismatches = _mismatches(status, expected)
|
||||
if mismatches:
|
||||
@@ -145,6 +154,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)
|
||||
_require_canary_delivery_gate(bridge, label)
|
||||
|
||||
|
||||
def _require_no_send_previews(bridge: dict[str, Any], label: str) -> None:
|
||||
@@ -325,6 +335,98 @@ def _require_canary_send_approval_packet(bridge: dict[str, Any], label: str) ->
|
||||
raise ValueError(f"{label}: canary send approval_decision_log must remain empty")
|
||||
|
||||
|
||||
def _require_canary_delivery_gate(bridge: dict[str, Any], label: str) -> None:
|
||||
gate = bridge.get("canary_delivery_gate") or {}
|
||||
expected_gate = {
|
||||
"status": "blocked_waiting_commander_delivery_fields",
|
||||
"gate_ready": True,
|
||||
"delivery_approved": False,
|
||||
"delivery_attempt_allowed": False,
|
||||
"selected_message_type": "not_selected",
|
||||
"target_room_env": "SRE_GROUP_CHAT_ID",
|
||||
"target_room_value_visible": False,
|
||||
"target_room_verified": False,
|
||||
"proposed_time_window": "waiting_commander_input",
|
||||
"approved_time_window": "not_approved",
|
||||
}
|
||||
mismatches = _mismatches(gate, expected_gate)
|
||||
if mismatches:
|
||||
raise ValueError(f"{label}: canary_delivery_gate mismatch: {mismatches}")
|
||||
if not gate:
|
||||
raise ValueError(
|
||||
f"{label}: expected {_EXPECTED_CANARY_DELIVERY_GATE_COUNT} canary delivery gate"
|
||||
)
|
||||
|
||||
fields = gate.get("required_delivery_fields") or []
|
||||
required_field_ids = {
|
||||
"commander_delivery_approval",
|
||||
"selected_message_type",
|
||||
"delivery_time_window",
|
||||
"target_room_env_ref",
|
||||
"receipt_readback_owner",
|
||||
"mute_rollback_plan",
|
||||
"failure_stop_condition",
|
||||
"dry_run_readback_ref",
|
||||
}
|
||||
field_ids = {field.get("field_id") for field in fields}
|
||||
if field_ids != required_field_ids:
|
||||
raise ValueError(f"{label}: canary delivery required 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")
|
||||
|
||||
attempt_plan = gate.get("delivery_attempt_plan") or {}
|
||||
expected_attempt = {
|
||||
"max_messages": 1,
|
||||
"send_mode": "blocked_no_send",
|
||||
"live_delivery_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(attempt_plan, expected_attempt)
|
||||
if mismatches:
|
||||
raise ValueError(f"{label}: canary delivery attempt plan mismatch: {mismatches}")
|
||||
|
||||
execution_flags = gate.get("execution_flags") or {}
|
||||
expected_execution = {
|
||||
"live_delivery_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 delivery execution flags mismatch: {mismatches}")
|
||||
|
||||
readback_plan = gate.get("readback_after_approval_plan") or {}
|
||||
if readback_plan.get("enabled_before_delivery") is not False:
|
||||
raise ValueError(f"{label}: canary delivery readback must stay disabled before delivery")
|
||||
if readback_plan.get("production_receipt_write_enabled") is not False:
|
||||
raise ValueError(f"{label}: canary delivery production receipt write must remain false")
|
||||
if not readback_plan.get("required_checks"):
|
||||
raise ValueError(f"{label}: canary delivery readback required_checks are required")
|
||||
if not gate.get("preflight_checks"):
|
||||
raise ValueError(f"{label}: canary delivery preflight_checks are required")
|
||||
if not gate.get("hold_reasons"):
|
||||
raise ValueError(f"{label}: canary delivery hold_reasons are required")
|
||||
if not gate.get("rollback_mute_controls"):
|
||||
raise ValueError(f"{label}: canary delivery rollback_mute_controls are required")
|
||||
if gate.get("delivery_decision_log") != []:
|
||||
raise ValueError(f"{label}: canary delivery 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:
|
||||
@@ -438,6 +540,28 @@ def _require_rollups(payload: dict[str, Any], label: str) -> None:
|
||||
).get("required_checks")
|
||||
or []
|
||||
),
|
||||
"canary_delivery_gate_count": 1
|
||||
if bridge.get("canary_delivery_gate")
|
||||
else 0,
|
||||
"canary_delivery_required_field_count": len(
|
||||
(bridge.get("canary_delivery_gate") or {}).get("required_delivery_fields") or []
|
||||
),
|
||||
"canary_delivery_preflight_check_count": len(
|
||||
(bridge.get("canary_delivery_gate") or {}).get("preflight_checks") or []
|
||||
),
|
||||
"canary_delivery_hold_reason_count": len(
|
||||
(bridge.get("canary_delivery_gate") or {}).get("hold_reasons") or []
|
||||
),
|
||||
"canary_delivery_readback_check_count": len(
|
||||
(
|
||||
(bridge.get("canary_delivery_gate") or {}).get("readback_after_approval_plan")
|
||||
or {}
|
||||
).get("required_checks")
|
||||
or []
|
||||
),
|
||||
"canary_delivery_rollback_mute_control_count": len(
|
||||
(bridge.get("canary_delivery_gate") or {}).get("rollback_mute_controls") or []
|
||||
),
|
||||
}
|
||||
mismatches = _mismatches(rollups, expected)
|
||||
if mismatches:
|
||||
|
||||
Reference in New Issue
Block a user