From f63d9faa2977050298657c735e25c61961058404 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 25 Jun 2026 20:09:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(governance):=20=E9=A1=AF=E7=A4=BA=20AI=20A?= =?UTF-8?q?gents=20=E5=85=A8=E5=9F=9F=E6=8E=A7=E7=AE=A1=E7=B8=BD=E7=9B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/messages/en.json | 151 ++++++ apps/web/messages/zh-TW.json | 151 ++++++ .../tabs/automation-inventory-tab.tsx | 434 ++++++++++++++++++ 3 files changed, 736 insertions(+) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index afea77bd..44302b2d 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -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}", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index afea77bd..44302b2d 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -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}", diff --git a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx index 1abd1fd3..326c4d97 100644 --- a/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx +++ b/apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx @@ -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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + ] + 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: , + }, + { + 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: , + }, + { + key: 'aiLane', + label: t('globalControl.pipeline.aiLane.label'), + value: String(warRoomRoleCount), + detail: t('globalControl.pipeline.aiLane.detail', { targets: deploymentLayoutTargets }), + tone: 'ok', + icon: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + { + 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: , + }, + ] + 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 (
@@ -5129,6 +5420,145 @@ export function AutomationInventoryTab() { ]} /> + +
+
+
+
+ +
+
+ + {t('globalControl.title')} + + + {t('globalControl.subtitle', { + domains: globalControlDomainRows.length, + gates: globalControlApprovalGateTotal, + live: globalControlLiveWriteAllowedTotal, + })} + +
+
+
+ + + +
+
+ +
+ } /> + } /> + } /> + } /> + 0 ? 'warn' : 'ok'} icon={} /> + } /> +
+ +
+
+
+ {t('globalControl.pipelineTitle')} + +
+
+ {globalControlPipelineRows.map((row, index) => ( + + ))} +
+
+ +
+
+ {t('globalControl.boundaryTitle')} + +
+ {globalControlBoundaryRows.map(row => ( + + ))} +
+
+ +
+ {globalControlDomainRows.map(row => { + const color = toneColor(row.tone) + return ( +
+
+
+ {row.icon} +
+
+ + {row.label} + + + {row.scope} + +
+
+
+ + +
+
+ + {row.sensor} + + + {row.candidate} + + + {row.gate} + + + {row.learning} + +
+
+ ) + })} +
+
+
+
@@ -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,