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
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:
@@ -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' }}>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user