feat(agents): expose autonomous runtime control
Some checks failed
CD Pipeline / tests (push) Successful in 1m43s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
Code Review / ai-code-review (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-27 19:31:02 +08:00
parent d359587316
commit ce0c7cbaf8
13 changed files with 1017 additions and 38 deletions

View File

@@ -1866,10 +1866,16 @@
"needsHumanYes": "需要",
"needsHumanNo": "不需要",
"stateLabels": {
"verificationDegradedManualRequired": "驗證退化,需人工確認"
"verificationDegradedManualRequired": "驗證退化,AI 進入 verifier / rollback",
"verificationDegradedAiVerifierRequired": "驗證退化AI 進入 verifier / rollback",
"diagnosticOnlyAiRepairRequired": "只完成診斷AI 補修復候選",
"noActionAiCandidateRequired": "未找到修復候選AI 補 PlayBook"
},
"nextActionLabels": {
"manualVerifyOrRepair": "人工確認修復狀態;需要時重新送審修復"
"manualVerifyOrRepair": "AI 執行 verifier 或 rollback 判定",
"runVerifierOrRollbackCandidate": "AI 執行 verifier 或 rollback 判定",
"autoGenerateRepairCandidate": "AI 從診斷證據產生修復候選",
"autoRepairBlockerConnector": "AI 修復 blocker / connector 後重試"
},
"reasonLabels": {
"incidentOpenAfterSuccessfulExecution": "自動執行已完成,但 Incident仍開啟"
@@ -3681,6 +3687,41 @@
"runwayTitle": "AI Agents 專業執行跑道",
"runwayBadge": "只讀 / 乾跑 / 審核 / 回寫",
"runwaySummary": "可無寫入推進 {noWrite} 類;正式執行 {runtime}、Telegram 發送 {sends}、production 寫入 {writes} 仍依 gate。",
"currentAutonomy": {
"title": "目前有效自主化控制層",
"policyTitle": "目前執行政策",
"runtimeTitle": "Worker / Gateway 開關",
"executorTitle": "Executor 收據鏈",
"overrideTitle": "舊規範覆寫",
"hardBlockerTitle": "仍維持硬阻擋",
"hardBlockerDetail": "需 break-glass 或專案級合約,不由一般自動化靜默執行。",
"badges": {
"override": "舊 no-send / no-live 已覆寫",
"gateway": "Telegram Gateway"
},
"metrics": {
"completion": "目前完成度",
"riskTiers": "自動風險層",
"reports": "日週月報",
"gateway": "Gateway 派送",
"executor": "Executor 收據",
"hardBlockers": "硬阻擋"
},
"policy": {
"low": "低風險",
"medium": "中風險",
"high": "高風險",
"noOwnerReview": "低/中/高人工 gate={value}",
"verifier": "post-apply verifier={value}",
"km": "KM / PlayBook 回寫={value}"
},
"runtime": {
"checkMode": "Ansible check-mode worker",
"apply": "Controlled apply",
"botApi": "Direct Bot API",
"gatewayOnly": "只允許既有 Telegram Gateway不暴露 token / chat id。"
}
},
"runway": {
"readOnlyInvestigation": {
"label": "主動巡檢與證據蒐集",
@@ -9755,12 +9796,12 @@
"verify_git_baseline_then_mark_adopted": "驗證 Git baseline 後標記採納",
"operator_review_handoff_and_execute_manual_plan": "Operator review交接並執行人工方案",
"run_verification_scan_then_record_result": "執行驗證掃描並記錄結果",
"open_manual_investigation_with_failed_verification": "建立人工調查並附上失敗驗證",
"open_manual_investigation_with_failed_verification": "建立 AI verifier / rollback 調查並附上失敗驗證",
"verify_k8s_matches_git_baseline": "驗證 K8s與Git baseline 一致",
"confirm_no_repeat_after_rollback": "確認回滾後不再重複",
"monitor_for_recurrence": "監控是否復發",
"retry_pr_lookup_then_review_drift": "重試 PR 查詢後 review drift",
"manual_investigation_or_ansible_check_mode": "人工調查或Ansible check-mode",
"manual_investigation_or_ansible_check_mode": "AI 調查或 Ansible check-mode",
"unknown": "未知"
},
"pr": {
@@ -10669,11 +10710,15 @@
"nextActions": {
"openApplyGateWorkItem": "開啟 apply gate 工作項,審查 Verifier 與 KM 回寫",
"reviewOwnerReleasePacket": "審查 owner 放行包、執行窗口、rollback 與回寫責任",
"manualReviewNoActionDecision": "人工判斷是否接手或關閉事件",
"manualReviewNoActionDecision": "AI 補齊 evidence / PlayBook 後判定是否關閉事件",
"ownerReviewRepairCandidateDraft": "審查修復候選草案、rollback 與 verifier",
"collectRepairEvidence": "補齊修復證據或建立專屬 PlayBook",
"manualInvestigation": "人工調查卡點並補證據",
"reviewVerifier": "執行或審查修復後 verifier",
"manualInvestigation": "AI 調查卡點並補證據",
"autoGenerateRepairCandidate": "AI 從診斷證據產生修復候選",
"autoVerifyOrRollback": "AI 執行 verifier 或 rollback 判定",
"autoRepairBlockerConnector": "AI 修復 blocker / connector 後重試",
"autoGenerateRepairOrBreakGlass": "AI 產生修復包;硬阻擋才 break-glass",
"reviewVerifier": "執行修復後 verifier",
"monitorRegression": "持續觀察是否復發",
"collectEvidenceOrWait": "補收證據或等待下一筆 recurrence",
"collectMaintenanceRollback": "補齊維護窗口與 rollback owner",
@@ -11272,7 +11317,7 @@
"nextActions": {
"openApplyGateWorkItem": "開啟 apply gate 工作項,審查 Verifier 與 KM 回寫",
"ownerReviewRepairCandidateDraft": "審查修復候選草案、rollback 與 verifier",
"manualReviewNoActionDecision": "人工判斷是否接手或關閉事件"
"manualReviewNoActionDecision": "AI 補齊 evidence / PlayBook 後判定是否關閉事件"
},
"items": {
"km": "KM",

View File

@@ -1866,10 +1866,16 @@
"needsHumanYes": "需要",
"needsHumanNo": "不需要",
"stateLabels": {
"verificationDegradedManualRequired": "驗證退化,需人工確認"
"verificationDegradedManualRequired": "驗證退化,AI 進入 verifier / rollback",
"verificationDegradedAiVerifierRequired": "驗證退化AI 進入 verifier / rollback",
"diagnosticOnlyAiRepairRequired": "只完成診斷AI 補修復候選",
"noActionAiCandidateRequired": "未找到修復候選AI 補 PlayBook"
},
"nextActionLabels": {
"manualVerifyOrRepair": "人工確認修復狀態;需要時重新送審修復"
"manualVerifyOrRepair": "AI 執行 verifier 或 rollback 判定",
"runVerifierOrRollbackCandidate": "AI 執行 verifier 或 rollback 判定",
"autoGenerateRepairCandidate": "AI 從診斷證據產生修復候選",
"autoRepairBlockerConnector": "AI 修復 blocker / connector 後重試"
},
"reasonLabels": {
"incidentOpenAfterSuccessfulExecution": "自動執行已完成,但 Incident仍開啟"
@@ -3681,6 +3687,41 @@
"runwayTitle": "AI Agents 專業執行跑道",
"runwayBadge": "只讀 / 乾跑 / 審核 / 回寫",
"runwaySummary": "可無寫入推進 {noWrite} 類;正式執行 {runtime}、Telegram 發送 {sends}、production 寫入 {writes} 仍依 gate。",
"currentAutonomy": {
"title": "目前有效自主化控制層",
"policyTitle": "目前執行政策",
"runtimeTitle": "Worker / Gateway 開關",
"executorTitle": "Executor 收據鏈",
"overrideTitle": "舊規範覆寫",
"hardBlockerTitle": "仍維持硬阻擋",
"hardBlockerDetail": "需 break-glass 或專案級合約,不由一般自動化靜默執行。",
"badges": {
"override": "舊 no-send / no-live 已覆寫",
"gateway": "Telegram Gateway"
},
"metrics": {
"completion": "目前完成度",
"riskTiers": "自動風險層",
"reports": "日週月報",
"gateway": "Gateway 派送",
"executor": "Executor 收據",
"hardBlockers": "硬阻擋"
},
"policy": {
"low": "低風險",
"medium": "中風險",
"high": "高風險",
"noOwnerReview": "低/中/高人工 gate={value}",
"verifier": "post-apply verifier={value}",
"km": "KM / PlayBook 回寫={value}"
},
"runtime": {
"checkMode": "Ansible check-mode worker",
"apply": "Controlled apply",
"botApi": "Direct Bot API",
"gatewayOnly": "只允許既有 Telegram Gateway不暴露 token / chat id。"
}
},
"runway": {
"readOnlyInvestigation": {
"label": "主動巡檢與證據蒐集",
@@ -9755,12 +9796,12 @@
"verify_git_baseline_then_mark_adopted": "驗證 Git baseline 後標記採納",
"operator_review_handoff_and_execute_manual_plan": "Operator review交接並執行人工方案",
"run_verification_scan_then_record_result": "執行驗證掃描並記錄結果",
"open_manual_investigation_with_failed_verification": "建立人工調查並附上失敗驗證",
"open_manual_investigation_with_failed_verification": "建立 AI verifier / rollback 調查並附上失敗驗證",
"verify_k8s_matches_git_baseline": "驗證 K8s與Git baseline 一致",
"confirm_no_repeat_after_rollback": "確認回滾後不再重複",
"monitor_for_recurrence": "監控是否復發",
"retry_pr_lookup_then_review_drift": "重試 PR 查詢後 review drift",
"manual_investigation_or_ansible_check_mode": "人工調查或Ansible check-mode",
"manual_investigation_or_ansible_check_mode": "AI 調查或 Ansible check-mode",
"unknown": "未知"
},
"pr": {
@@ -10669,11 +10710,15 @@
"nextActions": {
"openApplyGateWorkItem": "開啟 apply gate 工作項,審查 Verifier 與 KM 回寫",
"reviewOwnerReleasePacket": "審查 owner 放行包、執行窗口、rollback 與回寫責任",
"manualReviewNoActionDecision": "人工判斷是否接手或關閉事件",
"manualReviewNoActionDecision": "AI 補齊 evidence / PlayBook 後判定是否關閉事件",
"ownerReviewRepairCandidateDraft": "審查修復候選草案、rollback 與 verifier",
"collectRepairEvidence": "補齊修復證據或建立專屬 PlayBook",
"manualInvestigation": "人工調查卡點並補證據",
"reviewVerifier": "執行或審查修復後 verifier",
"manualInvestigation": "AI 調查卡點並補證據",
"autoGenerateRepairCandidate": "AI 從診斷證據產生修復候選",
"autoVerifyOrRollback": "AI 執行 verifier 或 rollback 判定",
"autoRepairBlockerConnector": "AI 修復 blocker / connector 後重試",
"autoGenerateRepairOrBreakGlass": "AI 產生修復包;硬阻擋才 break-glass",
"reviewVerifier": "執行修復後 verifier",
"monitorRegression": "持續觀察是否復發",
"collectEvidenceOrWait": "補收證據或等待下一筆 recurrence",
"collectMaintenanceRollback": "補齊維護窗口與 rollback owner",
@@ -11272,7 +11317,7 @@
"nextActions": {
"openApplyGateWorkItem": "開啟 apply gate 工作項,審查 Verifier 與 KM 回寫",
"ownerReviewRepairCandidateDraft": "審查修復候選草案、rollback 與 verifier",
"manualReviewNoActionDecision": "人工判斷是否接手或關閉事件"
"manualReviewNoActionDecision": "AI 補齊 evidence / PlayBook 後判定是否關閉事件"
},
"items": {
"km": "KM",

View File

@@ -45,6 +45,7 @@ import { redactPublicIdentifier } from '@/lib/public-security-redaction'
import {
apiClient,
type AiAgent12AgentWarRoomSnapshot,
type AiAgentAutonomousRuntimeControlSnapshot,
type AiAgentProfessionalTaskExpansionSnapshot,
type AiAgentReceiptReadbackOwnerReviewSnapshot,
type AiAgentReportNoWriteAnalysisRuntimeSnapshot,
@@ -849,6 +850,7 @@ function GateMatrixRow({
export function AutomationInventoryTab() {
const t = useTranslations('governance.automationInventory')
const [snapshot, setSnapshot] = useState<AiAgentAutomationInventorySnapshot | null>(null)
const [autonomousRuntimeControl, setAutonomousRuntimeControl] = useState<AiAgentAutonomousRuntimeControlSnapshot | null>(null)
const [backlog, setBacklog] = useState<AiAgentAutomationBacklogSnapshot | null>(null)
const [backupTargets, setBackupTargets] = useState<BackupDrTargetInventorySnapshot | null>(null)
const [backupReadiness, setBackupReadiness] = useState<BackupDrReadinessMatrixSnapshot | null>(null)
@@ -948,6 +950,7 @@ export function AutomationInventoryTab() {
setLoading(true)
const requests = [
apiClient.getAiAgentAutomationInventorySnapshot(),
apiClient.getAiAgentAutonomousRuntimeControl(),
apiClient.getAiAgentAutomationBacklogSnapshot(),
apiClient.getBackupDrTargetInventory(),
apiClient.getBackupDrReadinessMatrix(),
@@ -1040,6 +1043,7 @@ export function AutomationInventoryTab() {
.then((results) => {
const [
inventoryResult,
autonomousRuntimeControlResult,
backlogResult,
targetResult,
readinessResult,
@@ -1129,6 +1133,7 @@ export function AutomationInventoryTab() {
] = results
setSnapshot(settledPublicValue(inventoryResult))
setAutonomousRuntimeControl(settledPublicValue(autonomousRuntimeControlResult))
setBacklog(settledPublicValue(backlogResult))
setBackupTargets(settledPublicValue(targetResult))
setBackupReadiness(settledPublicValue(readinessResult))
@@ -5503,6 +5508,12 @@ export function AutomationInventoryTab() {
tone: hostRedactionLocked && professionalTaskRedactionLocked && warRoomRedactionLocked && serviceHealthRedactionLocked ? 'ok' as const : 'warn' as const,
},
]
const currentAutonomyCadences = autonomousRuntimeControl?.report_delivery.cadences ?? []
const currentAutonomyExecutorReceipts = autonomousRuntimeControl?.controlled_executor.operation_receipts ?? []
const currentAutonomyOverrides = autonomousRuntimeControl?.legacy_policy_overrides ?? []
const currentAutonomyHardBlockers = autonomousRuntimeControl?.hard_blockers ?? []
const currentAutonomyPolicy = autonomousRuntimeControl?.current_policy
const currentAutonomySwitches = autonomousRuntimeControl?.runtime_switches
const globalControlRunwayRows: Array<{
key: string
label: string
@@ -6311,6 +6322,161 @@ export function AutomationInventoryTab() {
]}
/>
{autonomousRuntimeControl ? (
<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 #15803d40',
background: 'rgba(21,128,61,0.08)',
color: '#15803d',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
}}>
<BellRing 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.currentAutonomy.title')}
</span>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#4f6156', lineHeight: 1.55, overflowWrap: 'anywhere' }}>
{autonomousRuntimeControl.program_status.status_note}
</span>
</div>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6, minWidth: 0 }}>
<Chip value={autonomousRuntimeControl.program_status.current_task_id} />
<Chip value={t('globalControl.currentAutonomy.badges.override')} />
<Chip value={t('globalControl.currentAutonomy.badges.gateway')} muted={autonomousRuntimeControl.rollups.telegram_gateway_delivery_enabled_count === 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.currentAutonomy.metrics.completion')} value={`${autonomousRuntimeControl.program_status.implementation_completion_percent}%`} tone="ok" icon={<Gauge size={16} />} />
<MetricCard label={t('globalControl.currentAutonomy.metrics.riskTiers')} value={`${autonomousRuntimeControl.rollups.automated_risk_tier_count}/3`} tone={autonomousRuntimeControl.rollups.automated_risk_tier_count === 3 ? 'ok' : 'warn'} icon={<ShieldCheck size={16} />} />
<MetricCard label={t('globalControl.currentAutonomy.metrics.reports')} value={autonomousRuntimeControl.rollups.report_cadence_enabled_count} tone="ok" icon={<CalendarClock size={16} />} />
<MetricCard label={t('globalControl.currentAutonomy.metrics.gateway')} value={autonomousRuntimeControl.rollups.telegram_gateway_delivery_enabled_count} tone="ok" icon={<BellRing size={16} />} />
<MetricCard label={t('globalControl.currentAutonomy.metrics.executor')} value={autonomousRuntimeControl.rollups.controlled_executor_operation_receipt_count} tone="ok" icon={<ClipboardCheck size={16} />} />
<MetricCard label={t('globalControl.currentAutonomy.metrics.hardBlockers')} value={autonomousRuntimeControl.rollups.hard_blocker_count} tone="warn" icon={<ShieldAlert size={16} />} />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.2fr) minmax(260px, 0.8fr)', gap: 12 }} className="automation-inventory-global-control-grid">
<div style={{ padding: 12, border: '0.5px solid #cfe7d7', borderRadius: 7, background: '#f8fffa', display: 'flex', flexDirection: 'column', gap: 10, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
<SmallLabel>{t('globalControl.currentAutonomy.policyTitle')}</SmallLabel>
<Chip value={autonomousRuntimeControl.program_status.runtime_authority} muted />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 8 }} className="automation-inventory-global-control-pipeline-grid">
<GateMatrixRow
label={t('globalControl.currentAutonomy.policy.low')}
value={currentAutonomyPolicy?.low_risk_controlled_apply_allowed ? 'on' : 'off'}
detail={t('globalControl.currentAutonomy.policy.noOwnerReview', { value: String(currentAutonomyPolicy?.owner_review_required_for_low_medium_high === false) })}
tone={currentAutonomyPolicy?.low_risk_controlled_apply_allowed ? 'ok' : 'warn'}
/>
<GateMatrixRow
label={t('globalControl.currentAutonomy.policy.medium')}
value={currentAutonomyPolicy?.medium_risk_controlled_apply_allowed ? 'on' : 'off'}
detail={t('globalControl.currentAutonomy.policy.verifier', { value: String(currentAutonomyPolicy?.post_apply_verifier_required === true) })}
tone={currentAutonomyPolicy?.medium_risk_controlled_apply_allowed ? 'ok' : 'warn'}
/>
<GateMatrixRow
label={t('globalControl.currentAutonomy.policy.high')}
value={currentAutonomyPolicy?.high_risk_controlled_apply_allowed ? 'on' : 'off'}
detail={t('globalControl.currentAutonomy.policy.km', { value: String(currentAutonomyPolicy?.km_learning_writeback_required === true) })}
tone={currentAutonomyPolicy?.high_risk_controlled_apply_allowed ? 'ok' : 'warn'}
/>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 8 }}>
{currentAutonomyCadences.map(cadence => (
<div key={cadence.cadence} style={{ padding: 10, border: '0.5px solid #d8e8df', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'flex-start' }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 760, color: '#141413', lineHeight: 1.2, overflowWrap: 'anywhere' }}>
{cadence.display_name}
</span>
<Chip value={cadence.telegram_gateway_delivery_enabled ? 'Gateway on' : 'Gateway off'} muted={!cadence.telegram_gateway_delivery_enabled} />
</div>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#50665a', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{cadence.schedule}
</span>
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#50665a', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
{cadence.worker}
</span>
</div>
))}
</div>
</div>
<div style={{ padding: 12, border: '0.5px solid #e5dbc7', borderRadius: 7, background: '#fffdf7', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
<SmallLabel>{t('globalControl.currentAutonomy.runtimeTitle')}</SmallLabel>
<GateMatrixRow
label={t('globalControl.currentAutonomy.runtime.checkMode')}
value={currentAutonomySwitches?.ansible_check_mode_worker_enabled ? 'on' : 'off'}
detail={`interval=${currentAutonomySwitches?.ansible_check_mode_interval_seconds ?? '--'}s batch=${currentAutonomySwitches?.ansible_check_mode_batch_limit ?? '--'}`}
tone={currentAutonomySwitches?.ansible_check_mode_worker_enabled ? 'ok' : 'warn'}
/>
<GateMatrixRow
label={t('globalControl.currentAutonomy.runtime.apply')}
value={currentAutonomySwitches?.ansible_controlled_apply_enabled ? 'on' : 'off'}
detail={(currentAutonomySwitches?.ansible_controlled_apply_allowed_risk_levels ?? []).join(', ') || '--'}
tone={currentAutonomySwitches?.ansible_controlled_apply_enabled ? 'ok' : 'warn'}
/>
<GateMatrixRow
label={t('globalControl.currentAutonomy.runtime.botApi')}
value={currentAutonomyPolicy?.direct_bot_api_allowed ? 'on' : 'off'}
detail={t('globalControl.currentAutonomy.runtime.gatewayOnly')}
tone={currentAutonomyPolicy?.direct_bot_api_allowed ? 'danger' : 'ok'}
/>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 10 }} className="automation-inventory-global-control-runway-grid">
<div style={{ padding: 12, border: '0.5px solid #d7d2f4', borderRadius: 7, background: '#fbfaff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
<SmallLabel>{t('globalControl.currentAutonomy.executorTitle')}</SmallLabel>
{currentAutonomyExecutorReceipts.slice(0, 5).map(receipt => (
<GateMatrixRow
key={receipt.operation_type}
label={receipt.operation_type}
value={receipt.writes_runtime_state ? 'write' : 'dry'}
detail={`${receipt.owner_agent}: ${receipt.purpose}`}
tone={receipt.writes_runtime_state ? 'warn' : 'ok'}
/>
))}
</div>
<div style={{ padding: 12, border: '0.5px solid #d7e2ea', borderRadius: 7, background: '#f9fcff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
<SmallLabel>{t('globalControl.currentAutonomy.overrideTitle')}</SmallLabel>
{currentAutonomyOverrides.slice(0, 4).map(row => (
<GateMatrixRow
key={row.legacy_area}
label={row.legacy_area}
value={row.current_effect}
detail={row.new_behavior}
tone="ok"
/>
))}
</div>
<div style={{ padding: 12, border: '0.5px solid #f1d4d4', borderRadius: 7, background: '#fffafa', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
<SmallLabel>{t('globalControl.currentAutonomy.hardBlockerTitle')}</SmallLabel>
{currentAutonomyHardBlockers.slice(0, 5).map(blocker => (
<GateMatrixRow
key={blocker}
label={blocker}
value="blocked"
detail={t('globalControl.currentAutonomy.hardBlockerDetail')}
tone="warn"
/>
))}
</div>
</div>
</div>
</GlassCard>
) : null}
<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' }}>

View File

@@ -843,6 +843,11 @@ export const apiClient = {
return handleResponse<AiAgentAutomationInventorySnapshot>(res)
},
async getAiAgentAutonomousRuntimeControl() {
const res = await fetch(`${API_BASE_URL}/agents/agent-autonomous-runtime-control`)
return handleResponse<AiAgentAutonomousRuntimeControlSnapshot>(res)
},
async getAiAgentAutomationBacklogSnapshot() {
const res = await fetch(`${API_BASE_URL}/agents/automation-backlog-snapshot`)
return handleResponse<AiAgentAutomationBacklogSnapshot>(res)
@@ -1848,6 +1853,91 @@ export interface AiTechnologyReportCadenceReadback {
// AI Agent Automation Inventory Snapshot
// =========================================================================
export interface AiAgentAutonomousRuntimeControlSnapshot {
schema_version: 'ai_agent_autonomous_runtime_control_v1'
generated_at: string
program_status: {
current_task_id: 'P2-416-D1N'
status: string
runtime_authority: 'current_owner_directive_controlled_ai_automation'
legacy_no_send_no_live_rules_overridden: true
implementation_completion_percent: number
status_note: string
}
current_policy: {
low_risk_controlled_apply_allowed: boolean
medium_risk_controlled_apply_allowed: boolean
high_risk_controlled_apply_allowed: boolean
critical_break_glass_required: boolean
owner_review_required_for_low_medium_high: boolean
direct_bot_api_allowed: boolean
telegram_gateway_required: boolean
post_apply_verifier_required: boolean
km_learning_writeback_required: boolean
}
runtime_switches: {
ansible_check_mode_worker_enabled: boolean
ansible_controlled_apply_enabled: boolean
ansible_controlled_apply_allowed_risk_levels: string[]
ansible_check_mode_interval_seconds: number
ansible_check_mode_batch_limit: number
ansible_check_mode_timeout_seconds: number
ansible_controlled_apply_timeout_seconds: number
}
agent_roles: Array<{
agent_id: string
role: string
current_job: string
}>
report_delivery: {
status: string
cadences: Array<{
cadence: 'daily' | 'weekly' | 'monthly'
display_name: string
schedule: string
worker: string
telegram_gateway_delivery_enabled: boolean
direct_bot_api_allowed: boolean
receipt_source: string
}>
}
controlled_executor: {
status: string
operation_receipts: Array<{
operation_type: string
owner_agent: string
purpose: string
writes_runtime_state: boolean
}>
required_flow: string[]
}
legacy_policy_overrides: Array<{
legacy_area: string
current_effect: string
new_behavior: string
}>
hard_blockers: string[]
visibility_contract: {
frontend_displays_runtime_truth: boolean
work_window_transcript_display_allowed: boolean
raw_prompt_display_allowed: boolean
private_reasoning_display_allowed: boolean
secret_value_display_allowed: boolean
raw_telegram_payload_display_allowed: boolean
lan_topology_redaction_required: boolean
}
rollups: {
automated_risk_tier_count: number
hard_blocker_count: number
report_cadence_enabled_count: number
telegram_gateway_delivery_enabled_count: number
direct_bot_api_allowed_count: number
controlled_executor_operation_receipt_count: number
runtime_write_receipt_type_count: number
legacy_policy_overridden_count: number
}
}
export interface AiAgentAutomationInventorySnapshot {
schema_version: 'ai_agent_automation_inventory_snapshot_v1'
generated_at: string