feat(governance): 新增 TG canary owner review gate
Some checks failed
Code Review / ai-code-review (push) Successful in 13s
CD Pipeline / tests (push) Successful in 1m46s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-18 09:38:22 +08:00
parent 52272a942d
commit efde109760
13 changed files with 2734 additions and 38 deletions

View File

@@ -35,6 +35,7 @@ import {
ShieldCheck,
Target,
Undo2,
UserCheck,
} from 'lucide-react'
import { useTranslations } from 'next-intl'
import { GlassCard } from '@/components/ui/glass-card'
@@ -3725,16 +3726,25 @@ export function AutomationInventoryTab() {
+ professionalTaskExpansion.rollups.canary_delivery_rehearsal_gateway_queue_write_enabled_count
+ professionalTaskExpansion.rollups.canary_delivery_rehearsal_bot_api_call_enabled_count
+ professionalTaskExpansion.rollups.canary_delivery_rehearsal_receipt_write_enabled_count
+ professionalTaskExpansion.rollups.canary_live_delivery_gateway_queue_write_enabled_count
+ professionalTaskExpansion.rollups.canary_live_delivery_bot_api_call_enabled_count
+ professionalTaskExpansion.rollups.canary_live_delivery_telegram_send_enabled_count
+ professionalTaskExpansion.rollups.canary_live_delivery_receipt_write_enabled_count
)
const professionalTaskCanarySendPacket = professionalTaskExpansion.telegram_runtime_bridge.canary_send_approval_packet
const professionalTaskCanaryDeliveryGate = professionalTaskExpansion.telegram_runtime_bridge.canary_delivery_gate
const professionalTaskCanaryDeliveryRehearsal = professionalTaskExpansion.telegram_runtime_bridge.canary_delivery_rehearsal
const professionalTaskCanaryLiveOwnerReview = professionalTaskExpansion.telegram_runtime_bridge.canary_live_delivery_owner_review_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
+ professionalTaskExpansion.rollups.canary_live_delivery_owner_review_received_count
+ professionalTaskExpansion.rollups.canary_live_delivery_owner_review_accepted_count
+ professionalTaskExpansion.rollups.canary_live_delivery_approved_count
+ professionalTaskExpansion.rollups.canary_live_delivery_attempt_allowed_count
)
const backlogProgressPercent = backlog.progress_summary.overall_percent
const explicitApprovalItemCount = backlog.item_approval_boundary_rollup.items_requiring_explicit_approval.length
@@ -4473,6 +4483,9 @@ export function AutomationInventoryTab() {
<MetricCard label={t('professionalTaskExpansion.metrics.deliveryRehearsal')} value={professionalTaskExpansion.rollups.canary_delivery_rehearsal_count} tone="ok" icon={<Route size={16} />} />
<MetricCard label={t('professionalTaskExpansion.metrics.rehearsalChecks')} value={`${professionalTaskExpansion.rollups.canary_delivery_rehearsal_completed_check_count}/${professionalTaskExpansion.rollups.canary_delivery_rehearsal_readback_check_count}`} tone="ok" icon={<ClipboardCheck size={16} />} />
<MetricCard label={t('professionalTaskExpansion.metrics.rehearsalStops')} value={professionalTaskExpansion.rollups.canary_delivery_rehearsal_stop_condition_count} tone="danger" icon={<ShieldAlert size={16} />} />
<MetricCard label={t('professionalTaskExpansion.metrics.ownerReviewGate')} value={professionalTaskExpansion.rollups.canary_live_delivery_owner_review_gate_count} tone="warn" icon={<UserCheck size={16} />} />
<MetricCard label={t('professionalTaskExpansion.metrics.ownerFields')} value={professionalTaskExpansion.rollups.canary_live_delivery_owner_review_required_field_count} tone="warn" icon={<FileText size={16} />} />
<MetricCard label={t('professionalTaskExpansion.metrics.ownerAcceptance')} value={professionalTaskExpansion.rollups.canary_live_delivery_owner_review_acceptance_check_count} tone="warn" icon={<ShieldCheck size={16} />} />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 10 }}>
@@ -4693,6 +4706,166 @@ export function AutomationInventoryTab() {
</div>
</div>
<div style={{ padding: 10, border: '0.5px solid #d7c7a1', borderRadius: 7, background: '#fffaf0', minWidth: 0 }}>
<SmallLabel>{t('professionalTaskExpansion.liveOwnerReviewTitle')}</SmallLabel>
<p style={{ margin: '6px 0 8px', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.5, color: '#684b1f', overflowWrap: 'anywhere' }}>
{professionalTaskCanaryLiveOwnerReview.gate_id} · {professionalTaskCanaryLiveOwnerReview.status}
</p>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
<Chip value={t('professionalTaskExpansion.labels.gateReady', { value: String(professionalTaskCanaryLiveOwnerReview.gate_ready) })} />
<Chip value={t('professionalTaskExpansion.labels.ownerReceived', { value: String(professionalTaskCanaryLiveOwnerReview.owner_review_received) })} muted />
<Chip value={t('professionalTaskExpansion.labels.ownerAccepted', { value: String(professionalTaskCanaryLiveOwnerReview.owner_review_accepted) })} muted />
<Chip value={t('professionalTaskExpansion.labels.liveApproved', { value: String(professionalTaskCanaryLiveOwnerReview.live_canary_delivery_approved) })} muted />
<Chip value={t('professionalTaskExpansion.labels.attemptAllowed', { value: String(professionalTaskCanaryLiveOwnerReview.delivery_attempt_allowed) })} muted />
<Chip value={t('professionalTaskExpansion.labels.selectedMessage', { value: professionalTaskCanaryLiveOwnerReview.selected_message_type })} muted />
<Chip value={t('professionalTaskExpansion.labels.targetEnv', { value: professionalTaskCanaryLiveOwnerReview.target_room_env })} muted />
<Chip value={t('professionalTaskExpansion.labels.previewHash', { value: professionalTaskCanaryLiveOwnerReview.sanitized_preview_hash })} muted />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: 8 }} className="automation-inventory-live-read-grid">
<div style={{ padding: 8, borderRadius: 6, background: '#fff', border: '0.5px solid #ead9ae', display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<SmallLabel>{t('professionalTaskExpansion.liveOwnerFieldsTitle')}</SmallLabel>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 6 }}>
{professionalTaskCanaryLiveOwnerReview.required_owner_fields.slice(0, 9).map(field => (
<div key={field.field_id} style={{ padding: 7, borderRadius: 6, background: '#f8f5ed', display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 10.5, fontWeight: 700, color: '#141413', overflowWrap: 'anywhere' }}>
{field.label}
</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
<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>
<div style={{ padding: 8, borderRadius: 6, background: '#fff', border: '0.5px solid #ead9ae', display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<SmallLabel>{t('professionalTaskExpansion.liveOwnerReceiptTitle')}</SmallLabel>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
<Chip value={t('professionalTaskExpansion.labels.owner', { value: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.owner_agent })} muted />
<Chip value={t('professionalTaskExpansion.labels.completedChecks', { done: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.completed_check_count, total: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.required_checks.length })} muted />
<Chip value={t('professionalTaskExpansion.labels.failedChecks', { count: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.failed_check_count })} muted />
<Chip value={t('professionalTaskExpansion.labels.receiptWrite', { value: String(professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.production_receipt_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.liveReadback', { value: String(professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.live_receipt_readback_enabled) })} muted />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(190px, 1fr))', gap: 6 }}>
{professionalTaskCanaryLiveOwnerReview.acceptance_checks.slice(0, 9).map(check => (
<div key={check} style={{ padding: 7, borderRadius: 6, background: '#eef8f4', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.45, color: '#176d8a', overflowWrap: 'anywhere' }}>
{check}
</div>
))}
</div>
</div>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8, marginTop: 8 }}>
{professionalTaskCanaryLiveOwnerReview.rejection_reasons.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.rejectionReason', { value: reason })}
</div>
))}
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
<Chip value={t('professionalTaskExpansion.labels.queueWrites', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.gateway_queue_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.botCalls', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.bot_api_call_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.send', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.telegram_send_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.receiptWrite', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.delivery_receipt_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.nextGate', { value: professionalTaskCanaryLiveOwnerReview.next_gate })} muted />
</div>
</div>
<div style={{ padding: 10, border: '0.5px solid #d7c7a1', borderRadius: 7, background: '#fffdf7', minWidth: 0 }}>
<SmallLabel>{t('professionalTaskExpansion.canaryLiveOwnerReviewTitle')}</SmallLabel>
<p style={{ margin: '6px 0 8px', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.5, color: '#5c5a55', overflowWrap: 'anywhere' }}>
{professionalTaskCanaryLiveOwnerReview.gate_id} · {professionalTaskCanaryLiveOwnerReview.status}
</p>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
<Chip value={t('professionalTaskExpansion.labels.gateReady', { value: String(professionalTaskCanaryLiveOwnerReview.gate_ready) })} />
<Chip value={t('professionalTaskExpansion.labels.canaryApproval', { value: String(professionalTaskCanaryLiveOwnerReview.approval_required) })} muted />
<Chip value={t('professionalTaskExpansion.labels.ownerReviewReceived', { value: String(professionalTaskCanaryLiveOwnerReview.owner_review_received) })} muted />
<Chip value={t('professionalTaskExpansion.labels.ownerReviewAccepted', { value: String(professionalTaskCanaryLiveOwnerReview.owner_review_accepted) })} muted />
<Chip value={t('professionalTaskExpansion.labels.liveDeliveryApproved', { value: String(professionalTaskCanaryLiveOwnerReview.live_canary_delivery_approved) })} muted />
<Chip value={t('professionalTaskExpansion.labels.attemptAllowed', { value: String(professionalTaskCanaryLiveOwnerReview.delivery_attempt_allowed) })} muted />
<Chip value={t('professionalTaskExpansion.labels.selectedMessage', { value: professionalTaskCanaryLiveOwnerReview.selected_message_type })} muted />
<Chip value={t('professionalTaskExpansion.labels.targetRoom', { value: professionalTaskCanaryLiveOwnerReview.target_room_env })} muted />
<Chip value={t('professionalTaskExpansion.labels.valueVisible', { value: String(professionalTaskCanaryLiveOwnerReview.target_room_value_visible) })} muted />
<Chip value={t('professionalTaskExpansion.labels.dedup', { value: professionalTaskCanaryLiveOwnerReview.dedup_key })} muted />
<Chip value={t('professionalTaskExpansion.labels.previewHash', { value: professionalTaskCanaryLiveOwnerReview.sanitized_preview_hash })} muted />
<Chip value={t('professionalTaskExpansion.labels.priorReadback', { done: professionalTaskCanaryLiveOwnerReview.prior_readback_completed_check_count, failed: professionalTaskCanaryLiveOwnerReview.prior_readback_failed_check_count })} muted />
<Chip value={t('professionalTaskExpansion.labels.receiptOwner', { value: professionalTaskCanaryLiveOwnerReview.receipt_readback_owner })} muted />
<Chip value={t('professionalTaskExpansion.labels.reviewerCount', { count: professionalTaskCanaryLiveOwnerReview.reviewers.length })} muted />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8 }}>
{professionalTaskCanaryLiveOwnerReview.required_owner_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 }}>
{professionalTaskCanaryLiveOwnerReview.acceptance_checks.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' }}>
{t('professionalTaskExpansion.labels.acceptanceCheck', { value: check })}
</div>
))}
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 8, marginTop: 8 }}>
{professionalTaskCanaryLiveOwnerReview.rejection_reasons.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.rejectionReason', { value: reason })}
</div>
))}
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) minmax(0, 1fr)', gap: 8, marginTop: 8 }} className="automation-inventory-live-read-grid">
<div style={{ padding: 8, borderRadius: 6, background: '#fff', border: '0.5px solid #e5d7ad', display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<SmallLabel>{t('professionalTaskExpansion.ownerReviewerActionsTitle')}</SmallLabel>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 6 }}>
{professionalTaskCanaryLiveOwnerReview.reviewer_actions.map(action => (
<span key={action} style={{ padding: 7, borderRadius: 6, background: '#f8f5ed', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.45, color: '#5c5a55', overflowWrap: 'anywhere' }}>
{t('professionalTaskExpansion.labels.reviewerAction', { value: action })}
</span>
))}
</div>
</div>
<div style={{ padding: 8, borderRadius: 6, background: '#fff', border: '0.5px solid #e5d7ad', display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<SmallLabel>{t('professionalTaskExpansion.ownerReceiptReadbackTitle')}</SmallLabel>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
<Chip value={t('professionalTaskExpansion.labels.owner', { value: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.owner_agent })} muted />
<Chip value={t('professionalTaskExpansion.labels.completedChecks', { done: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.completed_check_count, total: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.required_checks.length })} />
<Chip value={t('professionalTaskExpansion.labels.failedChecks', { count: professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.failed_check_count })} muted />
<Chip value={t('professionalTaskExpansion.labels.receiptWrite', { value: String(professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.production_receipt_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.liveReadback', { value: String(professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.live_receipt_readback_enabled) })} muted />
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 6 }}>
{professionalTaskCanaryLiveOwnerReview.receipt_readback_plan.required_checks.map(check => (
<span key={check} style={{ padding: 7, borderRadius: 6, background: '#eef8f4', fontFamily: "'DM Mono', monospace", fontSize: 10, lineHeight: 1.45, color: '#176d8a', overflowWrap: 'anywhere' }}>
{check}
</span>
))}
</div>
</div>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 8 }}>
<Chip value={t('professionalTaskExpansion.labels.canarySend', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.live_delivery_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.queueWrites', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.gateway_queue_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.botCalls', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.bot_api_call_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.send', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.telegram_send_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.receiptWrite', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.delivery_receipt_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.productionWrites', { value: String(professionalTaskCanaryLiveOwnerReview.execution_flags.production_write_enabled) })} muted />
<Chip value={t('professionalTaskExpansion.labels.nextGate', { value: professionalTaskCanaryLiveOwnerReview.next_gate })} muted />
</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 => {

View File

@@ -1429,8 +1429,8 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
program_status: {
overall_completion_percent: number
current_priority: 'P0' | 'P1' | 'P2' | 'P3'
current_task_id: 'P2-405E'
next_task_id: 'P2-405F'
current_task_id: 'P2-405F'
next_task_id: 'P2-406B'
read_only_mode: true
runtime_authority: 'professional_task_expansion_and_telegram_bridge_read_only_no_send'
status_note: string
@@ -1693,6 +1693,62 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
}
next_gate: string
}
canary_live_delivery_owner_review_gate: {
gate_id: string
status: string
gate_ready: boolean
approval_required: boolean
owner_review_received: boolean
owner_review_accepted: boolean
live_canary_delivery_approved: boolean
delivery_attempt_allowed: boolean
prior_rehearsal_id: string
prior_rehearsal_status: string
prior_readback_completed_check_count: number
prior_readback_failed_check_count: number
selected_message_type: string
selected_preview_id: string
selected_receipt_expectation_id: string
target_room_alias: string
target_room_env: string
target_room_value_visible: boolean
dedup_key: string
sanitized_preview_hash: string
owner_agent: string
receipt_readback_owner: string
arbiter: string
reviewers: string[]
required_owner_fields: Array<{
field_id: string
label: string
required: boolean
current_value_status: string
value_display_allowed: boolean
}>
acceptance_checks: string[]
rejection_reasons: string[]
reviewer_actions: string[]
receipt_readback_plan: {
owner_agent: string
required_checks: string[]
completed_check_count: number
failed_check_count: number
production_receipt_write_enabled: boolean
live_receipt_readback_enabled: boolean
}
execution_flags: {
live_delivery_enabled: boolean
gateway_queue_write_enabled: boolean
bot_api_call_enabled: boolean
telegram_send_enabled: boolean
delivery_receipt_write_enabled: boolean
production_write_enabled: boolean
secret_read_enabled: boolean
paid_api_enabled: boolean
}
owner_decision_log: unknown[]
next_gate: string
}
no_send_preview_completion_percent: number
canary_approval_package_completion_percent: number
canary_send_approval_packet_ready: boolean
@@ -1705,6 +1761,11 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
canary_delivery_gate_completion_percent: number
canary_delivery_rehearsal_ready: boolean
canary_delivery_rehearsal_completion_percent: number
canary_live_delivery_owner_review_ready: boolean
canary_live_delivery_owner_review_received: boolean
canary_live_delivery_owner_review_accepted: boolean
canary_live_delivery_approved: boolean
canary_live_delivery_owner_review_completion_percent: number
}
professional_task_domains: Array<{
domain_id: string
@@ -1812,6 +1873,20 @@ export interface AiAgentProfessionalTaskExpansionSnapshot {
canary_delivery_rehearsal_gateway_queue_write_enabled_count: number
canary_delivery_rehearsal_bot_api_call_enabled_count: number
canary_delivery_rehearsal_receipt_write_enabled_count: number
canary_live_delivery_owner_review_gate_count: number
canary_live_delivery_owner_review_required_field_count: number
canary_live_delivery_owner_review_acceptance_check_count: number
canary_live_delivery_owner_review_rejection_reason_count: number
canary_live_delivery_owner_review_reviewer_action_count: number
canary_live_delivery_owner_review_receipt_check_count: number
canary_live_delivery_owner_review_received_count: number
canary_live_delivery_owner_review_accepted_count: number
canary_live_delivery_approved_count: number
canary_live_delivery_attempt_allowed_count: number
canary_live_delivery_gateway_queue_write_enabled_count: number
canary_live_delivery_bot_api_call_enabled_count: number
canary_live_delivery_telegram_send_enabled_count: number
canary_live_delivery_receipt_write_enabled_count: number
}
}