diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 93bf559a..42a78022 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -3576,6 +3576,41 @@ "pipelineBadge": "Sensor → Gate → Verifier", "boundaryTitle": "真實邊界", "boundaryBadge": "不誇大接管", + "runwayTitle": "AI Agents 專業執行跑道", + "runwayBadge": "只讀 / 乾跑 / 審核 / 回寫", + "runwaySummary": "可無寫入推進 {noWrite} 類;正式執行 {runtime}、Telegram 發送 {sends}、production 寫入 {writes} 仍依 gate。", + "runway": { + "readOnlyInvestigation": { + "label": "主動巡檢與證據蒐集", + "detail": "只讀探針 {probes} 個,服務需處置訊號 {health} 個。", + "next": "下一步:整理 owner packet;runtime blocker {blocked} 個。" + }, + "dryRunCandidate": { + "label": "乾跑候選與套用審查", + "detail": "乾跑證據 {evidence} 筆,Verifier plan {verifier} 個。", + "next": "下一步:{review} 個候選進 owner review,不直接執行。" + }, + "shadowReplay": { + "label": "Nemotron replay / shadow", + "detail": "無寫入 replay {replays} 次,Verifier shadow case {verifier} 個。", + "next": "下一步:{approvals} 個 checkpoint 需批准才可升級。" + }, + "permissionModel": { + "label": "操作權限模型", + "detail": "Gate transition {gates} 條,blocked category {blocked} 個。", + "next": "下一步:{approvals} 類仍需人工批准。" + }, + "reportTelegram": { + "label": "日週月報與 Telegram receipt", + "detail": "Gateway queue write {queue},live report delivery {delivery}。", + "next": "下一步:{approvals} 個報告/通知決策需批准。" + }, + "learningWriteback": { + "label": "學習回寫與 PlayBook 成長", + "detail": "已匹配 approval {matched} 筆,KM draft {drafts} 筆。", + "next": "下一步:{gates} 個 learning / trust gate 未打開。" + } + }, "badges": { "readOnly": "全域只讀控管", "noTranscript": "只顯示脫敏治理狀態", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 93bf559a..42a78022 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -3576,6 +3576,41 @@ "pipelineBadge": "Sensor → Gate → Verifier", "boundaryTitle": "真實邊界", "boundaryBadge": "不誇大接管", + "runwayTitle": "AI Agents 專業執行跑道", + "runwayBadge": "只讀 / 乾跑 / 審核 / 回寫", + "runwaySummary": "可無寫入推進 {noWrite} 類;正式執行 {runtime}、Telegram 發送 {sends}、production 寫入 {writes} 仍依 gate。", + "runway": { + "readOnlyInvestigation": { + "label": "主動巡檢與證據蒐集", + "detail": "只讀探針 {probes} 個,服務需處置訊號 {health} 個。", + "next": "下一步:整理 owner packet;runtime blocker {blocked} 個。" + }, + "dryRunCandidate": { + "label": "乾跑候選與套用審查", + "detail": "乾跑證據 {evidence} 筆,Verifier plan {verifier} 個。", + "next": "下一步:{review} 個候選進 owner review,不直接執行。" + }, + "shadowReplay": { + "label": "Nemotron replay / shadow", + "detail": "無寫入 replay {replays} 次,Verifier shadow case {verifier} 個。", + "next": "下一步:{approvals} 個 checkpoint 需批准才可升級。" + }, + "permissionModel": { + "label": "操作權限模型", + "detail": "Gate transition {gates} 條,blocked category {blocked} 個。", + "next": "下一步:{approvals} 類仍需人工批准。" + }, + "reportTelegram": { + "label": "日週月報與 Telegram receipt", + "detail": "Gateway queue write {queue},live report delivery {delivery}。", + "next": "下一步:{approvals} 個報告/通知決策需批准。" + }, + "learningWriteback": { + "label": "學習回寫與 PlayBook 成長", + "detail": "已匹配 approval {matched} 筆,KM draft {drafts} 筆。", + "next": "下一步:{gates} 個 learning / trust gate 未打開。" + } + }, "badges": { "readOnly": "全域只讀控管", "noTranscript": "只顯示脫敏治理狀態", 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 326c4d97..0ad3538c 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 @@ -5364,6 +5364,97 @@ export function AutomationInventoryTab() { tone: hostRedactionLocked && professionalTaskRedactionLocked && warRoomRedactionLocked && serviceHealthRedactionLocked ? 'ok' as const : 'warn' as const, }, ] + const globalControlRunwayRows: Array<{ + key: string + label: string + owner: string + value: string + detail: string + next: string + tone: 'ok' | 'warn' | 'danger' | 'neutral' + icon: ReactNode + }> = [ + { + key: 'readOnlyInvestigation', + label: t('globalControl.runway.readOnlyInvestigation.label'), + owner: 'Hermes / OpenClaw', + value: String(runtimeActionRequired + serviceHealthActions + hostRunawayAlertLanes), + detail: t('globalControl.runway.readOnlyInvestigation.detail', { + probes: hostStatefulInventory.rollups.readonly_probe_step_count, + health: serviceHealthActions, + }), + next: t('globalControl.runway.readOnlyInvestigation.next', { blocked: hostRunawayBlocked }), + tone: hostRunawayBlocked > 0 ? 'warn' : 'ok', + icon: , + }, + { + key: 'dryRunCandidate', + label: t('globalControl.runway.dryRunCandidate.label'), + owner: 'OpenClaw / SRE', + value: `${candidateDryRunPassed}/${candidateDryRunCount}`, + detail: t('globalControl.runway.dryRunCandidate.detail', { + evidence: candidateDryRunEvidenceCount, + verifier: candidateDryRunVerifierPlans, + }), + next: t('globalControl.runway.dryRunCandidate.next', { review: candidateDryRunNeedsReview }), + tone: candidateDryRunNeedsReview > 0 ? 'warn' : 'ok', + icon: , + }, + { + key: 'shadowReplay', + label: t('globalControl.runway.shadowReplay.label'), + owner: 'Nemotron / Critic', + value: `${runtimeShadowPassed}/${runtimeShadowCandidates}`, + detail: t('globalControl.runway.shadowReplay.detail', { + replays: runtimeShadowReplays, + verifier: runtimeShadowVerifierCases, + }), + next: t('globalControl.runway.shadowReplay.next', { approvals: runtimeShadowApprovals }), + tone: runtimeShadowApprovals > 0 || runtimeShadowBlocked > 0 ? 'warn' : 'ok', + icon: , + }, + { + key: 'permissionModel', + label: t('globalControl.runway.permissionModel.label'), + owner: 'Security / OpenClaw', + value: `${operationPermissionObserveOnly + operationPermissionNoWrite + operationPermissionProposalOnly}/${operationPermissionCategories}`, + detail: t('globalControl.runway.permissionModel.detail', { + gates: operationPermissionGates, + blocked: operationPermissionBlocked, + }), + next: t('globalControl.runway.permissionModel.next', { approvals: operationPermissionHumanApproval }), + tone: operationPermissionBlocked > 0 || operationPermissionHumanApproval > 0 ? 'warn' : 'ok', + icon: , + }, + { + key: 'reportTelegram', + label: t('globalControl.runway.reportTelegram.label'), + owner: 'Hermes / Reporter', + value: `${reportRuntimeReady}/${reportRuntimeLanes}`, + detail: t('globalControl.runway.reportTelegram.detail', { + queue: reportRuntimeQueueWrites, + delivery: reportRuntimeLiveDelivery, + }), + next: t('globalControl.runway.reportTelegram.next', { approvals: reportRuntimeApprovals }), + tone: reportRuntimeApprovals > 0 || reportRuntimeBlocked > 0 ? 'warn' : 'ok', + icon: , + }, + { + key: 'learningWriteback', + label: t('globalControl.runway.learningWriteback.label'), + owner: 'Hermes / OpenClaw', + value: String(matchedPlaybookCandidates + taskResultKmDrafts), + detail: t('globalControl.runway.learningWriteback.detail', { + matched: matchedPlaybookApprovalMatched, + drafts: taskResultKmDrafts, + }), + next: t('globalControl.runway.learningWriteback.next', { + gates: matchedPlaybookGates + learningWritebackApprovals, + }), + tone: matchedPlaybookGates + learningWritebackApprovals > 0 ? 'warn' : 'ok', + icon: , + }, + ] return (
@@ -5505,6 +5596,63 @@ export function AutomationInventoryTab() {
+
+
+
+ {t('globalControl.runwayTitle')} + + {t('globalControl.runwaySummary', { + noWrite: operationPermissionObserveOnly + operationPermissionNoWrite + operationPermissionProposalOnly, + runtime: operationPermissionRuntimeRuns, + sends: operationPermissionSends, + writes: operationPermissionProductionWrites, + })} + +
+ +
+
+ {globalControlRunwayRows.map(row => { + const color = toneColor(row.tone) + return ( +
+
+
+
+ {row.icon} +
+ + {row.label} + +
+ +
+
+ +
+ + {row.detail} + + + {row.next} + +
+ ) + })} +
+
+
{globalControlDomainRows.map(row => { const color = toneColor(row.tone) @@ -18216,6 +18364,7 @@ export function AutomationInventoryTab() { .automation-inventory-global-control-kpi-grid, .automation-inventory-global-control-grid, .automation-inventory-global-control-pipeline-grid, + .automation-inventory-global-control-runway-grid, .automation-inventory-global-control-domain-grid, .automation-inventory-kpi-grid, .automation-inventory-command-grid,