feat(governance): 顯示 AI Agents 全域控管總盤
All checks were successful
Code Review / ai-code-review (push) Successful in 19s
CD Pipeline / tests (push) Successful in 1m51s
CD Pipeline / build-and-deploy (push) Successful in 10m48s
CD Pipeline / post-deploy-checks (push) Successful in 2m43s

This commit is contained in:
Your Name
2026-06-25 20:09:35 +08:00
parent 4ada9e6d19
commit f63d9faa29
3 changed files with 736 additions and 0 deletions

View File

@@ -3569,6 +3569,157 @@
"taskBoundaries": "任務邊界", "taskBoundaries": "任務邊界",
"explicitApprovalTasks": "需明確批准" "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": { "deploymentLayout": {
"title": "OpenClaw / Hermes / NemoTron 佈建布局", "title": "OpenClaw / Hermes / NemoTron 佈建布局",
"source": "{generated} · {current} → {next}", "source": "{generated} · {current} → {next}",

View File

@@ -3569,6 +3569,157 @@
"taskBoundaries": "任務邊界", "taskBoundaries": "任務邊界",
"explicitApprovalTasks": "需明確批准" "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": { "deploymentLayout": {
"title": "OpenClaw / Hermes / NemoTron 佈建布局", "title": "OpenClaw / Hermes / NemoTron 佈建布局",
"source": "{generated} · {current} → {next}", "source": "{generated} · {current} → {next}",

View File

@@ -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 ( return (
<div className="automation-inventory-tab-root" style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 16, minWidth: 0 }}> <div className="automation-inventory-tab-root" style={{ padding: 20, display: 'flex', flexDirection: 'column', gap: 16, minWidth: 0 }}>
<GlassCard variant="subtle" padding="md"> <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"> <GlassCard variant="subtle" padding="md">
<div style={{ display: 'flex', flexDirection: 'column', gap: 14, minWidth: 0 }}> <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', justifyContent: 'space-between', gap: 12, flexWrap: 'wrap' }}>
@@ -17783,6 +18213,10 @@ export function AutomationInventoryTab() {
.automation-inventory-visual-grid, .automation-inventory-visual-grid,
.automation-inventory-stage-grid, .automation-inventory-stage-grid,
.automation-inventory-visual-factor-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-kpi-grid,
.automation-inventory-command-grid, .automation-inventory-command-grid,
.automation-inventory-summary-grid, .automation-inventory-summary-grid,