diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 058d0fe5..3dc49823 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -3699,6 +3699,14 @@ "overrideTitle": "舊規範覆寫", "hardBlockerTitle": "仍維持硬阻擋", "hardBlockerDetail": "需 break-glass 或專案級合約,不由一般自動化靜默執行。", + "readback": { + "marker": "Production v2 marker", + "markerDetail": "{task} · {status}", + "executor": "live ansible_apply_executed", + "executorDetail": "post verifier {verifier} · KM {km} · Telegram {telegram}", + "loop": "latest flow closed", + "loopDetail": "MCP {mcp} · RAG {rag} · PlayBook {playbook}" + }, "badges": { "override": "舊 no-send / no-live 已覆寫", "gateway": "Telegram Gateway", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 058d0fe5..3dc49823 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -3699,6 +3699,14 @@ "overrideTitle": "舊規範覆寫", "hardBlockerTitle": "仍維持硬阻擋", "hardBlockerDetail": "需 break-glass 或專案級合約,不由一般自動化靜默執行。", + "readback": { + "marker": "Production v2 marker", + "markerDetail": "{task} · {status}", + "executor": "live ansible_apply_executed", + "executorDetail": "post verifier {verifier} · KM {km} · Telegram {telegram}", + "loop": "latest flow closed", + "loopDetail": "MCP {mcp} · RAG {rag} · PlayBook {playbook}" + }, "badges": { "override": "舊 no-send / no-live 已覆寫", "gateway": "Telegram Gateway", 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 d88b0104..6a20632f 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 @@ -847,6 +847,50 @@ function GateMatrixRow({ ) } +function AutonomousRuntimeControlReadbackGrid({ + control, + t, +}: { + control: AiAgentAutonomousRuntimeControlSnapshot + t: ReturnType +}) { + const rollups = control.rollups + + return ( +
+ + 0 ? 'ok' : 'warn'} + /> + 0 ? 'ok' : 'warn'} + /> +
+ ) +} + function AutonomousRuntimeControlPriorityPanel({ control, t, @@ -895,6 +939,8 @@ function AutonomousRuntimeControlPriorityPanel({ + +
} /> } /> @@ -1085,6 +1131,12 @@ export function AutomationInventoryTab() { .catch(() => undefined) } + const fetchAutonomousRuntimeControlReadback = () => { + apiClient.getAiAgentAutonomousRuntimeControl() + .then(value => setAutonomousRuntimeControl(sanitizePublicSnapshot(value))) + .catch(() => undefined) + } + const fetchSnapshot = () => { setLoading(true) const requests = [ @@ -1272,7 +1324,7 @@ export function AutomationInventoryTab() { ] = results setSnapshot(settledPublicValue(inventoryResult)) - setAutonomousRuntimeControl(settledPublicValue(autonomousRuntimeControlResult)) + setAutonomousRuntimeControl(previous => settledPublicValue(autonomousRuntimeControlResult) ?? previous) setBacklog(settledPublicValue(backlogResult)) setBackupTargets(settledPublicValue(targetResult)) setBackupReadiness(settledPublicValue(readinessResult)) @@ -1458,6 +1510,7 @@ export function AutomationInventoryTab() { useEffect(() => { fetchReportTruthQuickView() + fetchAutonomousRuntimeControlReadback() fetchSnapshot() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -6500,6 +6553,8 @@ export function AutomationInventoryTab() {
+ +
} /> } /> @@ -20063,6 +20118,7 @@ export function AutomationInventoryTab() { .automation-inventory-visual-grid, .automation-inventory-stage-grid, .automation-inventory-visual-factor-grid, + .automation-inventory-current-autonomy-readback-grid, .automation-inventory-global-control-kpi-grid, .automation-inventory-global-control-grid, .automation-inventory-global-control-pipeline-grid, diff --git a/apps/web/src/lib/api-client.ts b/apps/web/src/lib/api-client.ts index 0e704ced..a2f8c0d1 100644 --- a/apps/web/src/lib/api-client.ts +++ b/apps/web/src/lib/api-client.ts @@ -2189,6 +2189,15 @@ export interface AiAgentAutonomousRuntimeControlSnapshot { controlled_executor_operation_receipt_count: number runtime_write_receipt_type_count: number legacy_policy_overridden_count: number + live_ansible_apply_executed_count?: number + live_executor_latest_flow_closed_count?: number + live_km_writeback_count?: number + live_post_apply_verifier_count?: number + live_telegram_receipt_count?: number + mcp_sensor_count?: number + rag_context_query_count?: number + playbook_decision_class_count?: number + deploy_control_classifier_example_count?: number } }