feat(governance): show AI agent workload split
This commit is contained in:
@@ -3611,6 +3611,45 @@
|
|||||||
"next": "下一步:{gates} 個 learning / trust gate 未打開。"
|
"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": {
|
"executionQueue": {
|
||||||
"title": "全面授權後推進佇列",
|
"title": "全面授權後推進佇列",
|
||||||
"badge": "低中風險自動準備 · 高風險等審核",
|
"badge": "低中風險自動準備 · 高風險等審核",
|
||||||
|
|||||||
@@ -3611,6 +3611,45 @@
|
|||||||
"next": "下一步:{gates} 個 learning / trust gate 未打開。"
|
"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": {
|
"executionQueue": {
|
||||||
"title": "全面授權後推進佇列",
|
"title": "全面授權後推進佇列",
|
||||||
"badge": "低中風險自動準備 · 高風險等審核",
|
"badge": "低中風險自動準備 · 高風險等審核",
|
||||||
|
|||||||
@@ -5465,6 +5465,126 @@ export function AutomationInventoryTab() {
|
|||||||
)
|
)
|
||||||
const globalControlQueueOwnerReview = highRiskOwnerQueueItems + reportRuntimeApprovals + runtimeShadowApprovals + learningWritebackApprovals
|
const globalControlQueueOwnerReview = highRiskOwnerQueueItems + reportRuntimeApprovals + runtimeShadowApprovals + learningWritebackApprovals
|
||||||
const globalControlQueueBlocked = highRiskOwnerQueueBlocked + operationPermissionBlocked + runtimeShadowBlocked + reportRuntimeBlocked
|
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<{
|
const globalControlExecutionQueueRows: Array<{
|
||||||
key: string
|
key: string
|
||||||
label: string
|
label: string
|
||||||
@@ -5803,6 +5923,70 @@ export function AutomationInventoryTab() {
|
|||||||
</div>
|
</div>
|
||||||
</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={{ 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', alignItems: 'flex-start', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
|
<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-grid,
|
||||||
.automation-inventory-global-control-pipeline-grid,
|
.automation-inventory-global-control-pipeline-grid,
|
||||||
.automation-inventory-global-control-runway-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-grid,
|
||||||
.automation-inventory-global-control-execution-queue-meta-grid,
|
.automation-inventory-global-control-execution-queue-meta-grid,
|
||||||
.automation-inventory-global-control-domain-grid,
|
.automation-inventory-global-control-domain-grid,
|
||||||
|
|||||||
Reference in New Issue
Block a user