diff --git a/apps/api/src/agents/protocol.py b/apps/api/src/agents/protocol.py
index d52474eb0..37e4a8c14 100644
--- a/apps/api/src/agents/protocol.py
+++ b/apps/api/src/agents/protocol.py
@@ -133,7 +133,8 @@ class RecommendedAction:
label: str # UI 顯示文字(如「查 Pod 日誌」)
emoji: str # UI 圖示(如「📋」)
mcp_provider: Literal[ # MCP provider 限制在已知清單
- "k8s", "ssh", "prometheus", "signoz", "database", "internal"
+ "k8s", "ssh", "prometheus", "signoz", "database", "internal",
+ "controlled",
]
mcp_tool: str # MCP tool 名(必須在 B2 allowlist)
params: dict[str, str] # 參數模板(支援 {labels.xxx} / {incident_id})
diff --git a/apps/api/src/agents/solver_agent.py b/apps/api/src/agents/solver_agent.py
index 384822fcc..fbf83cd48 100644
--- a/apps/api/src/agents/solver_agent.py
+++ b/apps/api/src/agents/solver_agent.py
@@ -92,7 +92,7 @@ _CALLBACK_SPEC_PATH = Path(__file__).parent.parent / "services" / "callback_acti
# 有效的 mcp_provider 清單(與 RecommendedAction schema 對應)
_VALID_MCP_PROVIDERS = frozenset(
- {"k8s", "ssh", "prometheus", "signoz", "database", "internal"}
+ {"k8s", "ssh", "prometheus", "signoz", "database", "internal", "controlled"}
)
# 有效的 risk 等級(與 RecommendedAction schema 對應)
@@ -710,7 +710,7 @@ blast_radius 參考:
recommended_actions 規則(北極星 §1.1 修復多樣性):
- 第一個動作必須是診斷/查看類(低風險),讓 SRE 先確認情況
- 不要全部是 restart 類動作
-- mcp_provider 必須是以下之一:k8s | ssh | prometheus | signoz | database | internal
+- mcp_provider 必須是以下之一:k8s | ssh | prometheus | signoz | database | internal | controlled
- risk 必須是以下之一:low | medium | high | critical
- params 中可使用模板:{{labels.namespace}} / {{labels.pod}} / {{incident_id}}
diff --git a/apps/api/tests/test_current_owner_controlled_apply_policy.py b/apps/api/tests/test_current_owner_controlled_apply_policy.py
index 2149ad658..677675d4d 100644
--- a/apps/api/tests/test_current_owner_controlled_apply_policy.py
+++ b/apps/api/tests/test_current_owner_controlled_apply_policy.py
@@ -86,7 +86,9 @@ def test_medium_telegram_card_is_automation_progress_not_action_required() -> No
assert "AI CONTROLLED AUTOMATION" in rendered
assert "ACTION REQUIRED" not in rendered
assert "awaiting_approval" not in rendered
- assert "check>apply>verify>writeback" in rendered
+ assert "流程進度" in rendered
+ assert "執行:controlled_queue_evaluation" in rendered
+ assert "驗證:not_started" in rendered
def test_critical_telegram_card_stays_break_glass() -> None:
diff --git a/apps/api/tests/test_sre_k3s_controlled_automation_work_items_api.py b/apps/api/tests/test_sre_k3s_controlled_automation_work_items_api.py
index e0fd4c5e6..67552e8cc 100644
--- a/apps/api/tests/test_sre_k3s_controlled_automation_work_items_api.py
+++ b/apps/api/tests/test_sre_k3s_controlled_automation_work_items_api.py
@@ -117,7 +117,7 @@ def test_loader_returns_fixed_architecture_provider_order_and_agent99_bridge() -
"by_priority": {"P0": 16, "P1": 2},
"by_status": {
"source_implemented_runtime_pending": 17,
- "planned": 1,
+ "in_progress": 1,
},
"source_implemented_items": 17,
"runtime_closed_items": 0,
diff --git a/apps/api/tests/test_telegram_integration.py b/apps/api/tests/test_telegram_integration.py
index ad7ba800e..6abe9499e 100644
--- a/apps/api/tests/test_telegram_integration.py
+++ b/apps/api/tests/test_telegram_integration.py
@@ -136,7 +136,8 @@ class TestTelegramMessageStructure:
assert "api-service" in result
assert "INC-20260321-0001" in result
assert "後端" in result
- assert "88%" in result
+ assert "AI 結果未附 durable provider receipt" in result
+ assert "88%" not in result
def test_telegram_message_with_signoz_metrics(self):
"""✅ 含 SignOz 指標的訊息格式"""
diff --git a/apps/api/tests/test_telegram_message_templates.py b/apps/api/tests/test_telegram_message_templates.py
index 2ef2294d0..902af98ff 100644
--- a/apps/api/tests/test_telegram_message_templates.py
+++ b/apps/api/tests/test_telegram_message_templates.py
@@ -2460,9 +2460,11 @@ class TestTelegramMessageFormat:
assert "處置狀態" in result
assert "規則建議待 AI controlled policy 判定" in result
assert "AI 自動化鏈路" in result
- assert "OpenClaw" in result
- assert "NemoTron" in result
- assert "ElephantAlpha" in result
+ assert "分析:not_observed" in result
+ assert "Agent:not_observed" in result
+ assert "OpenClaw" not in result
+ assert "NemoTron" not in result
+ assert "ElephantAlpha" not in result
assert "自動化資產沉澱" in result
assert "KM" in result
assert "PlayBook" in result
@@ -2471,6 +2473,39 @@ class TestTelegramMessageFormat:
assert "Verifier" in result
assert len(result) <= 4096 # Telegram HTML message limit
+ def test_telegram_message_names_only_receipt_backed_ai_and_agent(self):
+ msg = TelegramMessage(
+ status_emoji="⚠️",
+ risk_level="MEDIUM",
+ resource_name="backup_restore",
+ root_cause="Backup freshness evidence verified",
+ suggested_action="NO_ACTION",
+ estimated_downtime="none",
+ approval_id="INC-20260719-AI-RECEIPT",
+ automation_quality={
+ "verdict": "diagnostic_only",
+ "facts": {
+ "analysis_receipt_observed": True,
+ "analysis_provider": "ollama_gcp_a:qwen3",
+ "execution_actors": ["Agent99 BackupCheck (read-only)"],
+ "latest_execution_backend": "Agent99",
+ "latest_operation_type": "BackupCheck",
+ "latest_operation_status": "completed",
+ "verification_result": "passed",
+ "knowledge_entries": 1,
+ "mcp_gateway_total": 1,
+ },
+ },
+ )
+
+ result = msg.format()
+
+ assert "分析:ollama_gcp_a:qwen3" in result
+ assert "Agent99 BackupCheck (read-only)" in result
+ assert "Executor:Agent99" in result
+ assert "Verifier:passed" in result
+ assert "Learning:KM 1 / MCP 1" in result
+
def test_telegram_message_ai_proposal_marks_controlled_apply(self):
"""有 AI 信心分數的修復建議必須排入 controlled apply。"""
msg = TelegramMessage(
diff --git a/docs/operations/sre-k3s-controlled-automation-work-items.snapshot.json b/docs/operations/sre-k3s-controlled-automation-work-items.snapshot.json
index 5a4584c60..e761a09dd 100644
--- a/docs/operations/sre-k3s-controlled-automation-work-items.snapshot.json
+++ b/docs/operations/sre-k3s-controlled-automation-work-items.snapshot.json
@@ -919,7 +919,7 @@
"title": "Gitea CD、production runtime 與 visible closure",
"owner_lane": "ReleaseControl",
"risk": "high",
- "status": "planned",
+ "status": "in_progress",
"dependencies": [
"AIA-SRE-001",
"AIA-SRE-002",
@@ -938,12 +938,17 @@
"verifier": "deploy marker, image SHA, API readback and desktop/mobile smoke",
"rollback": "previous immutable image revision and ConfigMap source SHA",
"exit_condition": "source/test/CD/runtime/UI evidence all match one deployed SHA; gitea-native exact metrics are fresh and the retired legacy GitHub exporter is absent from production",
+ "confirmed_truth": [
+ "the local release candidate is merged with the latest observed gitea/main and passes the CD-equivalent non-integration API gate with 5666 passed and 23 skipped, including the 977-test changed-file suite; 4 focused web tests, web typecheck and JSON/YAML parsing also pass",
+ "stale Telegram tests that required unobserved OpenClaw/NemoTron/ElephantAlpha labels, a promotional check/apply/verify/writeback string or an unreceipted 88 percent confidence were replaced by no-false-AI receipt and actual stage-state contracts; receipt-backed provider, Agent99 executor, verifier and KM/MCP evidence remain visible",
+ "the Solver, RecommendedAction schema and callback registry now agree that host/systemd actions use the controlled provider and host_ansible_reconcile typed route instead of generic SSH fallback"
+ ],
"runtime_gaps": [
"no program item is runtime closed for this source SHA",
"gitea-native exact target is missing while legacy GitHub exporter runtime drift remains",
- "source/test readiness, CD terminal, production runtime and visible UI evidence are separate incomplete layers"
+ "local source/test readiness is complete, but no normal push, CD terminal, deploy marker, production runtime or visible UI/Telegram evidence exists for this candidate"
],
- "next_action": "commit phase 1, normal push after shared writer release, then terminal CD plus production API/runtime/UI readback and exact gitea-native/legacy-exporter verification"
+ "next_action": "hand the exact local candidate SHA to the authorized release lane for one normal push after shared-writer coordination, then require terminal CD plus production API/runtime/UI/Telegram readback and exact gitea-native/legacy-exporter verification"
}
],
"rollups": {
@@ -954,7 +959,7 @@
},
"by_status": {
"source_implemented_runtime_pending": 17,
- "planned": 1
+ "in_progress": 1
},
"source_implemented_items": 17,
"runtime_closed_items": 0,