feat(ai): 新增 P2-406B receipt owner review
Some checks failed
Code Review / ai-code-review (push) Successful in 16s
CD Pipeline / tests (push) Successful in 1m52s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled
Some checks failed
Code Review / ai-code-review (push) Successful in 16s
CD Pipeline / tests (push) Successful in 1m52s
CD Pipeline / build-and-deploy (push) Has been cancelled
CD Pipeline / post-deploy-checks (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled
This commit is contained in:
@@ -46,6 +46,7 @@ import {
|
||||
apiClient,
|
||||
type AiAgent12AgentWarRoomSnapshot,
|
||||
type AiAgentProfessionalTaskExpansionSnapshot,
|
||||
type AiAgentReceiptReadbackOwnerReviewSnapshot,
|
||||
type AiAgentCandidateOperationDryRunEvidenceSnapshot,
|
||||
type AiAgentCriticReviewerResultCaptureSnapshot,
|
||||
type AiAgentDeploymentLayoutSnapshot,
|
||||
@@ -569,6 +570,7 @@ export function AutomationInventoryTab() {
|
||||
const [deploymentLayout, setDeploymentLayout] = useState<AiAgentDeploymentLayoutSnapshot | null>(null)
|
||||
const [warRoom, setWarRoom] = useState<AiAgent12AgentWarRoomSnapshot | null>(null)
|
||||
const [professionalTaskExpansion, setProfessionalTaskExpansion] = useState<AiAgentProfessionalTaskExpansionSnapshot | null>(null)
|
||||
const [receiptReadbackOwnerReview, setReceiptReadbackOwnerReview] = useState<AiAgentReceiptReadbackOwnerReviewSnapshot | null>(null)
|
||||
const [proactiveOperations, setProactiveOperations] = useState<AiAgentProactiveOperationsContractSnapshot | null>(null)
|
||||
const [interactionLearningProof, setInteractionLearningProof] = useState<AiAgentInteractionLearningProofSnapshot | null>(null)
|
||||
const [liveReadModelGate, setLiveReadModelGate] = useState<AiAgentLiveReadModelGateSnapshot | null>(null)
|
||||
@@ -653,6 +655,7 @@ export function AutomationInventoryTab() {
|
||||
apiClient.getAiAgentDeploymentLayout(),
|
||||
apiClient.getAiAgent12AgentWarRoom(),
|
||||
apiClient.getAiAgentProfessionalTaskExpansion(),
|
||||
apiClient.getAiAgentReceiptReadbackOwnerReview(),
|
||||
apiClient.getAiAgentProactiveOperationsContract(),
|
||||
apiClient.getAiAgentInteractionLearningProof(),
|
||||
apiClient.getAiAgentLiveReadModelGate(),
|
||||
@@ -736,6 +739,7 @@ export function AutomationInventoryTab() {
|
||||
deploymentLayoutResult,
|
||||
warRoomResult,
|
||||
professionalTaskExpansionResult,
|
||||
receiptReadbackOwnerReviewResult,
|
||||
proactiveOperationsResult,
|
||||
interactionLearningProofResult,
|
||||
liveReadModelGateResult,
|
||||
@@ -816,6 +820,7 @@ export function AutomationInventoryTab() {
|
||||
setDeploymentLayout(deploymentLayoutResult.status === 'fulfilled' ? deploymentLayoutResult.value : null)
|
||||
setWarRoom(warRoomResult.status === 'fulfilled' ? warRoomResult.value : null)
|
||||
setProfessionalTaskExpansion(professionalTaskExpansionResult.status === 'fulfilled' ? professionalTaskExpansionResult.value : null)
|
||||
setReceiptReadbackOwnerReview(receiptReadbackOwnerReviewResult.status === 'fulfilled' ? receiptReadbackOwnerReviewResult.value : null)
|
||||
setProactiveOperations(proactiveOperationsResult.status === 'fulfilled' ? proactiveOperationsResult.value : null)
|
||||
setInteractionLearningProof(interactionLearningProofResult.status === 'fulfilled' ? interactionLearningProofResult.value : null)
|
||||
setLiveReadModelGate(liveReadModelGateResult.status === 'fulfilled' ? liveReadModelGateResult.value : null)
|
||||
@@ -894,6 +899,7 @@ export function AutomationInventoryTab() {
|
||||
deploymentLayoutResult,
|
||||
warRoomResult,
|
||||
professionalTaskExpansionResult,
|
||||
receiptReadbackOwnerReviewResult,
|
||||
proactiveOperationsResult,
|
||||
interactionLearningProofResult,
|
||||
liveReadModelGateResult,
|
||||
@@ -2235,6 +2241,19 @@ export function AutomationInventoryTab() {
|
||||
}))
|
||||
}, [visibleServiceHealthTargets])
|
||||
|
||||
const visibleReceiptOwnerReviewGates = useMemo(() => {
|
||||
if (!receiptReadbackOwnerReview) return []
|
||||
const riskPriority = { critical: 0, high: 1, medium: 2, low: 3 } as Record<string, number>
|
||||
return [...receiptReadbackOwnerReview.owner_review_gates]
|
||||
.sort((a, b) => {
|
||||
const leftRisk = riskPriority[a.risk_tier] ?? 4
|
||||
const rightRisk = riskPriority[b.risk_tier] ?? 4
|
||||
if (leftRisk !== rightRisk) return leftRisk - rightRisk
|
||||
return a.gate_id.localeCompare(b.gate_id)
|
||||
})
|
||||
.slice(0, 6)
|
||||
}, [receiptReadbackOwnerReview])
|
||||
|
||||
const visibleSupplyChainDriftCandidates = useMemo(() => {
|
||||
if (!dependencySupplyChainDriftMonitor) return []
|
||||
const severityPriority = { critical: 0, high: 1, medium: 2, low: 3 } as Record<string, number>
|
||||
@@ -2265,7 +2284,7 @@ export function AutomationInventoryTab() {
|
||||
)
|
||||
}
|
||||
|
||||
if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !warRoom || !professionalTaskExpansion || !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 || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !resultCaptureOwnerReleaseApprovalGate || !resultCapturePostReleaseVerifierRollbackGate || !resultCaptureFinalReleaseCandidateReadback || !resultCaptureReleaseAuthorizationHold || !resultCaptureReleaseAuthorizationReadbackGate || !resultCaptureReleaseVerifierPreflightGate || !resultCaptureReleaseVerifierOwnerReviewPacket || !resultCaptureReleaseDecisionHold || !resultCaptureReleaseDecisionReadback || !resultCaptureReleaseDecisionNextHandoff || !resultCaptureReleaseDecisionInputPrep || !resultCaptureReleaseDecisionOwnerResponsePreflight || !resultCaptureReleaseDecisionOwnerResponseReadback || !resultCaptureReleaseDecisionOwnerResponseAcceptanceGate || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !dependencySupplyChainDriftMonitor || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) {
|
||||
if (error || !snapshot || !backlog || !backupTargets || !backupReadiness || !backupPolicy || !offsiteEscrow || !giteaHealth || !observabilityMatrix || !providerRouteMatrix || !deploymentLayout || !warRoom || !professionalTaskExpansion || !receiptReadbackOwnerReview || !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 || !canonicalRuntimeReadbackOwnerAcceptance || !failureReceiptNoSendReplay || !reviewerQueueNoWriteReadback || !resultCaptureNoWriteReadback || !resultCapturePromotionApprovalGate || !ownerApprovedResultCapturePromotionDryRun || !resultCaptureWriteGateReview || !resultCaptureWriterImplementationReview || !resultCaptureWriterDryRunFixture || !resultCaptureWriterDryRunReadback || !resultCaptureOwnerPromotionReview || !resultCaptureOwnerApprovedExecutionRehearsal || !resultCaptureOwnerAcceptanceMaintenanceGate || !resultCaptureOwnerAcceptanceReadbackPreflightHold || !resultCaptureOwnerApprovedPreflightReleasePackage || !resultCaptureOwnerApprovedReleaseReadinessReadback || !resultCaptureOwnerReleaseApprovalGate || !resultCapturePostReleaseVerifierRollbackGate || !resultCaptureFinalReleaseCandidateReadback || !resultCaptureReleaseAuthorizationHold || !resultCaptureReleaseAuthorizationReadbackGate || !resultCaptureReleaseVerifierPreflightGate || !resultCaptureReleaseVerifierOwnerReviewPacket || !resultCaptureReleaseDecisionHold || !resultCaptureReleaseDecisionReadback || !resultCaptureReleaseDecisionNextHandoff || !resultCaptureReleaseDecisionInputPrep || !resultCaptureReleaseDecisionOwnerResponsePreflight || !resultCaptureReleaseDecisionOwnerResponseReadback || !resultCaptureReleaseDecisionOwnerResponseAcceptanceGate || !reportTruthActionabilityReview || !ownerDryRunPackage || !hostStatefulInventory || !dependencySupplyChainDriftMonitor || !serviceHealthGapMatrix || !serviceHealthNotificationPolicy) {
|
||||
return (
|
||||
<div style={{ padding: 20 }}>
|
||||
<GlassCard variant="subtle" padding="lg">
|
||||
@@ -2455,6 +2474,60 @@ export function AutomationInventoryTab() {
|
||||
active: dependencySupplyChainDriftMonitor.monitor_boundaries.production_write_allowed,
|
||||
},
|
||||
]
|
||||
const receiptOwnerReviewOverall = receiptReadbackOwnerReview.program_status.overall_completion_percent
|
||||
const receiptOwnerReviewSources = receiptReadbackOwnerReview.rollups.source_readback_count
|
||||
const receiptOwnerReviewCadences = receiptReadbackOwnerReview.rollups.report_cadence_count
|
||||
const receiptOwnerReviewGates = receiptReadbackOwnerReview.rollups.owner_review_gate_count
|
||||
const receiptOwnerReviewChecks = receiptReadbackOwnerReview.rollups.receipt_readback_check_count
|
||||
const receiptOwnerReviewApprovals = receiptReadbackOwnerReview.rollups.approval_required_count
|
||||
const receiptOwnerReviewBlocked = receiptReadbackOwnerReview.rollups.blocked_runtime_action_count
|
||||
const receiptOwnerReviewLiveWrites = (
|
||||
receiptReadbackOwnerReview.rollups.live_write_count
|
||||
+ receiptReadbackOwnerReview.rollups.telegram_send_count
|
||||
+ receiptReadbackOwnerReview.rollups.gateway_queue_write_count
|
||||
+ receiptReadbackOwnerReview.rollups.bot_api_call_count
|
||||
+ receiptReadbackOwnerReview.rollups.production_write_count
|
||||
+ receiptReadbackOwnerReview.rollups.secret_read_count
|
||||
+ receiptReadbackOwnerReview.rollups.paid_api_call_count
|
||||
+ receiptReadbackOwnerReview.rollups.host_write_count
|
||||
+ receiptReadbackOwnerReview.rollups.kubectl_action_count
|
||||
)
|
||||
const receiptOwnerReviewBoundaryRows = [
|
||||
{
|
||||
key: 'gateway',
|
||||
label: t('receiptOwnerReview.boundaries.gateway'),
|
||||
active: receiptReadbackOwnerReview.activation_boundaries.gateway_queue_write_enabled,
|
||||
},
|
||||
{
|
||||
key: 'telegram',
|
||||
label: t('receiptOwnerReview.boundaries.telegram'),
|
||||
active: receiptReadbackOwnerReview.activation_boundaries.telegram_send_enabled,
|
||||
},
|
||||
{
|
||||
key: 'botApi',
|
||||
label: t('receiptOwnerReview.boundaries.botApi'),
|
||||
active: receiptReadbackOwnerReview.activation_boundaries.bot_api_call_enabled,
|
||||
},
|
||||
{
|
||||
key: 'receipt',
|
||||
label: t('receiptOwnerReview.boundaries.receipt'),
|
||||
active: receiptReadbackOwnerReview.activation_boundaries.receipt_production_write_enabled
|
||||
|| receiptReadbackOwnerReview.activation_boundaries.report_receipt_write_enabled,
|
||||
},
|
||||
{
|
||||
key: 'production',
|
||||
label: t('receiptOwnerReview.boundaries.production'),
|
||||
active: receiptReadbackOwnerReview.activation_boundaries.production_write_enabled,
|
||||
},
|
||||
{
|
||||
key: 'secret',
|
||||
label: t('receiptOwnerReview.boundaries.secret'),
|
||||
active: receiptReadbackOwnerReview.activation_boundaries.secret_read_enabled
|
||||
|| receiptReadbackOwnerReview.activation_boundaries.paid_api_enabled
|
||||
|| receiptReadbackOwnerReview.activation_boundaries.host_write_enabled
|
||||
|| receiptReadbackOwnerReview.activation_boundaries.kubectl_action_enabled,
|
||||
},
|
||||
]
|
||||
const reportRuntimeOverall = reportRuntimeReadiness.program_status.overall_completion_percent
|
||||
const reportRuntimeLanes = reportRuntimeReadiness.rollups.runtime_lane_count
|
||||
const reportRuntimeReady = reportRuntimeReadiness.rollups.ready_contract_count
|
||||
@@ -4439,6 +4512,134 @@ export function AutomationInventoryTab() {
|
||||
</div>
|
||||
</GlassCard>
|
||||
|
||||
<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 #2563eb35',
|
||||
background: 'rgba(37,99,235,0.07)',
|
||||
color: '#2563eb',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexShrink: 0,
|
||||
}}>
|
||||
<MessageSquareText 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('receiptOwnerReview.title')}
|
||||
</span>
|
||||
<span style={{ fontFamily: "'DM Mono', monospace", fontSize: 11, color: '#5c5a55', lineHeight: 1.55, overflowWrap: 'anywhere' }}>
|
||||
{t('receiptOwnerReview.subtitle', {
|
||||
current: receiptReadbackOwnerReview.program_status.current_task_id,
|
||||
next: receiptReadbackOwnerReview.program_status.next_task_id,
|
||||
gates: receiptOwnerReviewGates,
|
||||
blocked: receiptOwnerReviewBlocked,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'flex-end', gap: 6, minWidth: 0 }}>
|
||||
<Chip value={t('receiptOwnerReview.badges.room', { room: receiptReadbackOwnerReview.receipt_readback_plan.canonical_room })} />
|
||||
<Chip value={t('receiptOwnerReview.badges.owner', { owner: receiptReadbackOwnerReview.receipt_readback_plan.receipt_owner })} muted />
|
||||
<Chip value={t('receiptOwnerReview.badges.canary', { value: String(receiptReadbackOwnerReview.receipt_readback_plan.canary_send_approved) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(112px, 1fr))', gap: 10 }} className="automation-inventory-kpi-grid">
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.overall')} value={`${receiptOwnerReviewOverall}%`} tone="ok" icon={<Gauge size={16} />} />
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.sources')} value={receiptOwnerReviewSources} tone="ok" icon={<Database size={16} />} />
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.cadences')} value={receiptOwnerReviewCadences} tone="ok" icon={<CalendarClock size={16} />} />
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.gates')} value={receiptOwnerReviewGates} tone="warn" icon={<UserCheck size={16} />} />
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.checks')} value={receiptOwnerReviewChecks} tone="ok" icon={<ClipboardCheck size={16} />} />
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.approvals')} value={receiptOwnerReviewApprovals} tone="warn" icon={<Lock size={16} />} />
|
||||
<MetricCard label={t('receiptOwnerReview.metrics.liveWrites')} value={receiptOwnerReviewLiveWrites} tone={receiptOwnerReviewLiveWrites === 0 ? 'ok' : 'danger'} icon={<BellOff size={16} />} />
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1.35fr) minmax(260px, 0.65fr)', gap: 12 }} className="automation-inventory-visual-grid">
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 9, minWidth: 0 }}>
|
||||
<SmallLabel>{t('receiptOwnerReview.sections.ownerGates')}</SmallLabel>
|
||||
{visibleReceiptOwnerReviewGates.map(gate => (
|
||||
<div key={gate.gate_id} style={{ padding: 11, border: '0.5px solid #e0ddd4', borderRadius: 7, background: '#fff', minWidth: 0 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, flexWrap: 'wrap' }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 760, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(gate.title)}
|
||||
</span>
|
||||
<Chip value={t(`receiptOwnerReview.riskTiers.${gate.risk_tier}` as never)} muted={gate.risk_tier !== 'critical'} />
|
||||
</div>
|
||||
<div style={{ marginTop: 7, fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.55, color: '#5c5a55', overflowWrap: 'anywhere' }}>
|
||||
{redactPublicText(gate.next_action)}
|
||||
</div>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
|
||||
<Chip value={`${t('receiptOwnerReview.labels.owner')}: ${gate.owner_agent}`} muted />
|
||||
<Chip value={`${t('receiptOwnerReview.labels.requiredFields')}: ${gate.required_owner_fields.length}`} muted />
|
||||
<Chip value={`${t('receiptOwnerReview.labels.acceptance')}: ${gate.acceptance_checks.length}`} muted />
|
||||
<Chip value={`${t('receiptOwnerReview.labels.blockedActions')}: ${gate.blocked_runtime_actions.length}`} muted />
|
||||
<Chip value={`${t('receiptOwnerReview.labels.evidence')}: ${gate.evidence_refs.length}`} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 10, minWidth: 0 }}>
|
||||
<div style={{ padding: 12, border: '0.5px solid #e0ddd4', borderRadius: 7, background: '#faf9f3', minWidth: 0 }}>
|
||||
<SmallLabel>{t('receiptOwnerReview.sections.receiptPlan')}</SmallLabel>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
|
||||
<Chip value={t('receiptOwnerReview.labels.arbiter', { value: receiptReadbackOwnerReview.receipt_readback_plan.arbiter })} muted />
|
||||
<Chip value={t('receiptOwnerReview.labels.receiptOwner', { value: receiptReadbackOwnerReview.receipt_readback_plan.receipt_owner })} muted />
|
||||
<Chip value={t('receiptOwnerReview.labels.replayOwner', { value: receiptReadbackOwnerReview.receipt_readback_plan.replay_owner })} muted />
|
||||
<Chip value={t('receiptOwnerReview.labels.env', { value: receiptReadbackOwnerReview.receipt_readback_plan.canonical_room_env })} muted />
|
||||
</div>
|
||||
<div style={{ marginTop: 9 }}>
|
||||
{receiptReadbackOwnerReview.report_owner_review.cadences.map(cadence => (
|
||||
<GateMatrixRow
|
||||
key={cadence.cadence_id}
|
||||
label={cadence.display_name}
|
||||
value={`${cadence.completion_percent}%`}
|
||||
detail={t('receiptOwnerReview.labels.cadenceDetail', {
|
||||
owner: cadence.owner_agent,
|
||||
state: cadence.delivery_state,
|
||||
confidence: cadence.source_confidence,
|
||||
})}
|
||||
tone={cadence.live_delivery_count === 0 ? 'ok' : 'danger'}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 12, border: '0.5px solid #e0ddd4', borderRadius: 7, background: '#fff', minWidth: 0 }}>
|
||||
<SmallLabel>{t('receiptOwnerReview.sections.boundaries')}</SmallLabel>
|
||||
<div style={{ marginTop: 7 }}>
|
||||
{receiptOwnerReviewBoundaryRows.map(row => (
|
||||
<GateMatrixRow
|
||||
key={row.key}
|
||||
label={row.label}
|
||||
value={String(row.active)}
|
||||
detail={row.active ? t('receiptOwnerReview.labels.boundaryOpen') : t('receiptOwnerReview.labels.boundaryClosed')}
|
||||
tone={row.active ? 'danger' : 'ok'}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t('receiptOwnerReview.source', {
|
||||
generated: formatDateTime(receiptReadbackOwnerReview.generated_at),
|
||||
current: receiptReadbackOwnerReview.program_status.current_task_id,
|
||||
next: receiptReadbackOwnerReview.program_status.next_task_id,
|
||||
})} muted />
|
||||
<Chip value={t('receiptOwnerReview.labels.truthBlockers', { count: receiptReadbackOwnerReview.report_truth_owner_review.zero_signal_finding_count })} muted />
|
||||
<Chip value={t('receiptOwnerReview.labels.driftCandidates', { count: receiptReadbackOwnerReview.drift_monitor_owner_review.drift_candidate_count })} muted />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
|
||||
<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' }}>
|
||||
|
||||
@@ -339,6 +339,11 @@ export const apiClient = {
|
||||
return handleResponse<AiAgentProfessionalTaskExpansionSnapshot>(res)
|
||||
},
|
||||
|
||||
async getAiAgentReceiptReadbackOwnerReview() {
|
||||
const res = await fetch(`${API_BASE_URL}/agents/agent-receipt-readback-owner-review`)
|
||||
return handleResponse<AiAgentReceiptReadbackOwnerReviewSnapshot>(res)
|
||||
},
|
||||
|
||||
async getAiAgentProactiveOperationsContract() {
|
||||
const res = await fetch(`${API_BASE_URL}/agents/agent-proactive-operations-contract`)
|
||||
return handleResponse<AiAgentProactiveOperationsContractSnapshot>(res)
|
||||
@@ -1895,6 +1900,157 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
export interface AiAgentReceiptReadbackOwnerReviewSnapshot {
|
||||
schema_version: 'ai_agent_receipt_readback_owner_review_v1'
|
||||
generated_at: string
|
||||
program_status: {
|
||||
overall_completion_percent: number
|
||||
current_priority: 'P0' | 'P1' | 'P2' | 'P3'
|
||||
current_task_id: 'P2-406B'
|
||||
next_task_id: 'P2-407'
|
||||
read_only_mode: true
|
||||
runtime_authority: 'receipt_readback_owner_review_only_no_send_or_write'
|
||||
status_note: string
|
||||
}
|
||||
source_refs: string[]
|
||||
source_readbacks: Array<{
|
||||
readback_id: string
|
||||
source_schema_version: string
|
||||
source_ref: string
|
||||
endpoint: string
|
||||
owner_agent: 'openclaw' | 'hermes' | 'nemotron'
|
||||
status: string
|
||||
evidence_status: string
|
||||
key_readback: string
|
||||
next_action: string
|
||||
}>
|
||||
rollups: {
|
||||
source_readback_count: number
|
||||
report_cadence_count: number
|
||||
owner_review_gate_count: number
|
||||
receipt_readback_check_count: number
|
||||
drift_candidate_count: number
|
||||
report_truth_blocker_count: number
|
||||
approval_required_count: number
|
||||
blocked_runtime_action_count: number
|
||||
live_write_count: number
|
||||
telegram_send_count: number
|
||||
gateway_queue_write_count: number
|
||||
bot_api_call_count: number
|
||||
production_write_count: number
|
||||
secret_read_count: number
|
||||
paid_api_call_count: number
|
||||
host_write_count: number
|
||||
kubectl_action_count: number
|
||||
}
|
||||
report_owner_review: {
|
||||
cadences: Array<{
|
||||
cadence_id: 'daily' | 'weekly' | 'monthly'
|
||||
display_name: string
|
||||
owner_agent: 'openclaw' | 'hermes' | 'nemotron'
|
||||
completion_percent: number
|
||||
delivery_state: string
|
||||
source_confidence: string
|
||||
live_delivery_count: number
|
||||
review_status: string
|
||||
next_gate: string
|
||||
}>
|
||||
}
|
||||
receipt_readback_plan: {
|
||||
canonical_room: string
|
||||
canonical_room_env: string
|
||||
gateway_owner: string
|
||||
arbiter: 'openclaw'
|
||||
receipt_owner: 'hermes'
|
||||
replay_owner: 'nemotron'
|
||||
dry_run_receipt_only: boolean
|
||||
owner_review_required_before_canary: boolean
|
||||
canary_send_approved: boolean
|
||||
receipt_production_write_enabled: boolean
|
||||
readback_checks: Array<{
|
||||
check_id: string
|
||||
owner_agent: 'openclaw' | 'hermes' | 'nemotron'
|
||||
status: string
|
||||
evidence_refs: string[]
|
||||
blocked_runtime_action: string
|
||||
}>
|
||||
}
|
||||
owner_review_gates: Array<{
|
||||
gate_id: string
|
||||
title: string
|
||||
owner_agent: 'openclaw' | 'hermes' | 'nemotron'
|
||||
risk_tier: 'low' | 'medium' | 'high' | 'critical'
|
||||
status: string
|
||||
approval_required: true
|
||||
required_owner_fields: string[]
|
||||
acceptance_checks: string[]
|
||||
rejection_reasons: string[]
|
||||
blocked_runtime_actions: string[]
|
||||
evidence_refs: string[]
|
||||
next_action: string
|
||||
}>
|
||||
drift_monitor_owner_review: {
|
||||
source_task_id: 'P2-004'
|
||||
drift_candidate_count: number
|
||||
action_required_candidate_count: number
|
||||
stale_source_snapshot_count: number
|
||||
external_lookup_allowed: false
|
||||
package_upgrade_allowed: false
|
||||
owner_actions: string[]
|
||||
}
|
||||
report_truth_owner_review: {
|
||||
source_task_id: 'P2-403J'
|
||||
all_zero_weekly_report_is_actionable_anomaly: true
|
||||
all_zero_weekly_report_confidence: 'low_trust_actionable_anomaly'
|
||||
zero_signal_finding_count: number
|
||||
critical_finding_count: number
|
||||
high_finding_count: number
|
||||
telegram_report_send_allowed: false
|
||||
cronjob_change_allowed: false
|
||||
freshness_gate_implemented: false
|
||||
source_confidence_gate_implemented: false
|
||||
actionability_score_implemented: false
|
||||
owner_actions: string[]
|
||||
}
|
||||
activation_boundaries: Record<string, boolean>
|
||||
telegram_policy: {
|
||||
status: string
|
||||
canonical_room: string
|
||||
canonical_room_env: string
|
||||
gateway_queue_write_allowed: false
|
||||
direct_bot_api_allowed: false
|
||||
telegram_send_allowed: false
|
||||
receipt_write_allowed: false
|
||||
owner_review_required?: boolean
|
||||
canary_message_limit?: number
|
||||
canary_approval_task?: string
|
||||
}
|
||||
agent_roles: Array<{
|
||||
agent_id: 'openclaw' | 'hermes' | 'nemotron'
|
||||
role: string
|
||||
specialty: string
|
||||
autonomy_level: string
|
||||
approval_gate: string
|
||||
runtime_write_allowed: false
|
||||
outputs: string[]
|
||||
}>
|
||||
operator_decision: {
|
||||
status: 'owner_review_required_before_canary'
|
||||
approval_packet_required: true
|
||||
rollback_plan_required: true
|
||||
mute_plan_required: true
|
||||
required_fields: string[]
|
||||
stop_conditions: string[]
|
||||
next_decision_point: string
|
||||
}
|
||||
next_actions: Array<{
|
||||
task_id: string
|
||||
priority: 'P0' | 'P1' | 'P2' | 'P3'
|
||||
summary: string
|
||||
gate: string
|
||||
}>
|
||||
}
|
||||
|
||||
export interface AiAgentProactiveOperationsContractSnapshot {
|
||||
schema_version: 'ai_agent_proactive_operations_contract_v1'
|
||||
generated_at: string
|
||||
|
||||
Reference in New Issue
Block a user