feat(governance): 新增 TG canary owner review gate
This commit is contained in:
@@ -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 => {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user