fix(api): 將無修復批准轉入處置包
All checks were successful
CD Pipeline / tests (push) Successful in 1m52s
Code Review / ai-code-review (push) Successful in 17s
CD Pipeline / build-and-deploy (push) Successful in 7m44s
CD Pipeline / post-deploy-checks (push) Successful in 2m32s

This commit is contained in:
Your Name
2026-06-18 11:38:24 +08:00
parent 79f84aaacc
commit c1c20656ce
6 changed files with 203 additions and 10 deletions

View File

@@ -234,10 +234,24 @@ async def test_candidate_blocked_when_playbook_is_generic_fallback() -> None:
result.metadata["repair_candidate_next_step"]
)
assert "repair_command" in result.metadata["repair_candidate_draft_package"]["required_fields"]
assert "script_or_ansible_ref" in result.metadata["repair_candidate_draft_package"]["required_fields"]
assert "automation_asset_record" in result.metadata["repair_candidate_draft_package"]["required_fields"]
assert "km_update_draft" in result.metadata["repair_candidate_draft_package"]["required_writebacks"]
asset_requirements = result.metadata["repair_candidate_draft_package"][
"automation_asset_requirements"
]
assert [item["asset_type"] for item in asset_requirements] == [
"KM",
"PlayBook",
"ScriptOrAnsible",
"ScheduleOrMonitoringRule",
"Verifier",
]
coverage_gap = result.metadata["repair_candidate_draft_package"]["coverage_gap"]
assert coverage_gap["schema_version"] == "repair_candidate_coverage_gap_v1"
assert coverage_gap["coverage_key"] == "unknownalert:awoooi-api"
assert coverage_gap["blocking_stage"] == "service_playbook_coverage"
assert "automation_asset_record" in coverage_gap["playbook_template_fields"]
assert coverage_gap["next_owner_lane"] == "create_service_specific_repair_playbook"
assert coverage_gap["mcp_evidence_ready"] is True
assert coverage_gap["runtime_execution_authorized"] is False

View File

@@ -1190,7 +1190,8 @@ class TestTelegramMessageFormat:
assert "人工處置包" in result
assert "補證據node_exporter target up" in result
assert "AwoooP 建立修復候選" in result
assert "execution result、verifier、KM / PlayBook trust" in result
assert "沉澱資產KM、PlayBook、腳本/Ansible、排程/監控規則、Verifier 結果" in result
assert "Runs、Work Items、Knowledge Base 要顯示資產 ID、owner、狀態與下一步" in result
assert "等待人工批准" not in result
def test_telegram_message_diagnosis_state_is_not_auto_repair(self):

View File

@@ -125,6 +125,41 @@ async def test_telegram_approval_suppresses_executor_for_no_action(monkeypatch):
status=SimpleNamespace(value="approved"),
incident_id="INC-20260611-NOEXEC",
action="NO_ACTION - REPAIR_CANDIDATE_MISSING: LLM 分析失敗",
metadata={
"repair_candidate_blocker_summary": "只命中通用兜底 PlayBook",
"repair_candidate_draft_package": {
"next_step": "建立專屬 PlayBook 草案",
"required_fields": [
"alertname",
"target_selector",
"repair_command",
"rollback_command",
"verifier_plan",
"owner_review",
],
"required_writebacks": [
"incident_timeline_stage_update",
"km_update_draft",
"playbook_trust_update",
],
"automation_asset_requirements": [
{"asset_type": "KM", "visibility": "knowledge_base"},
{"asset_type": "PlayBook", "visibility": "awooop_work_items"},
{"asset_type": "ScriptOrAnsible", "visibility": "runs_and_work_items"},
],
"blocked_operations": ["approve_no_action_as_repair"],
"awooop_work_item": {
"work_item_id": (
"repair-candidate-draft:awoooi:INC-20260611-NOEXEC:"
"create_service_specific_repair"
),
"work_item_url": (
"https://awoooi.wooo.work/zh-TW/awooop/work-items?"
"project_id=awoooi&incident_id=INC-20260611-NOEXEC"
),
},
},
},
)
finalizer_calls: list[dict] = []
op_log_repo = _FakeAlertOperationLogRepository()
@@ -157,10 +192,30 @@ async def test_telegram_approval_suppresses_executor_for_no_action(monkeypatch):
result = await telegram_api.telegram_webhook(_callback_update(f"approve:{approval_id}:ts:nonce"))
assert result["ok"] is True
assert result["message"] == "ApprovedWithoutExecution"
assert result["message"] == "ApprovedForManualHandoff"
assert result["execution_triggered"] is True
assert result["execution_scheduled"] is False
assert result["execution_suppressed"] is True
assert result["manual_handoff_required"] is True
assert result["manual_handoff_scheduled"] is True
assert result["manual_handoff_kind"] == "repair_candidate_draft"
assert result["next_action"] == "建立專屬 PlayBook 草案"
assert result["repair_candidate_blocker"] == "只命中通用兜底 PlayBook"
assert result["work_item_id"] == (
"repair-candidate-draft:awoooi:INC-20260611-NOEXEC:"
"create_service_specific_repair"
)
assert "project_id=awoooi" in result["work_item_href"]
assert "repair_command" in result["required_fields"]
assert result["blocked_operations"] == ["approve_no_action_as_repair"]
assert result["required_writebacks"] == [
"incident_timeline_stage_update",
"km_update_draft",
"playbook_trust_update",
]
assert result["automation_asset_requirements"][0]["asset_type"] == "KM"
assert result["automation_asset_requirements"][1]["visibility"] == "awooop_work_items"
assert "此批准沒有執行命令" in result["operator_guidance"]
assert finalizer_calls == [{
"approval_id": approval_id,
"execution_triggered": True,