feat(governance): show AI agent workload split
All checks were successful
CD Pipeline / tests (push) Successful in 1m43s
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / build-and-deploy (push) Successful in 4m42s
CD Pipeline / post-deploy-checks (push) Successful in 1m44s

This commit is contained in:
Your Name
2026-06-26 07:25:14 +08:00
parent 12d93b7583
commit a2092ce581
3 changed files with 263 additions and 0 deletions

View File

@@ -3611,6 +3611,45 @@
"next": "下一步:{gates} 個 learning / trust gate 未打開。"
}
},
"agentWorkload": {
"title": "AI Agent 工作量與專業分工",
"badge": "OpenClaw / Hermes / Nemotron / Security-SRE",
"summary": "目前可見工作量 {workload} 件;其中負責人審核 {review} 件、阻擋 {blocked} 件,正式寫入 / Telegram / 機密讀取 / 破壞性操作邊界總數 {live}。",
"labels": {
"review": "審核 {count}",
"blocked": "阻擋 {count}"
},
"agents": {
"openclaw": {
"label": "OpenClaw",
"mission": "仲裁、風險分級、乾跑候選與負責人審核包主責;不靠身份保護,仍接受市場與回放數據挑戰。",
"telegram": "Telegram{reviews} 件需審核時只產摘要/批准包,不直接發正式處置。",
"learning": "學習:承接 {candidates} 個 PlayBook / KM 候選,等待 gate 後寫回。",
"next": "下一步:整理 {dryRuns} 個乾跑候選與 {high} 個高風險審核包。"
},
"hermes": {
"label": "Hermes",
"mission": "報告、圖表、回執、RAG / KM 摘要與 Telegram 無發送預覽主責。",
"telegram": "Telegram{drafts} 個佇列草稿先做無發送預覽,正式發送仍需 gate。",
"learning": "學習KM draft {km} 筆learning gate {gates} 個未開。",
"next": "下一步:產 {reports} 份報告資產與 {charts} 個圖表來源。"
},
"nemotron": {
"label": "Nemotron",
"mission": "市場版本雷達、回放、shadow scorecard 與模型候選比較主責;未通過 gate 不切 provider。",
"telegram": "Telegram{replays} 次回放只進摘要候選,不做正式發送。",
"learning": "學習:市場候選 {market}、版本漂移 {drift} 形成比較證據。",
"next": "下一步shadow 通過 {passed}/{total},未批准前不升級路由。"
},
"securitySre": {
"label": "Security / SRE",
"mission": "權限模型、主機/服務 gate、執行期寫入邊界、Verifier 與回滾檢查主責。",
"telegram": "Telegram{gates} 條 gate 只產風險/批准摘要,禁止直接 Bot API 操作。",
"learning": "學習Verifier / 服務健康證據 {verifiers} 筆進入審計與回寫候選。",
"next": "下一步:{blocked} 個被阻擋的執行期 / 寫入類別維持預設關閉。"
}
}
},
"executionQueue": {
"title": "全面授權後推進佇列",
"badge": "低中風險自動準備 · 高風險等審核",

View File

@@ -3611,6 +3611,45 @@
"next": "下一步:{gates} 個 learning / trust gate 未打開。"
}
},
"agentWorkload": {
"title": "AI Agent 工作量與專業分工",
"badge": "OpenClaw / Hermes / Nemotron / Security-SRE",
"summary": "目前可見工作量 {workload} 件;其中負責人審核 {review} 件、阻擋 {blocked} 件,正式寫入 / Telegram / 機密讀取 / 破壞性操作邊界總數 {live}。",
"labels": {
"review": "審核 {count}",
"blocked": "阻擋 {count}"
},
"agents": {
"openclaw": {
"label": "OpenClaw",
"mission": "仲裁、風險分級、乾跑候選與負責人審核包主責;不靠身份保護,仍接受市場與回放數據挑戰。",
"telegram": "Telegram{reviews} 件需審核時只產摘要/批准包,不直接發正式處置。",
"learning": "學習:承接 {candidates} 個 PlayBook / KM 候選,等待 gate 後寫回。",
"next": "下一步:整理 {dryRuns} 個乾跑候選與 {high} 個高風險審核包。"
},
"hermes": {
"label": "Hermes",
"mission": "報告、圖表、回執、RAG / KM 摘要與 Telegram 無發送預覽主責。",
"telegram": "Telegram{drafts} 個佇列草稿先做無發送預覽,正式發送仍需 gate。",
"learning": "學習KM draft {km} 筆learning gate {gates} 個未開。",
"next": "下一步:產 {reports} 份報告資產與 {charts} 個圖表來源。"
},
"nemotron": {
"label": "Nemotron",
"mission": "市場版本雷達、回放、shadow scorecard 與模型候選比較主責;未通過 gate 不切 provider。",
"telegram": "Telegram{replays} 次回放只進摘要候選,不做正式發送。",
"learning": "學習:市場候選 {market}、版本漂移 {drift} 形成比較證據。",
"next": "下一步shadow 通過 {passed}/{total},未批准前不升級路由。"
},
"securitySre": {
"label": "Security / SRE",
"mission": "權限模型、主機/服務 gate、執行期寫入邊界、Verifier 與回滾檢查主責。",
"telegram": "Telegram{gates} 條 gate 只產風險/批准摘要,禁止直接 Bot API 操作。",
"learning": "學習Verifier / 服務健康證據 {verifiers} 筆進入審計與回寫候選。",
"next": "下一步:{blocked} 個被阻擋的執行期 / 寫入類別維持預設關閉。"
}
}
},
"executionQueue": {
"title": "全面授權後推進佇列",
"badge": "低中風險自動準備 · 高風險等審核",

View File

@@ -5465,6 +5465,126 @@ export function AutomationInventoryTab() {
)
const globalControlQueueOwnerReview = highRiskOwnerQueueItems + reportRuntimeApprovals + runtimeShadowApprovals + learningWritebackApprovals
const globalControlQueueBlocked = highRiskOwnerQueueBlocked + operationPermissionBlocked + runtimeShadowBlocked + reportRuntimeBlocked
const openClawWorkload = (
serviceHealthActions
+ candidateDryRunNeedsReview
+ lowMediumWhitelistCandidates
+ highRiskOwnerQueueItems
+ operationPermissionHumanApproval
+ explicitApprovalTaskCount
)
const openClawOwnerReview = (
candidateDryRunNeedsReview
+ highRiskOwnerQueueItems
+ operationPermissionHumanApproval
)
const hermesWorkload = (
reportRuntimeReady
+ reportDryRunArtifacts
+ reportDryRunQueueDrafts
+ matchedPlaybookCandidates
+ taskResultKmDrafts
+ hostStatefulInventory.rollups.readonly_probe_step_count
)
const hermesOwnerReview = reportRuntimeApprovals + reportDryRunApprovals + reportFixtureApprovals + learningWritebackApprovals
const nemotronWorkload = (
runtimeShadowCandidates
+ runtimeShadowReplays
+ dependencySupplyChainDriftMonitor.rollups.drift_candidate_count
+ warRoomMarketCandidates
+ providerRouteGateApprovals
)
const nemotronOwnerReview = runtimeShadowApprovals + providerRouteGateApprovals + dependencySupplyChainDriftMonitor.rollups.blocked_operation_count
const securitySreWorkload = (
operationPermissionCategories
+ highRiskOwnerQueueItems
+ serviceHealthOperatorReviews
+ giteaRunnerActions
+ runtimeWriteApprovals
)
const securitySreOwnerReview = operationPermissionHumanApproval + highRiskOwnerQueueItems + runtimeWriteApprovals
const agentWorkloadTotal = openClawWorkload + hermesWorkload + nemotronWorkload + securitySreWorkload
const agentWorkloadOwnerReviewTotal = openClawOwnerReview + hermesOwnerReview + nemotronOwnerReview + securitySreOwnerReview
const agentWorkloadBlockedTotal = (
highRiskOwnerQueueBlocked
+ operationPermissionBlocked
+ runtimeShadowBlocked
+ reportRuntimeBlocked
+ lowMediumWhitelistBlocked
+ dependencySupplyChainDriftMonitor.rollups.blocked_operation_count
)
const agentWorkloadLiveBoundaryTotal = (
globalControlLiveWriteAllowedTotal
+ globalControlTelegramSendTotal
+ operationPermissionSecretReads
+ operationPermissionDestructive
)
const globalControlAgentWorkloadRows: Array<{
key: string
label: string
mission: string
workload: number
ownerReview: number
blocked: number
telegram: string
learning: string
next: string
tone: 'ok' | 'warn' | 'danger' | 'neutral'
icon: ReactNode
}> = [
{
key: 'openclaw',
label: t('globalControl.agentWorkload.agents.openclaw.label'),
mission: t('globalControl.agentWorkload.agents.openclaw.mission'),
workload: openClawWorkload,
ownerReview: openClawOwnerReview,
blocked: highRiskOwnerQueueBlocked + operationPermissionBlocked + lowMediumWhitelistBlocked,
telegram: t('globalControl.agentWorkload.agents.openclaw.telegram', { reviews: openClawOwnerReview }),
learning: t('globalControl.agentWorkload.agents.openclaw.learning', { candidates: matchedPlaybookCandidates + taskResultKmDrafts }),
next: t('globalControl.agentWorkload.agents.openclaw.next', { dryRuns: candidateDryRunNeedsReview, high: highRiskOwnerQueueItems }),
tone: openClawOwnerReview + highRiskOwnerQueueBlocked + operationPermissionBlocked > 0 ? 'warn' : 'ok',
icon: <Target size={15} />,
},
{
key: 'hermes',
label: t('globalControl.agentWorkload.agents.hermes.label'),
mission: t('globalControl.agentWorkload.agents.hermes.mission'),
workload: hermesWorkload,
ownerReview: hermesOwnerReview,
blocked: reportRuntimeBlocked + learningWritebackBlockedWrites + taskResultBlocked,
telegram: t('globalControl.agentWorkload.agents.hermes.telegram', { drafts: reportDryRunQueueDrafts }),
learning: t('globalControl.agentWorkload.agents.hermes.learning', { km: taskResultKmDrafts, gates: learningWritebackApprovals }),
next: t('globalControl.agentWorkload.agents.hermes.next', { reports: reportDryRunArtifacts, charts: visibleReportStatusCharts.length + visibleReportCharts.length }),
tone: hermesOwnerReview + reportRuntimeBlocked + learningWritebackApprovals > 0 ? 'warn' : 'ok',
icon: <MessageSquareText size={15} />,
},
{
key: 'nemotron',
label: t('globalControl.agentWorkload.agents.nemotron.label'),
mission: t('globalControl.agentWorkload.agents.nemotron.mission'),
workload: nemotronWorkload,
ownerReview: nemotronOwnerReview,
blocked: runtimeShadowBlocked + dependencySupplyChainDriftMonitor.rollups.blocked_operation_count + providerRouteDeniedCount,
telegram: t('globalControl.agentWorkload.agents.nemotron.telegram', { replays: runtimeShadowReplays }),
learning: t('globalControl.agentWorkload.agents.nemotron.learning', { market: warRoomMarketCandidates, drift: dependencySupplyChainDriftMonitor.rollups.drift_candidate_count }),
next: t('globalControl.agentWorkload.agents.nemotron.next', { passed: runtimeShadowPassed, total: runtimeShadowCandidates }),
tone: runtimeShadowBlocked + nemotronOwnerReview > 0 ? 'warn' : 'ok',
icon: <RefreshCw size={15} />,
},
{
key: 'securitySre',
label: t('globalControl.agentWorkload.agents.securitySre.label'),
mission: t('globalControl.agentWorkload.agents.securitySre.mission'),
workload: securitySreWorkload,
ownerReview: securitySreOwnerReview,
blocked: operationPermissionBlocked + runtimeWriteBlockedActions + serviceHealthOperatorReviews,
telegram: t('globalControl.agentWorkload.agents.securitySre.telegram', { gates: operationPermissionGates }),
learning: t('globalControl.agentWorkload.agents.securitySre.learning', { verifiers: serviceHealthOperatorReviews + runtimeVerifierActions }),
next: t('globalControl.agentWorkload.agents.securitySre.next', { blocked: operationPermissionBlocked + runtimeWriteBlockedActions }),
tone: operationPermissionBlocked + runtimeWriteBlockedActions + highRiskOwnerQueueItems > 0 ? 'danger' : 'ok',
icon: <ShieldAlert size={15} />,
},
]
const globalControlExecutionQueueRows: Array<{
key: string
label: string
@@ -5803,6 +5923,70 @@ export function AutomationInventoryTab() {
</div>
</div>
<div style={{ padding: 12, border: '0.5px solid #d7d2f4', borderRadius: 7, background: '#fbfaff', display: 'flex', flexDirection: 'column', gap: 11, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
<SmallLabel>{t('globalControl.agentWorkload.title')}</SmallLabel>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#625f78', lineHeight: 1.5, overflowWrap: 'anywhere' }}>
{t('globalControl.agentWorkload.summary', {
workload: agentWorkloadTotal,
review: agentWorkloadOwnerReviewTotal,
blocked: agentWorkloadBlockedTotal,
live: agentWorkloadLiveBoundaryTotal,
})}
</span>
</div>
<Chip value={t('globalControl.agentWorkload.badge')} muted />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 10 }} className="automation-inventory-global-control-agent-workload-grid">
{globalControlAgentWorkloadRows.map(row => {
const color = toneColor(row.tone)
return (
<div key={row.key} style={{ padding: 11, border: `0.5px solid ${color}44`, borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'flex-start', minWidth: 0 }}>
<div style={{ display: 'flex', gap: 7, alignItems: 'center', minWidth: 0 }}>
<div style={{
width: 28,
height: 28,
borderRadius: 7,
border: `0.5px solid ${color}55`,
background: `${color}12`,
color,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}}>
{row.icon}
</div>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 760, color: '#141413', lineHeight: 1.2, overflowWrap: 'anywhere' }}>
{row.label}
</span>
</div>
<Chip value={String(row.workload)} muted={row.tone === 'ok'} />
</div>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#625f78', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{row.mission}
</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
<Chip value={t('globalControl.agentWorkload.labels.review', { count: row.ownerReview })} muted />
<Chip value={t('globalControl.agentWorkload.labels.blocked', { count: row.blocked })} muted={row.blocked === 0} />
</div>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#625f78', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{row.telegram}
</span>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#625f78', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{row.learning}
</span>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color, fontWeight: 700, lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{row.next}
</span>
</div>
)
})}
</div>
</div>
<div style={{ padding: 12, border: '0.5px solid #eee1c8', borderRadius: 7, background: '#fffdf7', display: 'flex', flexDirection: 'column', gap: 11, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
@@ -18577,6 +18761,7 @@ export function AutomationInventoryTab() {
.automation-inventory-global-control-grid,
.automation-inventory-global-control-pipeline-grid,
.automation-inventory-global-control-runway-grid,
.automation-inventory-global-control-agent-workload-grid,
.automation-inventory-global-control-execution-queue-grid,
.automation-inventory-global-control-execution-queue-meta-grid,
.automation-inventory-global-control-domain-grid,