feat(web): surface incident automation evidence counts
All checks were successful
Code Review / ai-code-review (push) Successful in 11s
CD Pipeline / tests (push) Successful in 3m52s
CD Pipeline / build-and-deploy (push) Successful in 3m26s
CD Pipeline / post-deploy-checks (push) Successful in 1m53s

This commit is contained in:
Your Name
2026-05-20 14:40:53 +08:00
parent b9a0f289b2
commit 2eaffe07aa
3 changed files with 48 additions and 0 deletions

View File

@@ -427,6 +427,10 @@
"flowSourceTruthChain": "truth-chain / ADR-100",
"flowSourceHeuristic": "incident status heuristic",
"flowVerdictLabel": "Verdict",
"flowEvidenceMcp": "MCP {count}",
"flowEvidenceOps": "Ops {count}",
"flowEvidenceKm": "KM {count}",
"flowEvidenceRepair": "Repair {count}",
"flowTruthChainCurrent": "{stage} / {status}",
"flowComplete": "Complete",
"flowStages": {

View File

@@ -428,6 +428,10 @@
"flowSourceTruthChain": "truth-chain / ADR-100",
"flowSourceHeuristic": "事件狀態推導",
"flowVerdictLabel": "判定",
"flowEvidenceMcp": "MCP {count}",
"flowEvidenceOps": "操作 {count}",
"flowEvidenceKm": "KM {count}",
"flowEvidenceRepair": "修復 {count}",
"flowTruthChainCurrent": "{stage} / {status}",
"flowComplete": "已完成",
"flowStages": {

View File

@@ -313,6 +313,28 @@ export function IncidentCard({ incident, decision, statusChain, onApprovalChange
? chainValue(statusChain?.next_step)
: nextStage ? flowStageLabels[nextStage] : t('flowComplete')
const flowSourceText = hasTruthChain ? t('flowSourceTruthChain') : t('flowSourceHeuristic')
const statusChainEvidenceItems = hasTruthChain ? [
{
key: 'mcp',
label: t('flowEvidenceMcp', { count: statusChain?.evidence?.mcp_gateway_total ?? 0 }),
active: (statusChain?.evidence?.mcp_gateway_total ?? 0) > 0,
},
{
key: 'ops',
label: t('flowEvidenceOps', { count: statusChain?.evidence?.operation_records ?? 0 }),
active: (statusChain?.evidence?.operation_records ?? 0) > 0,
},
{
key: 'km',
label: t('flowEvidenceKm', { count: statusChain?.evidence?.knowledge_entries ?? 0 }),
active: (statusChain?.evidence?.knowledge_entries ?? 0) > 0,
},
{
key: 'repair',
label: t('flowEvidenceRepair', { count: statusChain?.evidence?.auto_repair_records ?? 0 }),
active: (statusChain?.evidence?.auto_repair_records ?? 0) > 0,
},
] : []
const serviceName = incident.affected_services?.[0] ?? '--'
const duration = formatDuration(incident.created_at)
@@ -566,6 +588,24 @@ export function IncidentCard({ incident, decision, statusChain, onApprovalChange
<span>
{t('flowVerdictLabel')}: <strong style={{ color: statusChain?.needs_human ? '#9f2f25' : '#17602a' }}>{chainValue(statusChain?.verdict)}</strong>
</span>
<span style={{ color: '#b0ad9f' }}>/</span>
<span data-testid="incident-flow-evidence" style={{ display: 'flex', alignItems: 'center', gap: 5, flexWrap: 'wrap' }}>
{statusChainEvidenceItems.map(item => (
<strong
key={item.key}
style={{
color: item.active ? '#17602a' : '#87867f',
background: item.active ? 'rgba(34,197,94,0.08)' : '#f5f4ed',
border: '0.5px solid #e0ddd4',
borderRadius: 4,
padding: '1px 5px',
fontWeight: 600,
}}
>
{item.label}
</strong>
))}
</span>
</>
)}
</div>