fix(awooop): route alert handoff through controlled review
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 18s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-29 19:06:18 +08:00
parent 04f5d20682
commit 09538932df
4 changed files with 34 additions and 32 deletions

View File

@@ -1870,11 +1870,11 @@
"telegramValue": "{channel} / {status}",
"telegramDetail": "類型 {type};出站 {outbound};最新 {latest}",
"aiTitle": "AI 處置判定",
"aiDetail": "狀態 {state};下一步 {nextStep}人工 {needsHuman}",
"aiDetail": "狀態 {state};下一步 {nextStep}受控分流 {controlledReview}",
"sourceTitle": "Sentry / SigNoz 匹配",
"sourceDetail": "直連 {direct} / 候選 {candidate} / 已套用 {applied};原因 {reason}",
"needsHumanYes": "需要",
"needsHumanNo": "不需要",
"controlledReviewYes": "AI 受控覆核 / critical evidence",
"controlledReviewNo": "AI 受控鏈路",
"stateLabels": {
"verificationDegradedManualRequired": "驗證退化AI 進入 verifier / rollback",
"verificationDegradedAiVerifierRequired": "驗證退化AI 進入 verifier / rollback",
@@ -1895,21 +1895,21 @@
},
"handoff": {
"eyebrow": "現在要做",
"titleManual": "需要 break-glass 確認",
"titleControlledReview": "AI 受控覆核critical 才 break-glass",
"titleAutomated": "自動鏈路已完成,持續觀察",
"titleUnknown": "等待 truth-chain 資料",
"actionManualVerifyOrRepair": "到 AwoooP Work Items / Runs 確認執行證據;若服務仍異常,排入 AI 受控重試或 rollback,不要直接靜默關閉。",
"actionControlledVerifyOrRepair": "到 AwoooP Work Items / Runs 確認執行證據;若服務仍異常,排入 AI 受控重試、verifier 或 rollback。",
"actionNoManual": "目前由 AI 受控鏈路處理保留真相鏈與Run history 供稽核追蹤。",
"actionUnknown": "尚未拿到完整狀態,先等 status-chain 載入完成。",
"ownerLabel": "主責",
"ownerSre": "SRE owner / AwoooP operator",
"ownerControlledReview": "AI controlled queue / SRE break-glass only",
"ownerAutomation": "AI 自動化鏈路",
"entryLabel": "處理入口",
"entryManual": "Work Items / Approvals / Runs",
"entryControlledReview": "Work Items / Runs / verifier",
"entryReadOnly": "Runs / History",
"reasonLabel": "原因",
"boundaryLabel": "邊界",
"boundary": "只讀追蹤,不觸發修復"
"boundary": "低 / 中 / 高走 AI controlledcritical 才 break-glass"
},
"repeatStates": {
"duplicate": "最新入站重複",
@@ -2291,8 +2291,8 @@
"loadFailed": "焦點 Incident 資料讀取失敗:{error}",
"boundary": "此區塊只讀取監控證據,不會自動標記 Sentry/SigNoz 已匹配,也不會觸發修復或靜音告警。最新 PlayBook{playbook}executor{executor}。",
"human": {
"yes": "需要人工",
"no": "未要求人工"
"yes": "AI 受控覆核",
"no": "AI 受控鏈路"
},
"links": {
"workItems": "工作項",
@@ -2329,7 +2329,7 @@
"ansibleDetail": "模式 {mode}、回傳碼 {rc}、套用 {apply}",
"km": "KM",
"kmDetail": "驗證 {verification};下一步 {next}",
"handoff": "交接狀態"
"handoff": "受控分流"
},
"providerEvidence": {
"title": "供應者匹配狀態",

View File

@@ -1870,11 +1870,11 @@
"telegramValue": "{channel} / {status}",
"telegramDetail": "類型 {type};出站 {outbound};最新 {latest}",
"aiTitle": "AI 處置判定",
"aiDetail": "狀態 {state};下一步 {nextStep}人工 {needsHuman}",
"aiDetail": "狀態 {state};下一步 {nextStep}受控分流 {controlledReview}",
"sourceTitle": "Sentry / SigNoz 匹配",
"sourceDetail": "直連 {direct} / 候選 {candidate} / 已套用 {applied};原因 {reason}",
"needsHumanYes": "需要",
"needsHumanNo": "不需要",
"controlledReviewYes": "AI 受控覆核 / critical evidence",
"controlledReviewNo": "AI 受控鏈路",
"stateLabels": {
"verificationDegradedManualRequired": "驗證退化AI 進入 verifier / rollback",
"verificationDegradedAiVerifierRequired": "驗證退化AI 進入 verifier / rollback",
@@ -1895,21 +1895,21 @@
},
"handoff": {
"eyebrow": "現在要做",
"titleManual": "需要 break-glass 確認",
"titleControlledReview": "AI 受控覆核critical 才 break-glass",
"titleAutomated": "自動鏈路已完成,持續觀察",
"titleUnknown": "等待 truth-chain 資料",
"actionManualVerifyOrRepair": "到 AwoooP Work Items / Runs 確認執行證據;若服務仍異常,排入 AI 受控重試或 rollback,不要直接靜默關閉。",
"actionControlledVerifyOrRepair": "到 AwoooP Work Items / Runs 確認執行證據;若服務仍異常,排入 AI 受控重試、verifier 或 rollback。",
"actionNoManual": "目前由 AI 受控鏈路處理保留真相鏈與Run history 供稽核追蹤。",
"actionUnknown": "尚未拿到完整狀態,先等 status-chain 載入完成。",
"ownerLabel": "主責",
"ownerSre": "SRE owner / AwoooP operator",
"ownerControlledReview": "AI controlled queue / SRE break-glass only",
"ownerAutomation": "AI 自動化鏈路",
"entryLabel": "處理入口",
"entryManual": "Work Items / Approvals / Runs",
"entryControlledReview": "Work Items / Runs / verifier",
"entryReadOnly": "Runs / History",
"reasonLabel": "原因",
"boundaryLabel": "邊界",
"boundary": "只讀追蹤,不觸發修復"
"boundary": "低 / 中 / 高走 AI controlledcritical 才 break-glass"
},
"repeatStates": {
"duplicate": "最新入站重複",
@@ -2291,8 +2291,8 @@
"loadFailed": "焦點 Incident 資料讀取失敗:{error}",
"boundary": "此區塊只讀取監控證據,不會自動標記 Sentry/SigNoz 已匹配,也不會觸發修復或靜音告警。最新 PlayBook{playbook}executor{executor}。",
"human": {
"yes": "需要人工",
"no": "未要求人工"
"yes": "AI 受控覆核",
"no": "AI 受控鏈路"
},
"links": {
"workItems": "工作項",
@@ -2329,7 +2329,7 @@
"ansibleDetail": "模式 {mode}、回傳碼 {rc}、套用 {apply}",
"km": "KM",
"kmDetail": "驗證 {verification};下一步 {next}",
"handoff": "交接狀態"
"handoff": "受控分流"
},
"providerEvidence": {
"title": "供應者匹配狀態",

View File

@@ -245,25 +245,27 @@ function FocusIncidentEvidencePanel({
const latestOutboundLabel = latestOutbound?.sent_at
? formatTimestamp(latestOutbound.sent_at, locale, emptyLabel)
: emptyLabel
const needsHumanLabel = chain?.needs_human ? t('operatorFlow.needsHumanYes') : t('operatorFlow.needsHumanNo')
const handoffTone = !chain ? 'gray' : chain.needs_human ? 'red' : 'green'
const controlledReviewLabel = chain?.needs_human
? t('operatorFlow.controlledReviewYes')
: t('operatorFlow.controlledReviewNo')
const handoffTone = !chain ? 'gray' : chain.needs_human ? 'amber' : 'green'
const handoffTitle = chain?.needs_human
? t('operatorFlow.handoff.titleManual')
? t('operatorFlow.handoff.titleControlledReview')
: chain
? t('operatorFlow.handoff.titleAutomated')
: t('operatorFlow.handoff.titleUnknown')
const handoffAction = !chain
? t('operatorFlow.handoff.actionUnknown')
: chain.needs_human
? t('operatorFlow.handoff.actionManualVerifyOrRepair')
? t('operatorFlow.handoff.actionControlledVerifyOrRepair')
: t('operatorFlow.handoff.actionNoManual')
const handoffOwner = chain?.needs_human
? t('operatorFlow.handoff.ownerSre')
? t('operatorFlow.handoff.ownerControlledReview')
: chain
? t('operatorFlow.handoff.ownerAutomation')
: emptyLabel
const handoffEntry = chain?.needs_human
? t('operatorFlow.handoff.entryManual')
? t('operatorFlow.handoff.entryControlledReview')
: chain
? t('operatorFlow.handoff.entryReadOnly')
: emptyLabel
@@ -328,9 +330,9 @@ function FocusIncidentEvidencePanel({
detail: t('operatorFlow.aiDetail', {
state: outcomeStateLabel,
nextStep: nextActionLabel,
needsHuman: needsHumanLabel,
controlledReview: controlledReviewLabel,
}),
tone: chain?.needs_human ? 'red' : chain ? 'green' : 'gray',
tone: chain?.needs_human ? 'amber' : chain ? 'green' : 'gray',
testId: 'alerts-ai-state',
},
{
@@ -467,7 +469,7 @@ function FocusIncidentEvidencePanel({
className={cn(
'mb-3 border px-3 py-3',
handoffTone === 'green' && 'border-[#9bc7a4] bg-[#f0faf2]',
handoffTone === 'red' && 'border-[#e2a29b] bg-[#fff0ef]',
handoffTone === 'amber' && 'border-[#d9b36f] bg-[#fff7e8]',
handoffTone === 'gray' && 'border-[#d8d3c7] bg-[#faf9f3]',
)}
>

View File

@@ -247,7 +247,7 @@ function IncidentObservabilityFocus({
const ansibleTone: EvidenceTone = ansible?.applied || (ansible?.apply_total ?? 0) > 0
? 'success'
: (ansible?.considered || (ansible?.record_total ?? 0) > 0 ? 'warning' : 'neutral')
const handoffTone: EvidenceTone = chain?.needs_human ? 'blocked' : (chain ? 'success' : 'neutral')
const handoffTone: EvidenceTone = chain?.needs_human ? 'warning' : (chain ? 'success' : 'neutral')
const navItems = [
{