feat(governance): 新增 owner-approved fixture promotion gate
This commit is contained in:
@@ -62,6 +62,7 @@ import {
|
||||
type AiAgentRuntimeReadbackFixtureApprovalSnapshot,
|
||||
type AiAgentRuntimeReadbackImplementationReviewSnapshot,
|
||||
type AiAgentRuntimeReadbackPromotionGateSnapshot,
|
||||
type AiAgentOwnerApprovedFixturePromotionGateSnapshot,
|
||||
type AiAgentRuntimeWorkerShadowGateSnapshot,
|
||||
type AiAgentRuntimeVerifierEvidenceReviewSnapshot,
|
||||
type AiAgentRuntimeWriteGateReviewSnapshot,
|
||||
@@ -444,6 +445,7 @@ export function AutomationInventoryTab() {
|
||||
const [reportLiveDeliveryApprovalPackage, setReportLiveDeliveryApprovalPackage] = useState<AiAgentReportLiveDeliveryApprovalPackageSnapshot | null>(null)
|
||||
const [runtimeReadbackFixtureApproval, setRuntimeReadbackFixtureApproval] = useState<AiAgentRuntimeReadbackFixtureApprovalSnapshot | null>(null)
|
||||
const [runtimeReadbackPromotionGate, setRuntimeReadbackPromotionGate] = useState<AiAgentRuntimeReadbackPromotionGateSnapshot | null>(null)
|
||||
const [ownerApprovedFixturePromotionGate, setOwnerApprovedFixturePromotionGate] = useState<AiAgentOwnerApprovedFixturePromotionGateSnapshot | null>(null)
|
||||
const [reportTruthActionabilityReview, setReportTruthActionabilityReview] = useState<AiAgentReportTruthActionabilityReviewSnapshot | null>(null)
|
||||
const [ownerDryRunPackage, setOwnerDryRunPackage] = useState<AiAgentOwnerApprovedFixtureDryRunSnapshot | null>(null)
|
||||
const [hostStatefulInventory, setHostStatefulInventory] = useState<AiAgentHostStatefulVersionInventorySnapshot | null>(null)
|
||||
@@ -494,6 +496,7 @@ export function AutomationInventoryTab() {
|
||||
apiClient.getAiAgentReportLiveDeliveryApprovalPackage(),
|
||||
apiClient.getAiAgentRuntimeReadbackFixtureApproval(),
|
||||
apiClient.getAiAgentRuntimeReadbackPromotionGate(),
|
||||
apiClient.getAiAgentOwnerApprovedFixturePromotionGate(),
|
||||
apiClient.getAiAgentReportTruthActionabilityReview(),
|
||||
apiClient.getAiAgentOwnerApprovedFixtureDryRun(),
|
||||
apiClient.getAiAgentHostStatefulVersionInventory(),
|
||||
@@ -543,6 +546,7 @@ export function AutomationInventoryTab() {
|
||||
reportLiveDeliveryApprovalPackageResult,
|
||||
runtimeReadbackFixtureApprovalResult,
|
||||
runtimeReadbackPromotionGateResult,
|
||||
ownerApprovedFixturePromotionGateResult,
|
||||
reportTruthActionabilityReviewResult,
|
||||
ownerDryRunPackageResult,
|
||||
hostStatefulInventoryResult,
|
||||
@@ -589,6 +593,7 @@ export function AutomationInventoryTab() {
|
||||
setReportLiveDeliveryApprovalPackage(reportLiveDeliveryApprovalPackageResult.status === 'fulfilled' ? reportLiveDeliveryApprovalPackageResult.value : null)
|
||||
setRuntimeReadbackFixtureApproval(runtimeReadbackFixtureApprovalResult.status === 'fulfilled' ? runtimeReadbackFixtureApprovalResult.value : null)
|
||||
setRuntimeReadbackPromotionGate(runtimeReadbackPromotionGateResult.status === 'fulfilled' ? runtimeReadbackPromotionGateResult.value : null)
|
||||
setOwnerApprovedFixturePromotionGate(ownerApprovedFixturePromotionGateResult.status === 'fulfilled' ? ownerApprovedFixturePromotionGateResult.value : null)
|
||||
setReportTruthActionabilityReview(reportTruthActionabilityReviewResult.status === 'fulfilled' ? reportTruthActionabilityReviewResult.value : null)
|
||||
setOwnerDryRunPackage(ownerDryRunPackageResult.status === 'fulfilled' ? ownerDryRunPackageResult.value : null)
|
||||
setHostStatefulInventory(hostStatefulInventoryResult.status === 'fulfilled' ? hostStatefulInventoryResult.value : null)
|
||||
@@ -633,6 +638,7 @@ export function AutomationInventoryTab() {
|
||||
reportLiveDeliveryApprovalPackageResult,
|
||||
runtimeReadbackFixtureApprovalResult,
|
||||
runtimeReadbackPromotionGateResult,
|
||||
ownerApprovedFixturePromotionGateResult,
|
||||
reportTruthActionabilityReviewResult,
|
||||
ownerDryRunPackageResult,
|
||||
hostStatefulInventoryResult,
|
||||
@@ -1875,7 +1881,7 @@ export function AutomationInventoryTab() {
|
||||
)
|
||||
}
|
||||
|
||||
if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) {
|
||||
if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !proactiveOperations || !interactionLearningProof || !liveReadModelGate || !redisDryRunGate || !learningWritebackPackage || !telegramReceiptPackage || !ownerApprovedLearningDryRun || !runtimeWriteGateReview || !postWriteVerifierPackage || !runtimeVerifierEvidenceReview || !reportAutomationReview || !reportStatusBoard || !reportRuntimeReadiness || !reportRuntimeDryRun || !reportRuntimeFixtureReadback || !runtimeWorkerShadowGate || !operationPermissionModel || !candidateOperationDryRunEvidence || !taskResultAuditTrail || !matchedPlaybookLearningGap || !criticReviewerResultCapture || !ownerApprovedResultCaptureDryRun || !ownerApprovedResultCaptureReadback || !runtimeReadbackApprovalPackage || !runtimeReadbackImplementationReview || !reportLiveDeliveryApprovalPackage || !runtimeReadbackFixtureApproval || !runtimeReadbackPromotionGate || !ownerApprovedFixturePromotionGate || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) {
|
||||
return (
|
||||
<div style={{ padding: 20 }}>
|
||||
<GlassCard variant="subtle" padding="lg">
|
||||
@@ -2357,6 +2363,57 @@ export function AutomationInventoryTab() {
|
||||
+ runtimeReadbackPromotionGate.rollups.playbook_trust_write_count
|
||||
+ runtimeReadbackPromotionGate.rollups.production_write_count
|
||||
)
|
||||
const ownerPromotionOverall = ownerApprovedFixturePromotionGate.program_status.overall_completion_percent
|
||||
const ownerPromotionPackets = ownerApprovedFixturePromotionGate.rollups.owner_approval_packet_count
|
||||
const ownerPromotionTemplates = ownerApprovedFixturePromotionGate.rollups.acceptance_record_template_count
|
||||
const ownerPromotionReviews = ownerApprovedFixturePromotionGate.rollups.fixture_promotion_review_count
|
||||
const ownerPromotionVerifiers = ownerApprovedFixturePromotionGate.rollups.no_write_verifier_plan_count
|
||||
const ownerPromotionBlockers = ownerApprovedFixturePromotionGate.rollups.blocked_promotion_count
|
||||
const ownerPromotionActions = ownerApprovedFixturePromotionGate.rollups.operator_action_count
|
||||
const ownerPromotionApprovalRequired = (
|
||||
ownerApprovedFixturePromotionGate.rollups.approval_required_packet_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.approval_required_template_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.approval_required_review_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.approval_required_verifier_count
|
||||
)
|
||||
const ownerPromotionBlocked = (
|
||||
ownerApprovedFixturePromotionGate.rollups.blocked_packet_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.blocked_template_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.blocked_review_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.blocked_verifier_count
|
||||
)
|
||||
const ownerPromotionCritical = ownerApprovedFixturePromotionGate.rollups.critical_blocker_count
|
||||
const ownerPromotionOwnerApprovals = ownerApprovedFixturePromotionGate.rollups.owner_approval_received_count
|
||||
const ownerPromotionAcceptanceWrites = ownerApprovedFixturePromotionGate.rollups.owner_acceptance_record_write_count
|
||||
const ownerPromotionExecutions = ownerApprovedFixturePromotionGate.rollups.promotion_execution_count
|
||||
const ownerPromotionCanonicalReads = ownerApprovedFixturePromotionGate.rollups.canonical_runtime_target_read_count
|
||||
const ownerPromotionLiveQueries = ownerApprovedFixturePromotionGate.rollups.live_query_count
|
||||
const ownerPromotionFailureReceiptSends = ownerApprovedFixturePromotionGate.rollups.failure_receipt_send_count
|
||||
const ownerPromotionReviewerQueueWrites = ownerApprovedFixturePromotionGate.rollups.reviewer_queue_write_count
|
||||
const ownerPromotionGatewayWrites = ownerApprovedFixturePromotionGate.rollups.gateway_queue_write_count
|
||||
const ownerPromotionTelegramSends = ownerApprovedFixturePromotionGate.rollups.telegram_send_count
|
||||
const ownerPromotionBotCalls = ownerApprovedFixturePromotionGate.rollups.bot_api_call_count
|
||||
const ownerPromotionReceiptWrites = ownerApprovedFixturePromotionGate.rollups.report_receipt_write_count
|
||||
const ownerPromotionResultWrites = ownerApprovedFixturePromotionGate.rollups.result_capture_write_count
|
||||
const ownerPromotionLearningWrites = ownerApprovedFixturePromotionGate.rollups.learning_write_count
|
||||
const ownerPromotionTrustWrites = ownerApprovedFixturePromotionGate.rollups.playbook_trust_write_count
|
||||
const ownerPromotionProductionWrites = ownerApprovedFixturePromotionGate.rollups.production_write_count
|
||||
const ownerPromotionLiveWrites = (
|
||||
ownerApprovedFixturePromotionGate.rollups.owner_acceptance_record_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.promotion_execution_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.canonical_runtime_target_read_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.live_query_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.failure_receipt_send_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.reviewer_queue_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.gateway_queue_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.telegram_send_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.bot_api_call_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.report_receipt_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.result_capture_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.learning_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.playbook_trust_write_count
|
||||
+ ownerApprovedFixturePromotionGate.rollups.production_write_count
|
||||
)
|
||||
const reportTruthOverall = reportTruthActionabilityReview.program_status.overall_completion_percent
|
||||
const reportTruthFindings = reportTruthActionabilityReview.rollups.zero_signal_finding_count
|
||||
const reportTruthCritical = reportTruthActionabilityReview.rollups.critical_finding_count
|
||||
@@ -6059,6 +6116,211 @@ export function AutomationInventoryTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 12, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#f8fff9', display: 'flex', flexDirection: 'column', gap: 12, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 7, minWidth: 0 }}>
|
||||
<ShieldCheck size={14} style={{ color: '#178a54' }} />
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413' }}>
|
||||
{t('ownerApprovedFixturePromotionGate.title')}
|
||||
</span>
|
||||
</div>
|
||||
<Chip
|
||||
value={t('ownerApprovedFixturePromotionGate.source', {
|
||||
generated: formatDateTime(ownerApprovedFixturePromotionGate.generated_at),
|
||||
current: ownerApprovedFixturePromotionGate.program_status.current_task_id,
|
||||
next: ownerApprovedFixturePromotionGate.program_status.next_task_id,
|
||||
})}
|
||||
muted
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(128px, 1fr))', gap: 10 }} className="automation-inventory-live-read-kpi-grid">
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.overall')} value={`${ownerPromotionOverall}%`} tone="ok" icon={<Gauge size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.packets')} value={ownerPromotionPackets} tone="warn" icon={<FileText size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.templates')} value={ownerPromotionTemplates} tone="warn" icon={<Archive size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.reviews')} value={ownerPromotionReviews} tone="warn" icon={<ShieldCheck size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.verifiers')} value={ownerPromotionVerifiers} tone="warn" icon={<ShieldCheck size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.blockers')} value={ownerPromotionBlockers} tone="danger" icon={<AlertTriangle size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.actions')} value={ownerPromotionActions} tone="warn" icon={<Target size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.approvalRequired')} value={ownerPromotionApprovalRequired} tone="warn" icon={<Lock size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.blocked')} value={ownerPromotionBlocked} tone="danger" icon={<AlertTriangle size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.critical')} value={ownerPromotionCritical} tone="danger" icon={<AlertTriangle size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.ownerApprovals')} value={ownerPromotionOwnerApprovals} tone="warn" icon={<ShieldCheck size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.acceptanceWrites')} value={ownerPromotionAcceptanceWrites} tone={ownerPromotionAcceptanceWrites === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.executions')} value={ownerPromotionExecutions} tone={ownerPromotionExecutions === 0 ? 'ok' : 'danger'} icon={<Gauge size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.canonicalReads')} value={ownerPromotionCanonicalReads} tone={ownerPromotionCanonicalReads === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.liveQueries')} value={ownerPromotionLiveQueries} tone={ownerPromotionLiveQueries === 0 ? 'ok' : 'danger'} icon={<Route size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.failureReceiptSends')} value={ownerPromotionFailureReceiptSends} tone={ownerPromotionFailureReceiptSends === 0 ? 'ok' : 'danger'} icon={<BellRing size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.reviewerQueueWrites')} value={ownerPromotionReviewerQueueWrites} tone={ownerPromotionReviewerQueueWrites === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.gatewayWrites')} value={ownerPromotionGatewayWrites} tone={ownerPromotionGatewayWrites === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.telegramSends')} value={ownerPromotionTelegramSends} tone={ownerPromotionTelegramSends === 0 ? 'ok' : 'danger'} icon={<BellRing size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.botCalls')} value={ownerPromotionBotCalls} tone={ownerPromotionBotCalls === 0 ? 'ok' : 'danger'} icon={<Route size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.receiptWrites')} value={ownerPromotionReceiptWrites} tone={ownerPromotionReceiptWrites === 0 ? 'ok' : 'danger'} icon={<Archive size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.resultWrites')} value={ownerPromotionResultWrites} tone={ownerPromotionResultWrites === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.learningWrites')} value={ownerPromotionLearningWrites} tone={ownerPromotionLearningWrites === 0 ? 'ok' : 'danger'} icon={<Archive size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.trustWrites')} value={ownerPromotionTrustWrites} tone={ownerPromotionTrustWrites === 0 ? 'ok' : 'danger'} icon={<ShieldCheck size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.productionWrites')} value={ownerPromotionProductionWrites} tone={ownerPromotionProductionWrites === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
<MetricCard label={t('ownerApprovedFixturePromotionGate.metrics.liveWrites')} value={ownerPromotionLiveWrites} tone={ownerPromotionLiveWrites === 0 ? 'ok' : 'danger'} icon={<Database size={16} />} />
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 12 }} className="automation-inventory-live-read-grid">
|
||||
<div style={{ padding: 11, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
|
||||
<SmallLabel>{t('ownerApprovedFixturePromotionGate.priorGateTitle')}</SmallLabel>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#64727a', lineHeight: 1.5, overflowWrap: 'anywhere' }}>
|
||||
{ownerApprovedFixturePromotionGate.prior_promotion_gate.readiness_note}
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={ownerApprovedFixturePromotionGate.prior_promotion_gate.schema_version} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.metrics.packets') + ` ${ownerApprovedFixturePromotionGate.prior_promotion_gate.promotion_lane_count}`} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.metrics.verifiers') + ` ${ownerApprovedFixturePromotionGate.prior_promotion_gate.no_write_verifier_check_count}`} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.metrics.liveQueries') + ` ${ownerApprovedFixturePromotionGate.prior_promotion_gate.live_query_count}`} muted />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 11, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
|
||||
<SmallLabel>{t('ownerApprovedFixturePromotionGate.truthTitle')}</SmallLabel>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#64727a', lineHeight: 1.5, overflowWrap: 'anywhere' }}>
|
||||
{ownerApprovedFixturePromotionGate.owner_gate_truth.truth_note}
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.promotionGateLoaded', { value: String(ownerApprovedFixturePromotionGate.owner_gate_truth.p2_113_promotion_gate_loaded) })} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.packageReady', { value: String(ownerApprovedFixturePromotionGate.owner_gate_truth.owner_promotion_package_ready) })} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.acceptanceReady', { value: String(ownerApprovedFixturePromotionGate.owner_gate_truth.acceptance_record_template_ready) })} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.ownerApproval', { value: String(ownerApprovedFixturePromotionGate.owner_gate_truth.owner_approval_received) })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.telegramSend', { value: String(ownerApprovedFixturePromotionGate.owner_gate_truth.telegram_send_enabled) })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.resultWrite', { value: String(ownerApprovedFixturePromotionGate.owner_gate_truth.result_capture_write_enabled) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 11, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 8, minWidth: 0 }}>
|
||||
<SmallLabel>{t('ownerApprovedFixturePromotionGate.redactionTitle')}</SmallLabel>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#64727a', lineHeight: 1.5, overflowWrap: 'anywhere' }}>
|
||||
{ownerApprovedFixturePromotionGate.display_redaction_contract.frontend_display_policy}
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.redactionRequired', { value: String(ownerApprovedFixturePromotionGate.display_redaction_contract.redaction_required) })} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.promptDisplay', { value: String(ownerApprovedFixturePromotionGate.display_redaction_contract.raw_prompt_display_allowed) })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.secretDisplay', { value: String(ownerApprovedFixturePromotionGate.display_redaction_contract.secret_value_display_allowed) })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.flags.runtimePayloadDisplay', { value: String(ownerApprovedFixturePromotionGate.display_redaction_contract.raw_runtime_payload_display_allowed) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(240px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{ownerApprovedFixturePromotionGate.owner_approval_packets.map(packet => (
|
||||
<div key={packet.packet_id} style={{ padding: 10, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'center', minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{packet.display_name}
|
||||
</span>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.packetStatuses.${packet.status}` as never)} muted={packet.status === 'ready_for_owner_review'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={redisDryRunValueLabel('agents', packet.owner_agent)} muted />
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.riskTiers.${packet.risk_tier}` as never)} muted={packet.risk_tier !== 'critical'} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.ownerFields', { count: packet.required_owner_fields.length })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.allowedFixture', { value: packet.allowed_fixture })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.blockedActions', { count: packet.blocked_runtime_actions.length })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{ownerApprovedFixturePromotionGate.acceptance_record_templates.map(template => (
|
||||
<div key={template.template_id} style={{ padding: 10, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'center', minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{template.display_name}
|
||||
</span>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.templateStatuses.${template.status}` as never)} muted={template.status === 'ready'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.requiredFields', { count: template.required_fields.length })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.accepted', { value: String(template.accepted) })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.recordWrite', { value: String(template.record_write_enabled) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{ownerApprovedFixturePromotionGate.fixture_promotion_reviews.map(review => (
|
||||
<div key={review.review_id} style={{ padding: 10, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'center', minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{review.display_name}
|
||||
</span>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.reviewStatuses.${review.status}` as never)} muted={review.status === 'ready'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={review.source_packet_id} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.reviewOutcome', { value: review.review_outcome })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.runtimeWrite', { value: String(review.runtime_write_enabled) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{ownerApprovedFixturePromotionGate.no_write_verifier_plans.map(plan => (
|
||||
<div key={plan.plan_id} style={{ padding: 10, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'center', minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{plan.display_name}
|
||||
</span>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.verifierStatuses.${plan.status}` as never)} muted={plan.status === 'ready'} />
|
||||
</div>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#64727a', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{plan.failure_if_missing}
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={plan.required_fixture} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.liveVerifier', { value: String(plan.live_verifier_enabled) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{ownerApprovedFixturePromotionGate.blocked_promotions.map(blocker => (
|
||||
<div key={blocker.blocker_id} style={{ padding: 10, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'center', minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{blocker.display_name}
|
||||
</span>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.severities.${blocker.severity}` as never)} muted={blocker.severity !== 'critical'} />
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.blockerStatuses.${blocker.status}` as never)} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.blockedAction', { value: blocker.blocked_action })} muted />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.blockedUntil', { value: blocker.blocked_until })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{ownerApprovedFixturePromotionGate.operator_actions.map(action => (
|
||||
<div key={action.action_id} style={{ padding: 10, border: '0.5px solid #c8d2e3', borderRadius: 7, background: '#fff', display: 'flex', flexDirection: 'column', gap: 7, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 8, alignItems: 'center', minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 12, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{action.display_name}
|
||||
</span>
|
||||
<Chip value={redisDryRunValueLabel('agents', action.owner_agent)} muted />
|
||||
</div>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 10, color: '#64727a', lineHeight: 1.45, overflowWrap: 'anywhere' }}>
|
||||
{action.operator_instruction}
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t(`ownerApprovedFixturePromotionGate.actionTypes.${action.action_type}` as never)} />
|
||||
<Chip value={t('ownerApprovedFixturePromotionGate.labels.runtimePromotionAllowed', { value: String(action.runtime_promotion_allowed) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 12, border: '0.5px solid #d8c6a6', borderRadius: 7, background: '#fffdf7', display: 'flex', flexDirection: 'column', gap: 12, minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, flexWrap: 'wrap' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 7, minWidth: 0 }}>
|
||||
|
||||
Reference in New Issue
Block a user