feat(governance): 新增 AI Agent TG canary delivery gate
This commit is contained in:
@@ -3716,12 +3716,20 @@ export function AutomationInventoryTab() {
|
||||
+ professionalTaskExpansion.rollups.canary_bot_api_call_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_receipt_write_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_secret_read_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_live_send_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_gateway_queue_write_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_bot_api_call_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_secret_read_enabled_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_paid_api_enabled_count
|
||||
)
|
||||
const professionalTaskCanarySendPacket = professionalTaskExpansion.telegram_runtime_bridge.canary_send_approval_packet
|
||||
const professionalTaskCanaryDeliveryGate = professionalTaskExpansion.telegram_runtime_bridge.canary_delivery_gate
|
||||
const professionalTaskCanaryApprovalGaps = (
|
||||
professionalTaskExpansion.rollups.canary_approval_granted_count
|
||||
+ professionalTaskExpansion.rollups.canary_selected_message_type_count
|
||||
+ professionalTaskExpansion.rollups.canary_approved_time_window_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_approved_count
|
||||
+ professionalTaskExpansion.rollups.canary_delivery_attempt_allowed_count
|
||||
)
|
||||
const backlogProgressPercent = backlog.progress_summary.overall_percent
|
||||
const explicitApprovalItemCount = backlog.item_approval_boundary_rollup.items_requiring_explicit_approval.length
|
||||
@@ -4152,6 +4160,10 @@ export function AutomationInventoryTab() {
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.canaryFields')} value={professionalTaskExpansion.rollups.canary_operator_approval_field_count} tone="warn" icon={<FileText size={16} />} />
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.stopConditions')} value={professionalTaskExpansion.rollups.canary_stop_condition_count} tone="danger" icon={<ShieldAlert size={16} />} />
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.canaryApprovalGaps')} value={professionalTaskCanaryApprovalGaps} tone={professionalTaskCanaryApprovalGaps === 0 ? 'ok' : 'danger'} icon={<BellOff size={16} />} />
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.deliveryGate')} value={professionalTaskExpansion.rollups.canary_delivery_gate_count} tone="warn" icon={<Route size={16} />} />
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.deliveryFields')} value={professionalTaskExpansion.rollups.canary_delivery_required_field_count} tone="warn" icon={<ClipboardCheck size={16} />} />
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.deliveryPreflight')} value={professionalTaskExpansion.rollups.canary_delivery_preflight_check_count} tone="warn" icon={<ShieldCheck size={16} />} />
|
||||
<MetricCard label={t('professionalTaskExpansion.metrics.deliveryHoldReasons')} value={professionalTaskExpansion.rollups.canary_delivery_hold_reason_count} tone="danger" icon={<Lock size={16} />} />
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 10 }}>
|
||||
@@ -4276,6 +4288,52 @@ export function AutomationInventoryTab() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: 10, border: '0.5px solid #d7c7a1', borderRadius: 7, background: '#fff', minWidth: 0 }}>
|
||||
<SmallLabel>{t('professionalTaskExpansion.canaryDeliveryGateTitle')}</SmallLabel>
|
||||
<p style={{ margin: '6px 0 8px', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.5, color: '#5c5a55', overflowWrap: 'anywhere' }}>
|
||||
{professionalTaskCanaryDeliveryGate.gate_id} · {professionalTaskCanaryDeliveryGate.status}
|
||||
</p>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
|
||||
<Chip value={t('professionalTaskExpansion.labels.gateReady', { value: String(professionalTaskCanaryDeliveryGate.gate_ready) })} />
|
||||
<Chip value={t('professionalTaskExpansion.labels.deliveryApproved', { value: String(professionalTaskCanaryDeliveryGate.delivery_approved) })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.attemptAllowed', { value: String(professionalTaskCanaryDeliveryGate.delivery_attempt_allowed) })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.selectedMessage', { value: professionalTaskCanaryDeliveryGate.selected_message_type })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.timeWindow', { value: professionalTaskCanaryDeliveryGate.proposed_time_window })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.targetVerified', { value: String(professionalTaskCanaryDeliveryGate.target_room_verified) })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.canarySend', { value: String(professionalTaskCanaryDeliveryGate.delivery_attempt_plan.live_delivery_enabled) })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.queueWrites', { value: String(professionalTaskCanaryDeliveryGate.delivery_attempt_plan.gateway_queue_write_enabled) })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.botCalls', { value: String(professionalTaskCanaryDeliveryGate.delivery_attempt_plan.bot_api_call_enabled) })} muted />
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8 }}>
|
||||
{professionalTaskCanaryDeliveryGate.required_delivery_fields.map(field => (
|
||||
<div key={field.field_id} style={{ padding: 8, borderRadius: 6, background: '#f8f5ed', display: 'flex', flexDirection: 'column', gap: 5, minWidth: 0 }}>
|
||||
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 11, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
|
||||
{field.label}
|
||||
</span>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
|
||||
<Chip value={t('professionalTaskExpansion.labels.required', { value: String(field.required) })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.inputStatus', { value: field.current_value_status })} muted />
|
||||
<Chip value={t('professionalTaskExpansion.labels.valueVisible', { value: String(field.value_display_allowed) })} muted />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8, marginTop: 8 }}>
|
||||
{professionalTaskCanaryDeliveryGate.preflight_checks.slice(0, 8).map(check => (
|
||||
<div key={check} style={{ padding: 8, borderRadius: 6, background: '#eef8f4', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.45, color: '#176d8a', overflowWrap: 'anywhere' }}>
|
||||
{check}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8, marginTop: 8 }}>
|
||||
{professionalTaskCanaryDeliveryGate.hold_reasons.slice(0, 7).map(reason => (
|
||||
<div key={reason} style={{ padding: 8, borderRadius: 6, background: '#fff7ed', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.45, color: '#7a4a20', overflowWrap: 'anywhere' }}>
|
||||
{t('professionalTaskExpansion.labels.holdReason', { value: reason })}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SmallLabel>{t('professionalTaskExpansion.tasksTitle')}</SmallLabel>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 10 }} className="automation-inventory-live-read-card-grid">
|
||||
{visibleProfessionalTasks.map(task => {
|
||||
|
||||
@@ -1429,8 +1429,8 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
|
||||
program_status: {
|
||||
overall_completion_percent: number
|
||||
current_priority: 'P0' | 'P1' | 'P2' | 'P3'
|
||||
current_task_id: 'P2-405C'
|
||||
next_task_id: 'P2-405D'
|
||||
current_task_id: 'P2-405D'
|
||||
next_task_id: 'P2-405E'
|
||||
read_only_mode: true
|
||||
runtime_authority: 'professional_task_expansion_and_telegram_bridge_read_only_no_send'
|
||||
status_note: string
|
||||
@@ -1588,12 +1588,73 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
|
||||
}
|
||||
approval_decision_log: unknown[]
|
||||
}
|
||||
canary_delivery_gate: {
|
||||
gate_id: string
|
||||
status: string
|
||||
gate_ready: boolean
|
||||
delivery_approved: boolean
|
||||
delivery_attempt_allowed: boolean
|
||||
selected_message_type: string
|
||||
selected_message_type_source: string
|
||||
target_room_alias: string
|
||||
target_room_env: string
|
||||
target_room_value_visible: boolean
|
||||
target_room_verified: boolean
|
||||
proposed_time_window: string
|
||||
approved_time_window: string
|
||||
owner_agent: string
|
||||
arbiter: string
|
||||
reviewers: string[]
|
||||
required_delivery_fields: Array<{
|
||||
field_id: string
|
||||
label: string
|
||||
required: boolean
|
||||
current_value_status: string
|
||||
value_display_allowed: boolean
|
||||
}>
|
||||
preflight_checks: string[]
|
||||
hold_reasons: string[]
|
||||
delivery_attempt_plan: {
|
||||
max_messages: number
|
||||
dry_run_message_type: string
|
||||
dedup_key_template: string
|
||||
send_mode: string
|
||||
live_delivery_enabled: boolean
|
||||
gateway_queue_write_enabled: boolean
|
||||
bot_api_call_enabled: boolean
|
||||
delivery_receipt_write_enabled: boolean
|
||||
production_write_enabled: boolean
|
||||
secret_read_enabled: boolean
|
||||
paid_api_enabled: boolean
|
||||
}
|
||||
readback_after_approval_plan: {
|
||||
owner_agent: string
|
||||
enabled_before_delivery: boolean
|
||||
production_receipt_write_enabled: boolean
|
||||
required_checks: string[]
|
||||
}
|
||||
rollback_mute_controls: string[]
|
||||
execution_flags: {
|
||||
live_delivery_enabled: boolean
|
||||
gateway_queue_write_enabled: boolean
|
||||
bot_api_call_enabled: boolean
|
||||
delivery_receipt_write_enabled: boolean
|
||||
production_write_enabled: boolean
|
||||
secret_read_enabled: boolean
|
||||
paid_api_enabled: boolean
|
||||
}
|
||||
delivery_decision_log: unknown[]
|
||||
}
|
||||
no_send_preview_completion_percent: number
|
||||
canary_approval_package_completion_percent: number
|
||||
canary_send_approval_packet_ready: boolean
|
||||
canary_send_approval_granted: boolean
|
||||
canary_send_execution_enabled: boolean
|
||||
canary_send_approval_packet_completion_percent: number
|
||||
canary_delivery_gate_ready: boolean
|
||||
canary_delivery_approved: boolean
|
||||
canary_delivery_attempt_allowed: boolean
|
||||
canary_delivery_gate_completion_percent: number
|
||||
}
|
||||
professional_task_domains: Array<{
|
||||
domain_id: string
|
||||
@@ -1630,6 +1691,7 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
|
||||
frontend_display_policy: string
|
||||
message_preview_redaction_checks: string[]
|
||||
canary_packet_redaction_checks: string[]
|
||||
canary_delivery_redaction_checks: string[]
|
||||
}
|
||||
rollups: {
|
||||
professional_task_count: number
|
||||
@@ -1676,6 +1738,19 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
|
||||
canary_bot_api_call_enabled_count: number
|
||||
canary_delivery_receipt_write_enabled_count: number
|
||||
canary_secret_read_enabled_count: number
|
||||
canary_delivery_gate_count: number
|
||||
canary_delivery_required_field_count: number
|
||||
canary_delivery_preflight_check_count: number
|
||||
canary_delivery_hold_reason_count: number
|
||||
canary_delivery_readback_check_count: number
|
||||
canary_delivery_rollback_mute_control_count: number
|
||||
canary_delivery_approved_count: number
|
||||
canary_delivery_attempt_allowed_count: number
|
||||
canary_delivery_live_send_enabled_count: number
|
||||
canary_delivery_gateway_queue_write_enabled_count: number
|
||||
canary_delivery_bot_api_call_enabled_count: number
|
||||
canary_delivery_secret_read_enabled_count: number
|
||||
canary_delivery_paid_api_enabled_count: number
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user