fix(ui): make autonomous control cockpit visual
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 39s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 0s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Failing after 1m14s
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 39s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 0s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Failing after 1m14s
This commit is contained in:
@@ -3852,6 +3852,45 @@
|
||||
"overrideTitle": "舊規範覆寫",
|
||||
"hardBlockerTitle": "仍維持硬阻擋",
|
||||
"hardBlockerDetail": "需 break-glass 或專案級合約,不由一般自動化靜默執行。",
|
||||
"cockpit": {
|
||||
"liveLabel": "LIVE PRODUCTION",
|
||||
"title": "AI Agent Cockpit",
|
||||
"subtitle": "Production readback for the active control layer, closed loop, receipts, and hard boundaries.",
|
||||
"production": "Production",
|
||||
"dbOk": "DB readback OK",
|
||||
"dbReview": "DB readback review",
|
||||
"workItems": "Work items",
|
||||
"consumer": "LOG consumer",
|
||||
"apply": "Apply",
|
||||
"verifier": "Verifier",
|
||||
"km": "KM",
|
||||
"telegram": "Telegram",
|
||||
"receiptDetail": "controlled runtime receipt",
|
||||
"verifierDetail": "post-apply verifier",
|
||||
"kmDetail": "KM / PlayBook writeback",
|
||||
"telegramDetail": "Gateway receipt",
|
||||
"loopTitle": "Runtime loop",
|
||||
"closed": "closed",
|
||||
"review": "review",
|
||||
"missing": "missing",
|
||||
"runtimeWrite": "runtime write",
|
||||
"noRuntimeWrite": "no runtime write",
|
||||
"riskTitle": "Controlled risk lanes",
|
||||
"on": "ON",
|
||||
"off": "OFF",
|
||||
"ownerRequired": "owner review required",
|
||||
"ownerNotRequired": "owner review not required",
|
||||
"criticalBreakGlass": "critical break-glass",
|
||||
"criticalReview": "critical review"
|
||||
},
|
||||
"flow": {
|
||||
"candidate": "Candidate",
|
||||
"checkMode": "Check-mode",
|
||||
"apply": "Controlled apply",
|
||||
"verifier": "Verifier",
|
||||
"learning": "KM learning",
|
||||
"telegram": "Telegram"
|
||||
},
|
||||
"readback": {
|
||||
"marker": "Production v2 marker",
|
||||
"markerDetail": "{task} · {status}",
|
||||
|
||||
@@ -3852,6 +3852,45 @@
|
||||
"overrideTitle": "舊規範覆寫",
|
||||
"hardBlockerTitle": "仍維持硬阻擋",
|
||||
"hardBlockerDetail": "需 break-glass 或專案級合約,不由一般自動化靜默執行。",
|
||||
"cockpit": {
|
||||
"liveLabel": "LIVE PRODUCTION",
|
||||
"title": "AI Agent Cockpit",
|
||||
"subtitle": "用 production readback 呈現控制層、閉環、收據與硬邊界。",
|
||||
"production": "Production",
|
||||
"dbOk": "DB readback OK",
|
||||
"dbReview": "DB readback review",
|
||||
"workItems": "Work items",
|
||||
"consumer": "LOG consumer",
|
||||
"apply": "Apply",
|
||||
"verifier": "Verifier",
|
||||
"km": "KM",
|
||||
"telegram": "Telegram",
|
||||
"receiptDetail": "controlled runtime receipt",
|
||||
"verifierDetail": "post-apply verifier",
|
||||
"kmDetail": "KM / PlayBook writeback",
|
||||
"telegramDetail": "Gateway receipt",
|
||||
"loopTitle": "Runtime loop",
|
||||
"closed": "closed",
|
||||
"review": "review",
|
||||
"missing": "missing",
|
||||
"runtimeWrite": "runtime write",
|
||||
"noRuntimeWrite": "no runtime write",
|
||||
"riskTitle": "Controlled risk lanes",
|
||||
"on": "ON",
|
||||
"off": "OFF",
|
||||
"ownerRequired": "owner review required",
|
||||
"ownerNotRequired": "owner review not required",
|
||||
"criticalBreakGlass": "critical break-glass",
|
||||
"criticalReview": "critical review"
|
||||
},
|
||||
"flow": {
|
||||
"candidate": "Candidate",
|
||||
"checkMode": "Check-mode",
|
||||
"apply": "Controlled apply",
|
||||
"verifier": "Verifier",
|
||||
"learning": "KM learning",
|
||||
"telegram": "Telegram"
|
||||
},
|
||||
"readback": {
|
||||
"marker": "Production v2 marker",
|
||||
"markerDetail": "{task} · {status}",
|
||||
|
||||
@@ -853,6 +853,237 @@ function GateMatrixRow({
|
||||
)
|
||||
}
|
||||
|
||||
function AutonomyCockpitMetric({
|
||||
label,
|
||||
value,
|
||||
detail,
|
||||
tone = 'neutral',
|
||||
icon,
|
||||
}: {
|
||||
label: string
|
||||
value: number | string
|
||||
detail: string
|
||||
tone?: 'ok' | 'warn' | 'danger' | 'neutral'
|
||||
icon: ReactNode
|
||||
}) {
|
||||
const color = toneColor(tone)
|
||||
return (
|
||||
<div style={{
|
||||
padding: 12,
|
||||
border: `0.5px solid ${color}40`,
|
||||
borderRadius: 7,
|
||||
background: '#fff',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '32px minmax(0, 1fr)',
|
||||
gap: 10,
|
||||
alignItems: 'center',
|
||||
minWidth: 0,
|
||||
}}>
|
||||
<div style={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 7,
|
||||
border: `0.5px solid ${color}55`,
|
||||
background: `${color}12`,
|
||||
color,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
{icon}
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 5, minWidth: 0 }}>
|
||||
<SmallLabel>{label}</SmallLabel>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 26, fontWeight: 780, color, lineHeight: 1, overflowWrap: 'anywhere' }}>
|
||||
{value}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#6b675f', lineHeight: 1.35, overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(detail)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function AutonomyFlowStep({
|
||||
label,
|
||||
status,
|
||||
detail,
|
||||
tone = 'neutral',
|
||||
icon,
|
||||
}: {
|
||||
label: string
|
||||
status: string
|
||||
detail: string
|
||||
tone?: 'ok' | 'warn' | 'danger' | 'neutral'
|
||||
icon: ReactNode
|
||||
}) {
|
||||
const color = toneColor(tone)
|
||||
return (
|
||||
<div style={{
|
||||
padding: 11,
|
||||
border: `0.5px solid ${color}40`,
|
||||
borderRadius: 7,
|
||||
background: '#fff',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 9,
|
||||
minWidth: 0,
|
||||
}}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 8, 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,
|
||||
}}>
|
||||
{icon}
|
||||
</div>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, fontWeight: 800, color, textAlign: 'right', overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(status)}
|
||||
</span>
|
||||
</div>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 760, color: '#141413', lineHeight: 1.15, overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(label)}
|
||||
</span>
|
||||
<div style={{ height: 4, borderRadius: 999, background: '#eee9dd', overflow: 'hidden' }}>
|
||||
<div style={{ width: tone === 'danger' ? '40%' : tone === 'warn' ? '70%' : '100%', height: '100%', background: color }} />
|
||||
</div>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#706d65', lineHeight: 1.35, overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(detail)}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function autonomyStageTone(stage: { present: boolean; status: string } | undefined, loopClosed: boolean): 'ok' | 'warn' | 'danger' | 'neutral' {
|
||||
if (!stage?.present) return 'danger'
|
||||
if (['success', 'sent', 'REVIEW', 'inferred_from_check_mode'].includes(stage.status)) return 'ok'
|
||||
if (stage.status === 'failed' && loopClosed) return 'warn'
|
||||
if (stage.status === 'failed') return 'danger'
|
||||
return 'neutral'
|
||||
}
|
||||
|
||||
function AutonomyWorkspaceScene({
|
||||
stations,
|
||||
completion,
|
||||
status,
|
||||
}: {
|
||||
stations: Array<{
|
||||
key: string
|
||||
label: string
|
||||
value: number | string
|
||||
tone: 'ok' | 'warn' | 'danger' | 'neutral'
|
||||
icon: ReactNode
|
||||
}>
|
||||
completion: number
|
||||
status: string
|
||||
}) {
|
||||
const safeCompletion = Math.max(0, Math.min(100, completion))
|
||||
return (
|
||||
<div className="automation-inventory-autonomy-workspace-scene" style={{
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
border: '0.5px solid #cfe7d7',
|
||||
borderRadius: 8,
|
||||
background: '#f7fff9',
|
||||
minHeight: 238,
|
||||
padding: 14,
|
||||
}}>
|
||||
<div className="automation-inventory-autonomy-workspace-rail" aria-hidden="true" />
|
||||
<span className="automation-inventory-autonomy-workspace-packet automation-inventory-autonomy-workspace-packet-a" aria-hidden="true" />
|
||||
<span className="automation-inventory-autonomy-workspace-packet automation-inventory-autonomy-workspace-packet-b" aria-hidden="true" />
|
||||
<span className="automation-inventory-autonomy-workspace-packet automation-inventory-autonomy-workspace-packet-c" aria-hidden="true" />
|
||||
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
inset: '50% auto auto 50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
width: 132,
|
||||
height: 132,
|
||||
borderRadius: 8,
|
||||
border: '0.5px solid #15803d33',
|
||||
background: 'rgba(255,255,255,0.9)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: 7,
|
||||
zIndex: 2,
|
||||
boxShadow: '0 12px 30px rgba(20, 20, 19, 0.08)',
|
||||
}} className="automation-inventory-autonomy-workspace-console">
|
||||
<Gauge size={20} style={{ color: '#15803d' }} />
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 34, fontWeight: 800, lineHeight: 1, color: '#15803d' }}>
|
||||
{safeCompletion}%
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#4f6156', textAlign: 'center', lineHeight: 1.3, overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(status)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
position: 'relative',
|
||||
zIndex: 3,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
|
||||
gap: 10,
|
||||
minHeight: 210,
|
||||
alignItems: 'stretch',
|
||||
}} className="automation-inventory-autonomy-workspace-grid">
|
||||
{stations.map((station, index) => {
|
||||
const color = toneColor(station.tone)
|
||||
return (
|
||||
<div
|
||||
key={station.key}
|
||||
className={`automation-inventory-autonomy-workspace-station automation-inventory-autonomy-workspace-station-${index}`}
|
||||
style={{
|
||||
padding: 11,
|
||||
border: `0.5px solid ${color}44`,
|
||||
borderRadius: 8,
|
||||
background: 'rgba(255,255,255,0.93)',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
gap: 10,
|
||||
minWidth: 0,
|
||||
minHeight: 92,
|
||||
boxShadow: '0 8px 20px rgba(20, 20, 19, 0.05)',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, 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,
|
||||
}}>
|
||||
{station.icon}
|
||||
</div>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 22, fontWeight: 800, lineHeight: 1, color }}>
|
||||
{station.value}
|
||||
</span>
|
||||
</div>
|
||||
<SmallLabel>{station.label}</SmallLabel>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function AutonomousRuntimeControlReadbackGrid({
|
||||
control,
|
||||
t,
|
||||
@@ -5782,6 +6013,99 @@ export function AutomationInventoryTab() {
|
||||
const currentAutonomyHardBlockers = autonomousRuntimeControl?.hard_blockers ?? []
|
||||
const currentAutonomyPolicy = autonomousRuntimeControl?.current_policy
|
||||
const currentAutonomySwitches = autonomousRuntimeControl?.runtime_switches
|
||||
const currentAutonomyRuntimeReadback = autonomousRuntimeControl?.runtime_receipt_readback
|
||||
const currentAutonomyLoopLedger = currentAutonomyRuntimeReadback?.autonomous_execution_loop_ledger
|
||||
const currentAutonomyLoopClosed = currentAutonomyLoopLedger?.closed === true
|
||||
const currentAutonomyStageById = new Map((currentAutonomyLoopLedger?.stages ?? []).map(stage => [stage.stage_id, stage]))
|
||||
const currentAutonomyFlowStages = [
|
||||
{
|
||||
key: 'candidate',
|
||||
label: t('globalControl.currentAutonomy.flow.candidate'),
|
||||
stage: currentAutonomyStageById.get('candidate'),
|
||||
icon: <Target size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'checkMode',
|
||||
label: t('globalControl.currentAutonomy.flow.checkMode'),
|
||||
stage: currentAutonomyStageById.get('check_mode'),
|
||||
icon: <ShieldCheck size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'apply',
|
||||
label: t('globalControl.currentAutonomy.flow.apply'),
|
||||
stage: currentAutonomyStageById.get('controlled_apply'),
|
||||
icon: <ClipboardCheck size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'verifier',
|
||||
label: t('globalControl.currentAutonomy.flow.verifier'),
|
||||
stage: currentAutonomyStageById.get('post_apply_verifier'),
|
||||
icon: <Gauge size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'learning',
|
||||
label: t('globalControl.currentAutonomy.flow.learning'),
|
||||
stage: currentAutonomyStageById.get('km_playbook_writeback'),
|
||||
icon: <BookOpenCheck size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'telegram',
|
||||
label: t('globalControl.currentAutonomy.flow.telegram'),
|
||||
stage: currentAutonomyStageById.get('telegram_receipt'),
|
||||
icon: <BellRing size={15} />,
|
||||
},
|
||||
]
|
||||
const currentAutonomyReceiptStats = [
|
||||
{
|
||||
key: 'apply',
|
||||
label: t('globalControl.currentAutonomy.cockpit.apply'),
|
||||
value: autonomousRuntimeControl?.rollups.live_ansible_apply_executed_count ?? 0,
|
||||
detail: t('globalControl.currentAutonomy.cockpit.receiptDetail'),
|
||||
tone: (autonomousRuntimeControl?.rollups.live_ansible_apply_executed_count ?? 0) > 0 ? 'ok' as const : 'warn' as const,
|
||||
icon: <ClipboardCheck size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'verifier',
|
||||
label: t('globalControl.currentAutonomy.cockpit.verifier'),
|
||||
value: autonomousRuntimeControl?.rollups.live_post_apply_verifier_count ?? 0,
|
||||
detail: t('globalControl.currentAutonomy.cockpit.verifierDetail'),
|
||||
tone: (autonomousRuntimeControl?.rollups.live_post_apply_verifier_count ?? 0) > 0 ? 'ok' as const : 'warn' as const,
|
||||
icon: <Gauge size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'km',
|
||||
label: t('globalControl.currentAutonomy.cockpit.km'),
|
||||
value: autonomousRuntimeControl?.rollups.live_km_writeback_count ?? 0,
|
||||
detail: t('globalControl.currentAutonomy.cockpit.kmDetail'),
|
||||
tone: (autonomousRuntimeControl?.rollups.live_km_writeback_count ?? 0) > 0 ? 'ok' as const : 'warn' as const,
|
||||
icon: <BookOpenCheck size={15} />,
|
||||
},
|
||||
{
|
||||
key: 'telegram',
|
||||
label: t('globalControl.currentAutonomy.cockpit.telegram'),
|
||||
value: autonomousRuntimeControl?.rollups.live_telegram_receipt_count ?? 0,
|
||||
detail: t('globalControl.currentAutonomy.cockpit.telegramDetail'),
|
||||
tone: (autonomousRuntimeControl?.rollups.live_telegram_receipt_count ?? 0) > 0 ? 'ok' as const : 'warn' as const,
|
||||
icon: <BellRing size={15} />,
|
||||
},
|
||||
]
|
||||
const currentAutonomyRiskRows = [
|
||||
{
|
||||
key: 'low',
|
||||
label: t('globalControl.currentAutonomy.policy.low'),
|
||||
enabled: currentAutonomyPolicy?.low_risk_controlled_apply_allowed === true,
|
||||
},
|
||||
{
|
||||
key: 'medium',
|
||||
label: t('globalControl.currentAutonomy.policy.medium'),
|
||||
enabled: currentAutonomyPolicy?.medium_risk_controlled_apply_allowed === true,
|
||||
},
|
||||
{
|
||||
key: 'high',
|
||||
label: t('globalControl.currentAutonomy.policy.high'),
|
||||
enabled: currentAutonomyPolicy?.high_risk_controlled_apply_allowed === true,
|
||||
},
|
||||
]
|
||||
const globalControlRunwayRows: Array<{
|
||||
key: string
|
||||
label: string
|
||||
@@ -6592,9 +6916,19 @@ 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={{ display: 'flex', flexDirection: 'column', gap: 12, minWidth: 0 }} className="automation-inventory-autonomy-cockpit">
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'minmax(0, 1fr) auto',
|
||||
gap: 12,
|
||||
alignItems: 'start',
|
||||
padding: 14,
|
||||
border: '0.5px solid #cfe7d7',
|
||||
borderRadius: 8,
|
||||
background: 'linear-gradient(135deg, rgba(248,255,250,0.96), rgba(255,255,255,0.98))',
|
||||
minWidth: 0,
|
||||
}} className="automation-inventory-autonomy-cockpit-header">
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '38px minmax(0, 1fr)', gap: 10, alignItems: 'start', minWidth: 0 }}>
|
||||
<div style={{
|
||||
width: 38,
|
||||
height: 38,
|
||||
@@ -6610,138 +6944,143 @@ export function AutomationInventoryTab() {
|
||||
<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')}
|
||||
<SmallLabel>{t('globalControl.currentAutonomy.cockpit.liveLabel')}</SmallLabel>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 22, fontWeight: 780, color: '#141413', lineHeight: 1.05, overflowWrap: 'anywhere' }}>
|
||||
{t('globalControl.currentAutonomy.cockpit.title')}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#4f6156', lineHeight: 1.55, overflowWrap: 'anywhere' }}>
|
||||
{autonomousRuntimeControl.program_status.status_note}
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#4f6156', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{t('globalControl.currentAutonomy.cockpit.subtitle')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6, minWidth: 0, maxWidth: 460 }}>
|
||||
<Chip value={autonomousRuntimeControl.program_status.current_task_id} />
|
||||
<Chip value={t('globalControl.currentAutonomy.badges.override')} />
|
||||
<Chip value={currentAutonomyRuntimeReadback?.db_read_status === 'ok' ? t('globalControl.currentAutonomy.cockpit.dbOk') : t('globalControl.currentAutonomy.cockpit.dbReview')} />
|
||||
<Chip value={t('globalControl.currentAutonomy.badges.gateway')} muted={autonomousRuntimeControl.rollups.telegram_gateway_delivery_enabled_count === 0} />
|
||||
<Chip value={`${t('globalControl.currentAutonomy.badges.deployMarker')}: ${autonomousRuntimeControl.program_status.deploy_readback_marker}`} muted />
|
||||
<Chip value={t('globalControl.currentAutonomy.badges.override')} muted />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AutonomousRuntimeControlReadbackGrid control={autonomousRuntimeControl} t={t} />
|
||||
<AutonomyWorkspaceScene
|
||||
stations={currentAutonomyReceiptStats}
|
||||
completion={autonomousRuntimeControl.program_status.implementation_completion_percent}
|
||||
status={currentAutonomyLoopClosed ? t('globalControl.currentAutonomy.cockpit.closed') : t('globalControl.currentAutonomy.cockpit.review')}
|
||||
/>
|
||||
|
||||
<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 style={{ display: 'grid', gridTemplateColumns: 'minmax(280px, 0.9fr) minmax(0, 1.1fr)', gap: 12 }} className="automation-inventory-autonomy-cockpit-hero-grid">
|
||||
<div style={{ padding: 14, border: '0.5px solid #d9eadf', borderRadius: 8, background: '#fff', display: 'flex', flexDirection: 'column', gap: 12, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
|
||||
<SmallLabel>{t('globalControl.currentAutonomy.metrics.completion')}</SmallLabel>
|
||||
<Chip value={t('globalControl.currentAutonomy.cockpit.production')} />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 0.75fr) minmax(0, 1.25fr)', gap: 14, alignItems: 'end' }} className="automation-inventory-autonomy-cockpit-score-grid">
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 52, fontWeight: 800, color: '#15803d', lineHeight: 0.95 }}>
|
||||
{autonomousRuntimeControl.program_status.implementation_completion_percent}%
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
|
||||
<div style={{ height: 8, borderRadius: 999, background: '#edf3ea', overflow: 'hidden' }}>
|
||||
<div style={{ width: `${Math.min(100, autonomousRuntimeControl.program_status.implementation_completion_percent)}%`, height: '100%', background: '#15803d' }} />
|
||||
</div>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#5c675d', lineHeight: 1.35, overflowWrap: 'anywhere' }}>
|
||||
{autonomousRuntimeControl.program_status.deploy_readback_marker}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={`${t('globalControl.currentAutonomy.cockpit.workItems')}: ${autonomousRuntimeControl.rollups.live_work_item_completed_count ?? 0}`} />
|
||||
<Chip value={`${t('globalControl.currentAutonomy.metrics.hardBlockers')}: ${autonomousRuntimeControl.rollups.hard_blocker_count}`} muted />
|
||||
<Chip value={`${t('globalControl.currentAutonomy.cockpit.consumer')}: ${autonomousRuntimeControl.rollups.live_log_controlled_writeback_consumer_apply_receipt_count ?? 0}`} muted />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 10 }} className="automation-inventory-autonomy-cockpit-metric-grid">
|
||||
{currentAutonomyReceiptStats.map(stat => (
|
||||
<AutonomyCockpitMetric
|
||||
key={stat.key}
|
||||
label={stat.label}
|
||||
value={stat.value}
|
||||
detail={stat.detail}
|
||||
tone={stat.tone}
|
||||
icon={stat.icon}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</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={{ padding: 12, border: '0.5px solid #d7e5d8', borderRadius: 8, background: '#f9fff9', 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.cockpit.loopTitle')}</SmallLabel>
|
||||
<Chip value={currentAutonomyLoopClosed ? t('globalControl.currentAutonomy.cockpit.closed') : t('globalControl.currentAutonomy.cockpit.review')} />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, minmax(0, 1fr))', gap: 9 }} className="automation-inventory-autonomy-cockpit-flow-grid">
|
||||
{currentAutonomyFlowStages.map(row => (
|
||||
<AutonomyFlowStep
|
||||
key={row.key}
|
||||
label={row.label}
|
||||
status={row.stage?.status ?? t('globalControl.currentAutonomy.cockpit.missing')}
|
||||
detail={row.stage?.writes_runtime_state ? t('globalControl.currentAutonomy.cockpit.runtimeWrite') : t('globalControl.currentAutonomy.cockpit.noRuntimeWrite')}
|
||||
tone={autonomyStageTone(row.stage, currentAutonomyLoopClosed)}
|
||||
icon={row.icon}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: 12 }} className="automation-inventory-autonomy-cockpit-control-grid">
|
||||
<div style={{ padding: 12, border: '0.5px solid #d7e2ea', borderRadius: 8, background: '#f9fcff', 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 />
|
||||
<SmallLabel>{t('globalControl.currentAutonomy.cockpit.riskTitle')}</SmallLabel>
|
||||
<Chip value={`${autonomousRuntimeControl.rollups.automated_risk_tier_count}/3`} />
|
||||
</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) })}
|
||||
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}
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 8 }} className="automation-inventory-autonomy-cockpit-risk-grid">
|
||||
{currentAutonomyRiskRows.map(row => (
|
||||
<div key={row.key} style={{ padding: 10, border: `0.5px solid ${row.enabled ? '#22C55E44' : '#F59E0B44'}`, borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<SmallLabel>{row.label}</SmallLabel>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 20, fontWeight: 780, color: row.enabled ? '#22C55E' : '#F59E0B', lineHeight: 1 }}>
|
||||
{row.enabled ? t('globalControl.currentAutonomy.cockpit.on') : t('globalControl.currentAutonomy.cockpit.off')}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={currentAutonomyPolicy?.owner_review_required_for_low_medium_high ? t('globalControl.currentAutonomy.cockpit.ownerRequired') : t('globalControl.currentAutonomy.cockpit.ownerNotRequired')} muted />
|
||||
<Chip value={currentAutonomyPolicy?.critical_break_glass_required ? t('globalControl.currentAutonomy.cockpit.criticalBreakGlass') : t('globalControl.currentAutonomy.cockpit.criticalReview')} muted />
|
||||
<Chip value={`${t('globalControl.currentAutonomy.overrideTitle')}: ${currentAutonomyOverrides.length}`} muted />
|
||||
</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 style={{ padding: 12, border: '0.5px solid #e5dbc7', borderRadius: 8, background: '#fffdf7', 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.runtimeTitle')}</SmallLabel>
|
||||
<Chip value={(currentAutonomySwitches?.ansible_controlled_apply_allowed_risk_levels ?? []).join(', ') || '--'} muted />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 8 }} className="automation-inventory-autonomy-cockpit-runtime-grid">
|
||||
<AutonomyCockpitMetric
|
||||
label={t('globalControl.currentAutonomy.runtime.checkMode')}
|
||||
value={currentAutonomySwitches?.ansible_check_mode_worker_enabled ? t('globalControl.currentAutonomy.cockpit.on') : t('globalControl.currentAutonomy.cockpit.off')}
|
||||
detail={`${currentAutonomySwitches?.ansible_check_mode_interval_seconds ?? '--'}s`}
|
||||
tone={currentAutonomySwitches?.ansible_check_mode_worker_enabled ? 'ok' : 'warn'}
|
||||
icon={<ShieldCheck size={15} />}
|
||||
/>
|
||||
))}
|
||||
</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"
|
||||
<AutonomyCockpitMetric
|
||||
label={t('globalControl.currentAutonomy.runtime.apply')}
|
||||
value={currentAutonomySwitches?.ansible_controlled_apply_enabled ? t('globalControl.currentAutonomy.cockpit.on') : t('globalControl.currentAutonomy.cockpit.off')}
|
||||
detail={`${t('globalControl.currentAutonomy.executorTitle')}: ${currentAutonomyExecutorReceipts.length}`}
|
||||
tone={currentAutonomySwitches?.ansible_controlled_apply_enabled ? 'ok' : 'warn'}
|
||||
icon={<Route size={15} />}
|
||||
/>
|
||||
))}
|
||||
</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"
|
||||
<AutonomyCockpitMetric
|
||||
label={t('globalControl.currentAutonomy.metrics.reports')}
|
||||
value={currentAutonomyCadences.length}
|
||||
detail={currentAutonomyCadences.map(cadence => cadence.cadence).join(' / ') || '--'}
|
||||
tone={currentAutonomyCadences.length > 0 ? 'ok' : 'warn'}
|
||||
icon={<CalendarClock size={15} />}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={`${t('globalControl.currentAutonomy.hardBlockerTitle')}: ${currentAutonomyHardBlockers.length}`} muted />
|
||||
<Chip value={currentAutonomyPolicy?.direct_bot_api_allowed ? t('globalControl.currentAutonomy.runtime.botApi') : t('globalControl.currentAutonomy.runtime.gatewayOnly')} muted={!currentAutonomyPolicy?.direct_bot_api_allowed} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -20187,7 +20526,117 @@ export function AutomationInventoryTab() {
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-rail {
|
||||
position: absolute;
|
||||
inset: 28px;
|
||||
border: 0.5px solid rgba(21, 128, 61, 0.18);
|
||||
border-radius: 8px;
|
||||
background:
|
||||
linear-gradient(90deg, rgba(21, 128, 61, 0.08) 1px, transparent 1px),
|
||||
linear-gradient(0deg, rgba(21, 128, 61, 0.06) 1px, transparent 1px);
|
||||
background-size: 44px 44px;
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-packet {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 3px;
|
||||
background: #15803d;
|
||||
box-shadow: 0 0 0 4px rgba(21, 128, 61, 0.12), 0 8px 18px rgba(21, 128, 61, 0.22);
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-packet-a {
|
||||
top: 48%;
|
||||
left: 10%;
|
||||
animation: autonomy-packet-x 4.8s linear infinite;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-packet-b {
|
||||
top: 22%;
|
||||
left: 48%;
|
||||
animation: autonomy-packet-y 5.4s linear infinite;
|
||||
animation-delay: 0.8s;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-packet-c {
|
||||
top: 72%;
|
||||
left: 16%;
|
||||
animation: autonomy-packet-x 6.2s linear infinite;
|
||||
animation-delay: 1.6s;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-station {
|
||||
animation: autonomy-station-breathe 3.8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-station-1 {
|
||||
animation-delay: 0.25s;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-station-2 {
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-station-3 {
|
||||
animation-delay: 0.75s;
|
||||
}
|
||||
|
||||
@keyframes autonomy-packet-x {
|
||||
0% {
|
||||
left: 10%;
|
||||
opacity: 0;
|
||||
}
|
||||
12% {
|
||||
opacity: 1;
|
||||
}
|
||||
88% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
left: 88%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes autonomy-packet-y {
|
||||
0% {
|
||||
top: 18%;
|
||||
opacity: 0;
|
||||
}
|
||||
12% {
|
||||
opacity: 1;
|
||||
}
|
||||
88% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
top: 78%;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes autonomy-station-breathe {
|
||||
0%, 100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.automation-inventory-autonomy-cockpit-header,
|
||||
.automation-inventory-autonomy-cockpit-hero-grid,
|
||||
.automation-inventory-autonomy-cockpit-score-grid,
|
||||
.automation-inventory-autonomy-cockpit-metric-grid,
|
||||
.automation-inventory-autonomy-cockpit-flow-grid,
|
||||
.automation-inventory-autonomy-cockpit-control-grid,
|
||||
.automation-inventory-autonomy-cockpit-risk-grid,
|
||||
.automation-inventory-autonomy-cockpit-runtime-grid,
|
||||
.automation-inventory-autonomy-workspace-grid,
|
||||
.automation-inventory-visual-grid,
|
||||
.automation-inventory-stage-grid,
|
||||
.automation-inventory-visual-factor-grid,
|
||||
@@ -20269,6 +20718,25 @@ export function AutomationInventoryTab() {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-scene {
|
||||
min-height: 430px !important;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-console {
|
||||
position: relative !important;
|
||||
inset: auto !important;
|
||||
transform: none !important;
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
min-height: 104px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.automation-inventory-autonomy-workspace-rail,
|
||||
.automation-inventory-autonomy-workspace-packet {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.automation-inventory-tab-root button,
|
||||
.automation-inventory-tab-root [role='button'],
|
||||
.automation-inventory-tab-root span,
|
||||
|
||||
@@ -2213,6 +2213,11 @@ export interface AiAgentAutonomousRuntimeControlSnapshot {
|
||||
live_km_writeback_count?: number
|
||||
live_post_apply_verifier_count?: number
|
||||
live_telegram_receipt_count?: number
|
||||
live_log_controlled_writeback_consumer_apply_receipt_count?: number
|
||||
live_log_controlled_writeback_consumer_dispatch_ledger_count?: number
|
||||
live_log_controlled_writeback_runtime_target_write_count?: number
|
||||
live_work_item_completed_count?: number
|
||||
live_work_item_blocked_count?: number
|
||||
mcp_sensor_count?: number
|
||||
rag_context_query_count?: number
|
||||
playbook_decision_class_count?: number
|
||||
|
||||
Reference in New Issue
Block a user