feat(governance): 顯示 AI Agents 全域控管總盤
This commit is contained in:
@@ -3569,6 +3569,157 @@
|
||||
"taskBoundaries": "任務邊界",
|
||||
"explicitApprovalTasks": "需明確批准"
|
||||
},
|
||||
"globalControl": {
|
||||
"title": "AI Agents 全域控管總盤",
|
||||
"subtitle": "八大範圍已納入只讀控管視圖;目前 {domains}/8 domain 可見,{gates} 個 gate 待審,正式寫入/直送總數 {live}。",
|
||||
"pipelineTitle": "MASTER 自主化飛輪",
|
||||
"pipelineBadge": "Sensor → Gate → Verifier",
|
||||
"boundaryTitle": "真實邊界",
|
||||
"boundaryBadge": "不誇大接管",
|
||||
"badges": {
|
||||
"readOnly": "全域只讀控管",
|
||||
"noTranscript": "只顯示脫敏治理狀態",
|
||||
"noLiveWrite": "正式寫入 {value}"
|
||||
},
|
||||
"metrics": {
|
||||
"domains": "納管範圍",
|
||||
"assets": "資產",
|
||||
"runtime": "Runtime surfaces",
|
||||
"candidates": "候選操作",
|
||||
"gates": "審核 gate",
|
||||
"liveWrites": "正式寫入"
|
||||
},
|
||||
"telegram": {
|
||||
"digestOnly": "Telegram 摘要候選",
|
||||
"failureOnly": "失敗/需處置才通知",
|
||||
"approvalRequired": "批准後才通知",
|
||||
"notifyBridge": "Notify bridge 受控",
|
||||
"ownerGate": "Owner gate 後通知"
|
||||
},
|
||||
"learning": {
|
||||
"ownerReview": "維護窗與 owner review 寫回待批准。",
|
||||
"snapshot": "以 committed snapshot 累積資產知識。",
|
||||
"redactedEvidence": "只寫入脫敏證據,不寫入對話內容。",
|
||||
"versionRadar": "版本雷達產生候選,升級仍需 gate。",
|
||||
"healthLoop": "服務健康差距進入候選修復迴圈。",
|
||||
"noiseReduction": "降噪提案進入審核與回放。",
|
||||
"agentMemory": "Agent 互動與任務成果只保留脫敏摘要。",
|
||||
"marketRadar": "市場雷達只形成比較證據與 canary 申請。"
|
||||
},
|
||||
"domains": {
|
||||
"hosts": {
|
||||
"label": "主機與 Stateful 服務",
|
||||
"scope": "主機 {hosts} · K3s node {nodes} · Stateful {stateful}",
|
||||
"sensor": "只讀探針 {probes} 個,禁止 SSH / kubectl 寫入。",
|
||||
"candidate": "維護窗必填欄位 {fields} 個,先產批准包。",
|
||||
"gate": "未授權寫入/重啟/升級允許數 {writes}。",
|
||||
"telegram": "直送 {direct} · 佇列 {queue}"
|
||||
},
|
||||
"products": {
|
||||
"label": "產品與專案",
|
||||
"scope": "資產 {assets} · domain {domains}",
|
||||
"sensor": "工作流 {workstreams} 條,統一進入治理台帳。",
|
||||
"candidate": "任務 {tasks} 筆,按優先序與 gate 推進。",
|
||||
"gate": "需明確批准任務 {approvals} 筆。"
|
||||
},
|
||||
"websites": {
|
||||
"label": "網站前後台",
|
||||
"scope": "Web 資產 {websites} · source/runtime component {runtime}",
|
||||
"sensor": "Runtime binding {bound}/{total},缺口列入證據。",
|
||||
"candidate": "Live check 缺口 {missing} 個,先補讀回。",
|
||||
"gate": "Secret surface {secrets} 個,只顯示名稱或模板。"
|
||||
},
|
||||
"packages": {
|
||||
"label": "套件與供應鏈",
|
||||
"scope": "來源快照 {sources} · 監控檢查 {checks}",
|
||||
"sensor": "過期來源 {stale} 個,外部查詢仍受 gate。",
|
||||
"candidate": "漂移/升級候選 {candidates} 個。",
|
||||
"gate": "被阻擋操作 {blocked} 個,禁止自動升版。"
|
||||
},
|
||||
"services": {
|
||||
"label": "服務健康與 API",
|
||||
"scope": "健康目標 {targets} · runtime surface {surfaces}",
|
||||
"sensor": "需處置 {action} · stale endpoint {stale}。",
|
||||
"candidate": "健康 gap {gaps} 個,先產修復候選。",
|
||||
"gate": "重啟、端點變更、runtime 執行允許數 {allowed}。",
|
||||
"telegram": "立即升級 {escalation} · 成功降噪 {quiet}"
|
||||
},
|
||||
"tools": {
|
||||
"label": "工具、CI/CD 與觀測",
|
||||
"scope": "Workflow {workflows} · 觀測 surface {observability}",
|
||||
"sensor": "Runner attestation 缺口 {runners} 個。",
|
||||
"candidate": "降噪/觀測優化候選 {opportunities} 個。",
|
||||
"gate": "觀測變更需批准 {approvals} 個。"
|
||||
},
|
||||
"agents": {
|
||||
"label": "OpenClaw / Hermes / Nemotron",
|
||||
"scope": "Agent role {roles} · 專業任務 {tasks}",
|
||||
"sensor": "12-agent 批次 {batches} 批,只保留狀態。",
|
||||
"candidate": "高/關鍵風險專業任務 {high} 個。",
|
||||
"gate": "Agent 執行批准 gate {approvals} 個。",
|
||||
"telegram": "Telegram 無發送預覽 {previews} 則"
|
||||
},
|
||||
"aiSolutions": {
|
||||
"label": "AI Agent 與 AI 解決方案",
|
||||
"scope": "Provider route {routes} · 版本 domain {domains}",
|
||||
"sensor": "市場候選 {candidates} 個,需 replay/canary。",
|
||||
"candidate": "候選 provider gate {gates} 個。",
|
||||
"gate": "provider switch / paid API / shadow 允許數 {denied}。"
|
||||
}
|
||||
},
|
||||
"pipeline": {
|
||||
"sensor": {
|
||||
"label": "Sensor",
|
||||
"detail": "資產台帳 {assets} 筆已進只讀感測。"
|
||||
},
|
||||
"normalizer": {
|
||||
"label": "Normalizer",
|
||||
"detail": "任務狀態 {statuses} 種,統一狀態分類。"
|
||||
},
|
||||
"aiLane": {
|
||||
"label": "AI Lane",
|
||||
"detail": "佈建目標 {targets} 個,按專長分工。"
|
||||
},
|
||||
"candidate": {
|
||||
"label": "Candidate",
|
||||
"detail": "乾跑證據 {evidence} 筆,未過 gate 不執行。"
|
||||
},
|
||||
"gate": {
|
||||
"label": "Gate",
|
||||
"detail": "硬邊界 {blocked} 類,需 owner/風險 gate。"
|
||||
},
|
||||
"execution": {
|
||||
"label": "Execution Boundary",
|
||||
"detail": "Telegram 正式發送/Bot API 總數 {telegram}。"
|
||||
},
|
||||
"verifier": {
|
||||
"label": "Verifier",
|
||||
"detail": "release readback blocked {blocked}。"
|
||||
},
|
||||
"learning": {
|
||||
"label": "Learning",
|
||||
"detail": "學習寫回 gate {gates} 個,未批准為 0。"
|
||||
}
|
||||
},
|
||||
"boundaries": {
|
||||
"allScope": {
|
||||
"label": "全部納入控管視圖",
|
||||
"detail": "八大範圍已可見,但這不是全部自動執行。"
|
||||
},
|
||||
"notFullControl": {
|
||||
"label": "尚未全自動接管",
|
||||
"detail": "整體仍在 {gates} 個審核/授權 gate 前。"
|
||||
},
|
||||
"writes": {
|
||||
"label": "寫入與通知權限",
|
||||
"detail": "Telegram/Bot API 正式直送總數 {telegram},不得誤報已接通。"
|
||||
},
|
||||
"redaction": {
|
||||
"label": "前端脫敏",
|
||||
"detail": "host redaction={host} · agent redaction={agent}。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deploymentLayout": {
|
||||
"title": "OpenClaw / Hermes / NemoTron 佈建布局",
|
||||
"source": "{generated} · {current} → {next}",
|
||||
|
||||
@@ -3569,6 +3569,157 @@
|
||||
"taskBoundaries": "任務邊界",
|
||||
"explicitApprovalTasks": "需明確批准"
|
||||
},
|
||||
"globalControl": {
|
||||
"title": "AI Agents 全域控管總盤",
|
||||
"subtitle": "八大範圍已納入只讀控管視圖;目前 {domains}/8 domain 可見,{gates} 個 gate 待審,正式寫入/直送總數 {live}。",
|
||||
"pipelineTitle": "MASTER 自主化飛輪",
|
||||
"pipelineBadge": "Sensor → Gate → Verifier",
|
||||
"boundaryTitle": "真實邊界",
|
||||
"boundaryBadge": "不誇大接管",
|
||||
"badges": {
|
||||
"readOnly": "全域只讀控管",
|
||||
"noTranscript": "只顯示脫敏治理狀態",
|
||||
"noLiveWrite": "正式寫入 {value}"
|
||||
},
|
||||
"metrics": {
|
||||
"domains": "納管範圍",
|
||||
"assets": "資產",
|
||||
"runtime": "Runtime surfaces",
|
||||
"candidates": "候選操作",
|
||||
"gates": "審核 gate",
|
||||
"liveWrites": "正式寫入"
|
||||
},
|
||||
"telegram": {
|
||||
"digestOnly": "Telegram 摘要候選",
|
||||
"failureOnly": "失敗/需處置才通知",
|
||||
"approvalRequired": "批准後才通知",
|
||||
"notifyBridge": "Notify bridge 受控",
|
||||
"ownerGate": "Owner gate 後通知"
|
||||
},
|
||||
"learning": {
|
||||
"ownerReview": "維護窗與 owner review 寫回待批准。",
|
||||
"snapshot": "以 committed snapshot 累積資產知識。",
|
||||
"redactedEvidence": "只寫入脫敏證據,不寫入對話內容。",
|
||||
"versionRadar": "版本雷達產生候選,升級仍需 gate。",
|
||||
"healthLoop": "服務健康差距進入候選修復迴圈。",
|
||||
"noiseReduction": "降噪提案進入審核與回放。",
|
||||
"agentMemory": "Agent 互動與任務成果只保留脫敏摘要。",
|
||||
"marketRadar": "市場雷達只形成比較證據與 canary 申請。"
|
||||
},
|
||||
"domains": {
|
||||
"hosts": {
|
||||
"label": "主機與 Stateful 服務",
|
||||
"scope": "主機 {hosts} · K3s node {nodes} · Stateful {stateful}",
|
||||
"sensor": "只讀探針 {probes} 個,禁止 SSH / kubectl 寫入。",
|
||||
"candidate": "維護窗必填欄位 {fields} 個,先產批准包。",
|
||||
"gate": "未授權寫入/重啟/升級允許數 {writes}。",
|
||||
"telegram": "直送 {direct} · 佇列 {queue}"
|
||||
},
|
||||
"products": {
|
||||
"label": "產品與專案",
|
||||
"scope": "資產 {assets} · domain {domains}",
|
||||
"sensor": "工作流 {workstreams} 條,統一進入治理台帳。",
|
||||
"candidate": "任務 {tasks} 筆,按優先序與 gate 推進。",
|
||||
"gate": "需明確批准任務 {approvals} 筆。"
|
||||
},
|
||||
"websites": {
|
||||
"label": "網站前後台",
|
||||
"scope": "Web 資產 {websites} · source/runtime component {runtime}",
|
||||
"sensor": "Runtime binding {bound}/{total},缺口列入證據。",
|
||||
"candidate": "Live check 缺口 {missing} 個,先補讀回。",
|
||||
"gate": "Secret surface {secrets} 個,只顯示名稱或模板。"
|
||||
},
|
||||
"packages": {
|
||||
"label": "套件與供應鏈",
|
||||
"scope": "來源快照 {sources} · 監控檢查 {checks}",
|
||||
"sensor": "過期來源 {stale} 個,外部查詢仍受 gate。",
|
||||
"candidate": "漂移/升級候選 {candidates} 個。",
|
||||
"gate": "被阻擋操作 {blocked} 個,禁止自動升版。"
|
||||
},
|
||||
"services": {
|
||||
"label": "服務健康與 API",
|
||||
"scope": "健康目標 {targets} · runtime surface {surfaces}",
|
||||
"sensor": "需處置 {action} · stale endpoint {stale}。",
|
||||
"candidate": "健康 gap {gaps} 個,先產修復候選。",
|
||||
"gate": "重啟、端點變更、runtime 執行允許數 {allowed}。",
|
||||
"telegram": "立即升級 {escalation} · 成功降噪 {quiet}"
|
||||
},
|
||||
"tools": {
|
||||
"label": "工具、CI/CD 與觀測",
|
||||
"scope": "Workflow {workflows} · 觀測 surface {observability}",
|
||||
"sensor": "Runner attestation 缺口 {runners} 個。",
|
||||
"candidate": "降噪/觀測優化候選 {opportunities} 個。",
|
||||
"gate": "觀測變更需批准 {approvals} 個。"
|
||||
},
|
||||
"agents": {
|
||||
"label": "OpenClaw / Hermes / Nemotron",
|
||||
"scope": "Agent role {roles} · 專業任務 {tasks}",
|
||||
"sensor": "12-agent 批次 {batches} 批,只保留狀態。",
|
||||
"candidate": "高/關鍵風險專業任務 {high} 個。",
|
||||
"gate": "Agent 執行批准 gate {approvals} 個。",
|
||||
"telegram": "Telegram 無發送預覽 {previews} 則"
|
||||
},
|
||||
"aiSolutions": {
|
||||
"label": "AI Agent 與 AI 解決方案",
|
||||
"scope": "Provider route {routes} · 版本 domain {domains}",
|
||||
"sensor": "市場候選 {candidates} 個,需 replay/canary。",
|
||||
"candidate": "候選 provider gate {gates} 個。",
|
||||
"gate": "provider switch / paid API / shadow 允許數 {denied}。"
|
||||
}
|
||||
},
|
||||
"pipeline": {
|
||||
"sensor": {
|
||||
"label": "Sensor",
|
||||
"detail": "資產台帳 {assets} 筆已進只讀感測。"
|
||||
},
|
||||
"normalizer": {
|
||||
"label": "Normalizer",
|
||||
"detail": "任務狀態 {statuses} 種,統一狀態分類。"
|
||||
},
|
||||
"aiLane": {
|
||||
"label": "AI Lane",
|
||||
"detail": "佈建目標 {targets} 個,按專長分工。"
|
||||
},
|
||||
"candidate": {
|
||||
"label": "Candidate",
|
||||
"detail": "乾跑證據 {evidence} 筆,未過 gate 不執行。"
|
||||
},
|
||||
"gate": {
|
||||
"label": "Gate",
|
||||
"detail": "硬邊界 {blocked} 類,需 owner/風險 gate。"
|
||||
},
|
||||
"execution": {
|
||||
"label": "Execution Boundary",
|
||||
"detail": "Telegram 正式發送/Bot API 總數 {telegram}。"
|
||||
},
|
||||
"verifier": {
|
||||
"label": "Verifier",
|
||||
"detail": "release readback blocked {blocked}。"
|
||||
},
|
||||
"learning": {
|
||||
"label": "Learning",
|
||||
"detail": "學習寫回 gate {gates} 個,未批准為 0。"
|
||||
}
|
||||
},
|
||||
"boundaries": {
|
||||
"allScope": {
|
||||
"label": "全部納入控管視圖",
|
||||
"detail": "八大範圍已可見,但這不是全部自動執行。"
|
||||
},
|
||||
"notFullControl": {
|
||||
"label": "尚未全自動接管",
|
||||
"detail": "整體仍在 {gates} 個審核/授權 gate 前。"
|
||||
},
|
||||
"writes": {
|
||||
"label": "寫入與通知權限",
|
||||
"detail": "Telegram/Bot API 正式直送總數 {telegram},不得誤報已接通。"
|
||||
},
|
||||
"redaction": {
|
||||
"label": "前端脫敏",
|
||||
"detail": "host redaction={host} · agent redaction={agent}。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"deploymentLayout": {
|
||||
"title": "OpenClaw / Hermes / NemoTron 佈建布局",
|
||||
"source": "{generated} · {current} → {next}",
|
||||
|
||||
@@ -5074,6 +5074,297 @@ export function AutomationInventoryTab() {
|
||||
}
|
||||
}
|
||||
|
||||
const websiteAssetCount = snapshot.assets.filter(asset => asset.asset_type === 'web').length
|
||||
const globalControlApprovalGateTotal = (
|
||||
explicitApprovalTaskCount
|
||||
+ explicitApprovalItemCount
|
||||
+ deploymentLayoutApprovalTargets
|
||||
+ proactiveApprovalCapabilities
|
||||
+ providerRouteGateApprovals
|
||||
+ professionalTaskApprovals
|
||||
+ warRoomApprovals
|
||||
+ learningWritebackApprovals
|
||||
+ serviceHealthActionRequiredRules
|
||||
)
|
||||
const globalControlLiveWriteAllowedTotal = (
|
||||
hostReadonlyDeniedCount
|
||||
+ providerRouteDeniedCount
|
||||
+ serviceHealthDeniedCount
|
||||
+ serviceHealthNotificationAllowedCount
|
||||
+ resultCaptureReleaseReadbackLiveWrites
|
||||
+ runtimeWriteLiveTotal
|
||||
+ learningWritebackLiveWrites
|
||||
+ professionalTaskLiveWrites
|
||||
+ professionalTaskPreviewLiveWrites
|
||||
+ warRoomLiveWrites
|
||||
+ reportLiveDelivery
|
||||
+ reportLiveOptimization
|
||||
)
|
||||
const globalControlTelegramSendTotal = (
|
||||
hostTelegramDirectSendAllowed
|
||||
+ serviceHealthNotificationAllowedCount
|
||||
+ telegramReceiptLiveTotal
|
||||
+ professionalTaskExpansion.rollups.telegram_send_count
|
||||
+ professionalTaskExpansion.rollups.bot_api_call_count
|
||||
+ warRoom.rollups.telegram_send_count
|
||||
+ warRoom.rollups.bot_api_call_count
|
||||
)
|
||||
const globalControlDomainRows: Array<{
|
||||
key: string
|
||||
label: string
|
||||
scope: string
|
||||
owner: string
|
||||
sensor: string
|
||||
candidate: string
|
||||
gate: string
|
||||
telegram: string
|
||||
learning: string
|
||||
tone: 'ok' | 'warn' | 'danger' | 'neutral'
|
||||
icon: ReactNode
|
||||
}> = [
|
||||
{
|
||||
key: 'hosts',
|
||||
label: t('globalControl.domains.hosts.label'),
|
||||
scope: t('globalControl.domains.hosts.scope', {
|
||||
hosts: hostStatefulInventory.rollups.host_count,
|
||||
nodes: hostStatefulInventory.rollups.k3s_node_count,
|
||||
stateful: hostStatefulInventory.rollups.stateful_service_count,
|
||||
}),
|
||||
owner: 'OpenClaw / Hermes',
|
||||
sensor: t('globalControl.domains.hosts.sensor', { probes: hostStatefulInventory.rollups.readonly_probe_step_count }),
|
||||
candidate: t('globalControl.domains.hosts.candidate', { fields: hostStatefulInventory.rollups.maintenance_required_field_count }),
|
||||
gate: t('globalControl.domains.hosts.gate', { writes: hostReadonlyDeniedCount }),
|
||||
telegram: t('globalControl.domains.hosts.telegram', {
|
||||
direct: hostTelegramDirectSendAllowed,
|
||||
queue: hostTelegramGatewayWriteAllowed,
|
||||
}),
|
||||
learning: t('globalControl.learning.ownerReview'),
|
||||
tone: hostReadonlyDeniedCount === 0 ? 'ok' : 'danger',
|
||||
icon: <Server size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'products',
|
||||
label: t('globalControl.domains.products.label'),
|
||||
scope: t('globalControl.domains.products.scope', {
|
||||
assets: snapshot.assets.length,
|
||||
domains: snapshot.asset_domains.length,
|
||||
}),
|
||||
owner: 'OpenClaw / Hermes / Nemotron',
|
||||
sensor: t('globalControl.domains.products.sensor', { workstreams: snapshot.workstreams.length }),
|
||||
candidate: t('globalControl.domains.products.candidate', { tasks: snapshot.tasks.length }),
|
||||
gate: t('globalControl.domains.products.gate', { approvals: explicitApprovalTaskCount }),
|
||||
telegram: t('globalControl.telegram.digestOnly'),
|
||||
learning: t('globalControl.learning.snapshot'),
|
||||
tone: explicitApprovalTaskCount > 0 ? 'warn' : 'ok',
|
||||
icon: <Layers3 size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'websites',
|
||||
label: t('globalControl.domains.websites.label'),
|
||||
scope: t('globalControl.domains.websites.scope', {
|
||||
websites: websiteAssetCount,
|
||||
runtime: runtimeSurfaceComponentTotal,
|
||||
}),
|
||||
owner: 'Hermes / OpenClaw',
|
||||
sensor: t('globalControl.domains.websites.sensor', { bound: runtimeBoundComponents, total: runtimeSurfaceComponentTotal }),
|
||||
candidate: t('globalControl.domains.websites.candidate', { missing: runtimeLiveMissing }),
|
||||
gate: t('globalControl.domains.websites.gate', { secrets: runtimeSecrets }),
|
||||
telegram: t('globalControl.telegram.failureOnly'),
|
||||
learning: t('globalControl.learning.redactedEvidence'),
|
||||
tone: runtimeLiveMissing > 0 || runtimeSecrets > 0 ? 'warn' : 'ok',
|
||||
icon: <Route size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'packages',
|
||||
label: t('globalControl.domains.packages.label'),
|
||||
scope: t('globalControl.domains.packages.scope', {
|
||||
sources: dependencySupplyChainDriftMonitor.rollups.source_snapshot_count,
|
||||
checks: dependencySupplyChainDriftMonitor.rollups.monitor_check_count,
|
||||
}),
|
||||
owner: 'Nemotron / Hermes',
|
||||
sensor: t('globalControl.domains.packages.sensor', { stale: dependencySupplyChainDriftMonitor.rollups.stale_source_snapshot_count }),
|
||||
candidate: t('globalControl.domains.packages.candidate', { candidates: dependencySupplyChainDriftMonitor.rollups.drift_candidate_count }),
|
||||
gate: t('globalControl.domains.packages.gate', { blocked: dependencySupplyChainDriftMonitor.rollups.blocked_operation_count }),
|
||||
telegram: t('globalControl.telegram.approvalRequired'),
|
||||
learning: t('globalControl.learning.versionRadar'),
|
||||
tone: dependencySupplyChainDriftMonitor.rollups.blocked_operation_count > 0 ? 'warn' : 'ok',
|
||||
icon: <PackageCheck size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'services',
|
||||
label: t('globalControl.domains.services.label'),
|
||||
scope: t('globalControl.domains.services.scope', {
|
||||
targets: serviceHealthGapMatrix.rollups.total_targets,
|
||||
surfaces: runtimeSurface?.rollups.total_surfaces ?? 0,
|
||||
}),
|
||||
owner: 'OpenClaw / Hermes',
|
||||
sensor: t('globalControl.domains.services.sensor', { action: serviceHealthActions, stale: serviceHealthStaleGaps }),
|
||||
candidate: t('globalControl.domains.services.candidate', { gaps: serviceHealthOperatorReviews }),
|
||||
gate: t('globalControl.domains.services.gate', { allowed: serviceHealthDeniedCount }),
|
||||
telegram: t('globalControl.domains.services.telegram', {
|
||||
escalation: serviceHealthImmediateEscalations,
|
||||
quiet: serviceHealthSuppressedSuccess,
|
||||
}),
|
||||
learning: t('globalControl.learning.healthLoop'),
|
||||
tone: serviceHealthDeniedCount === 0 ? 'ok' : 'danger',
|
||||
icon: <Database size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'tools',
|
||||
label: t('globalControl.domains.tools.label'),
|
||||
scope: t('globalControl.domains.tools.scope', {
|
||||
workflows: giteaHealth.rollups.total_workflows,
|
||||
observability: observabilityMatrix.rollups.total_surfaces,
|
||||
}),
|
||||
owner: 'Hermes / OpenClaw',
|
||||
sensor: t('globalControl.domains.tools.sensor', { runners: giteaRunnerActions }),
|
||||
candidate: t('globalControl.domains.tools.candidate', { opportunities: observabilityProposalCount }),
|
||||
gate: t('globalControl.domains.tools.gate', { approvals: observabilityApprovalRequired }),
|
||||
telegram: t('globalControl.telegram.notifyBridge'),
|
||||
learning: t('globalControl.learning.noiseReduction'),
|
||||
tone: giteaRunnerActions > 0 || observabilityApprovalRequired > 0 ? 'warn' : 'ok',
|
||||
icon: <GitBranch size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'agents',
|
||||
label: t('globalControl.domains.agents.label'),
|
||||
scope: t('globalControl.domains.agents.scope', {
|
||||
roles: warRoomRoleCount,
|
||||
tasks: professionalTaskTotal,
|
||||
}),
|
||||
owner: 'OpenClaw / Hermes / Nemotron',
|
||||
sensor: t('globalControl.domains.agents.sensor', { batches: warRoomBatchCount }),
|
||||
candidate: t('globalControl.domains.agents.candidate', { high: professionalTaskHighCritical }),
|
||||
gate: t('globalControl.domains.agents.gate', { approvals: warRoomApprovals + professionalTaskApprovals }),
|
||||
telegram: t('globalControl.domains.agents.telegram', { previews: visibleTelegramPreviews.length }),
|
||||
learning: t('globalControl.learning.agentMemory'),
|
||||
tone: warRoomApprovals + professionalTaskApprovals > 0 ? 'warn' : 'ok',
|
||||
icon: <MessageSquareText size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'aiSolutions',
|
||||
label: t('globalControl.domains.aiSolutions.label'),
|
||||
scope: t('globalControl.domains.aiSolutions.scope', {
|
||||
routes: providerRouteMatrix.rollups.total_routes,
|
||||
domains: proactiveOperations.rollups.version_domain_count,
|
||||
}),
|
||||
owner: 'Nemotron / OpenClaw',
|
||||
sensor: t('globalControl.domains.aiSolutions.sensor', { candidates: warRoomMarketCandidates }),
|
||||
candidate: t('globalControl.domains.aiSolutions.candidate', { gates: providerRouteGateApprovals }),
|
||||
gate: t('globalControl.domains.aiSolutions.gate', { denied: providerRouteDeniedCount }),
|
||||
telegram: t('globalControl.telegram.ownerGate'),
|
||||
learning: t('globalControl.learning.marketRadar'),
|
||||
tone: providerRouteDeniedCount === 0 ? 'ok' : 'danger',
|
||||
icon: <BookOpenCheck size={16} />,
|
||||
},
|
||||
]
|
||||
const globalControlPipelineRows: Array<{
|
||||
key: string
|
||||
label: string
|
||||
value: string
|
||||
detail: string
|
||||
tone: 'ok' | 'warn' | 'danger' | 'neutral'
|
||||
icon: ReactNode
|
||||
}> = [
|
||||
{
|
||||
key: 'sensor',
|
||||
label: t('globalControl.pipeline.sensor.label'),
|
||||
value: `${globalControlDomainRows.length}/8`,
|
||||
detail: t('globalControl.pipeline.sensor.detail', { assets: snapshot.assets.length }),
|
||||
tone: globalControlDomainRows.length === 8 ? 'ok' : 'warn',
|
||||
icon: <Fingerprint size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'normalizer',
|
||||
label: t('globalControl.pipeline.normalizer.label'),
|
||||
value: String(snapshot.status_taxonomy.gate_statuses.length),
|
||||
detail: t('globalControl.pipeline.normalizer.detail', { statuses: snapshot.status_taxonomy.task_statuses.length }),
|
||||
tone: 'ok',
|
||||
icon: <Boxes size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'aiLane',
|
||||
label: t('globalControl.pipeline.aiLane.label'),
|
||||
value: String(warRoomRoleCount),
|
||||
detail: t('globalControl.pipeline.aiLane.detail', { targets: deploymentLayoutTargets }),
|
||||
tone: 'ok',
|
||||
icon: <UserCheck size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'candidate',
|
||||
label: t('globalControl.pipeline.candidate.label'),
|
||||
value: String(candidateDryRunCount + dependencySupplyChainDriftMonitor.rollups.drift_candidate_count),
|
||||
detail: t('globalControl.pipeline.candidate.detail', { evidence: candidateDryRunEvidenceCount }),
|
||||
tone: candidateDryRunNeedsReview > 0 ? 'warn' : 'ok',
|
||||
icon: <ClipboardCheck size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'gate',
|
||||
label: t('globalControl.pipeline.gate.label'),
|
||||
value: String(globalControlApprovalGateTotal),
|
||||
detail: t('globalControl.pipeline.gate.detail', { blocked: blockedApprovals.length }),
|
||||
tone: globalControlApprovalGateTotal > 0 ? 'warn' : 'ok',
|
||||
icon: <Lock size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'execution',
|
||||
label: t('globalControl.pipeline.execution.label'),
|
||||
value: String(globalControlLiveWriteAllowedTotal),
|
||||
detail: t('globalControl.pipeline.execution.detail', { telegram: globalControlTelegramSendTotal }),
|
||||
tone: globalControlLiveWriteAllowedTotal === 0 && globalControlTelegramSendTotal === 0 ? 'ok' : 'danger',
|
||||
icon: <BellOff size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'verifier',
|
||||
label: t('globalControl.pipeline.verifier.label'),
|
||||
value: String(resultCaptureReleaseReadbacks),
|
||||
detail: t('globalControl.pipeline.verifier.detail', { blocked: resultCaptureReleaseReadbackBlocked }),
|
||||
tone: resultCaptureReleaseReadbackBlocked > 0 ? 'warn' : 'ok',
|
||||
icon: <ShieldCheck size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'learning',
|
||||
label: t('globalControl.pipeline.learning.label'),
|
||||
value: String(learningWritebackLiveWrites),
|
||||
detail: t('globalControl.pipeline.learning.detail', { gates: learningWritebackApprovals }),
|
||||
tone: learningWritebackLiveWrites === 0 ? 'ok' : 'danger',
|
||||
icon: <BookOpenCheck size={16} />,
|
||||
},
|
||||
]
|
||||
const globalControlBoundaryRows = [
|
||||
{
|
||||
key: 'allScope',
|
||||
label: t('globalControl.boundaries.allScope.label'),
|
||||
value: `${globalControlDomainRows.length}/8`,
|
||||
detail: t('globalControl.boundaries.allScope.detail'),
|
||||
tone: 'ok' as const,
|
||||
},
|
||||
{
|
||||
key: 'notFullControl',
|
||||
label: t('globalControl.boundaries.notFullControl.label'),
|
||||
value: `${snapshot.program_status.overall_completion_percent}%`,
|
||||
detail: t('globalControl.boundaries.notFullControl.detail', { gates: globalControlApprovalGateTotal }),
|
||||
tone: 'warn' as const,
|
||||
},
|
||||
{
|
||||
key: 'writes',
|
||||
label: t('globalControl.boundaries.writes.label'),
|
||||
value: String(globalControlLiveWriteAllowedTotal),
|
||||
detail: t('globalControl.boundaries.writes.detail', { telegram: globalControlTelegramSendTotal }),
|
||||
tone: globalControlLiveWriteAllowedTotal === 0 && globalControlTelegramSendTotal === 0 ? 'ok' as const : 'danger' as const,
|
||||
},
|
||||
{
|
||||
key: 'redaction',
|
||||
label: t('globalControl.boundaries.redaction.label'),
|
||||
value: hostRedactionLocked && professionalTaskRedactionLocked && warRoomRedactionLocked && serviceHealthRedactionLocked ? 'on' : 'review',
|
||||
detail: t('globalControl.boundaries.redaction.detail', {
|
||||
host: String(hostRedactionLocked),
|
||||
agent: String(professionalTaskRedactionLocked && warRoomRedactionLocked),
|
||||
}),
|
||||
tone: hostRedactionLocked && professionalTaskRedactionLocked && warRoomRedactionLocked && serviceHealthRedactionLocked ? 'ok' as const : 'warn' as const,
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="automation-inventory-tab-root" style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 16, minWidth: 0 }}>
|
||||
<GlassCard variant="subtle" padding="md">
|
||||
@@ -5129,6 +5420,145 @@ export function AutomationInventoryTab() {
|
||||
]}
|
||||
/>
|
||||
|
||||
<GlassCard variant="subtle" padding="md">
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 14, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10, minWidth: 0 }}>
|
||||
<div style={{
|
||||
width: 38,
|
||||
height: 38,
|
||||
borderRadius: 8,
|
||||
border: '0.5px solid #0f766e40',
|
||||
background: 'rgba(15,118,110,0.08)',
|
||||
color: '#0f766e',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexShrink: 0,
|
||||
}}>
|
||||
<Target size={18} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 5, minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 18, fontWeight: 760, color: '#141413', lineHeight: 1.15, overflowWrap: 'anywhere' }}>
|
||||
{t('globalControl.title')}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#5c5a55', lineHeight: 1.55, overflowWrap: 'anywhere' }}>
|
||||
{t('globalControl.subtitle', {
|
||||
domains: globalControlDomainRows.length,
|
||||
gates: globalControlApprovalGateTotal,
|
||||
live: globalControlLiveWriteAllowedTotal,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6, minWidth: 0 }}>
|
||||
<Chip value={t('globalControl.badges.readOnly')} />
|
||||
<Chip value={t('globalControl.badges.noTranscript')} muted />
|
||||
<Chip value={t('globalControl.badges.noLiveWrite', { value: globalControlLiveWriteAllowedTotal })} muted={globalControlLiveWriteAllowedTotal === 0} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(128px, 1fr))', gap: 10 }} className="automation-inventory-global-control-kpi-grid">
|
||||
<MetricCard label={t('globalControl.metrics.domains')} value={`${globalControlDomainRows.length}/8`} tone="ok" icon={<Layers3 size={16} />} />
|
||||
<MetricCard label={t('globalControl.metrics.assets')} value={snapshot.assets.length} tone="ok" icon={<Boxes size={16} />} />
|
||||
<MetricCard label={t('globalControl.metrics.runtime')} value={runtimeSurface?.rollups.total_surfaces ?? 0} tone="ok" icon={<Server size={16} />} />
|
||||
<MetricCard label={t('globalControl.metrics.candidates')} value={candidateDryRunCount + dependencySupplyChainDriftMonitor.rollups.drift_candidate_count} tone="warn" icon={<ClipboardCheck size={16} />} />
|
||||
<MetricCard label={t('globalControl.metrics.gates')} value={globalControlApprovalGateTotal} tone={globalControlApprovalGateTotal > 0 ? 'warn' : 'ok'} icon={<Lock size={16} />} />
|
||||
<MetricCard label={t('globalControl.metrics.liveWrites')} value={globalControlLiveWriteAllowedTotal} tone={globalControlLiveWriteAllowedTotal === 0 ? 'ok' : 'danger'} icon={<BellOff size={16} />} />
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.25fr) minmax(260px, 0.75fr)', gap: 12 }} className="automation-inventory-global-control-grid">
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 10, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
|
||||
<SmallLabel>{t('globalControl.pipelineTitle')}</SmallLabel>
|
||||
<Chip value={t('globalControl.pipelineBadge')} muted />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 10 }} className="automation-inventory-global-control-pipeline-grid">
|
||||
{globalControlPipelineRows.map((row, index) => (
|
||||
<FlowStageTile
|
||||
key={row.key}
|
||||
index={String(index + 1).padStart(2, '0')}
|
||||
label={row.label}
|
||||
value={row.value}
|
||||
detail={row.detail}
|
||||
icon={row.icon}
|
||||
tone={row.tone}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 12, border: '0.5px solid #d6e7de', borderRadius: 7, background: '#f7fffb', display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
|
||||
<SmallLabel>{t('globalControl.boundaryTitle')}</SmallLabel>
|
||||
<Chip value={t('globalControl.boundaryBadge')} muted />
|
||||
</div>
|
||||
{globalControlBoundaryRows.map(row => (
|
||||
<GateMatrixRow
|
||||
key={row.key}
|
||||
label={row.label}
|
||||
value={row.value}
|
||||
detail={row.detail}
|
||||
tone={row.tone}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, minmax(0, 1fr))', gap: 10 }} className="automation-inventory-global-control-domain-grid">
|
||||
{globalControlDomainRows.map(row => {
|
||||
const color = toneColor(row.tone)
|
||||
return (
|
||||
<div key={row.key} style={{ padding: 12, border: `0.5px solid ${color}45`, borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 9, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 9, minWidth: 0 }}>
|
||||
<div style={{
|
||||
width: 30,
|
||||
height: 30,
|
||||
borderRadius: 7,
|
||||
border: `0.5px solid ${color}55`,
|
||||
background: `${color}12`,
|
||||
color,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexShrink: 0,
|
||||
}}>
|
||||
{row.icon}
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 760, color: '#141413', lineHeight: 1.2, overflowWrap: 'anywhere' }}>
|
||||
{row.label}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#6d6a61', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{row.scope}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={row.owner} />
|
||||
<Chip value={row.telegram} muted />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#5f5a4f', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{row.sensor}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#5f5a4f', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{row.candidate}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color, fontWeight: 700, lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{row.gate}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#87867f', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{row.learning}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
|
||||
<GlassCard variant="subtle" padding="md">
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 14, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
|
||||
@@ -17783,6 +18213,10 @@ export function AutomationInventoryTab() {
|
||||
.automation-inventory-visual-grid,
|
||||
.automation-inventory-stage-grid,
|
||||
.automation-inventory-visual-factor-grid,
|
||||
.automation-inventory-global-control-kpi-grid,
|
||||
.automation-inventory-global-control-grid,
|
||||
.automation-inventory-global-control-pipeline-grid,
|
||||
.automation-inventory-global-control-domain-grid,
|
||||
.automation-inventory-kpi-grid,
|
||||
.automation-inventory-command-grid,
|
||||
.automation-inventory-summary-grid,
|
||||
|
||||
Reference in New Issue
Block a user