{{ error }}
Rule deployed to shadow successfully!
{{ shadowDeployError }}
Rule rollout updated successfully!
{{ rolloutDeployError }}
{{ saveSuccessMessage }}
You are viewing Revision {{ revisionNumber }} of this rule (read-only).
Read-only mode. Editing, pause/resume, draft deployment, and rollout controls are hidden for your current permissions.
This rule is paused. It stays saved, but it is excluded from active production evaluation until resumed.
{{ saveError }}
{{ selectedLaneDescription() }}
Validation errors
Field warnings
Detected references
Fields
User lists
Outcomes
A validated AI draft is still only in preview. Use “Use Draft In Main Editor” before saving changes.
Stored outcome hits for this rule over time in the selected window.
{{ performanceError }}
Hits In Window
{{ getPerformanceHitCount() }}
Outcomes Seen
{{ performanceOutcomeDatasets.length }}
Hit counts reflect stored non-null outcomes persisted for this rule.
Reason: {{ testResult.reason }}
Rule Result: {{ testResult.rule_outcome | json }}
{{ testError }}
Compare the current rule logic against your proposed changes using recent event data.
{{ backtestError }}
{{ getBacktestQueueStatus(bt.task_id, bt) === 'pending' ? 'Backtest is queued...' : 'Backtest is running...' }}
{{ getTaskResult(bt.task_id)?.error || 'Backtest failed' }}
{{ getTaskResult(bt.task_id)?.error || 'Backtest cancelled' }}
{{ change.value }}
| Outcome | Current | Proposed | Delta |
|---|---|---|---|
| {{ row.outcome }} | {{ row.storedCount }} ({{ row.storedRate | number:'1.1-1' }}%) | {{ row.proposedCount }} ({{ row.proposedRate | number:'1.1-1' }}%) | 0, 'text-red-600': row.delta < 0, 'text-gray-500': row.delta === 0 }"> {{ row.delta > 0 ? '+' : '' }}{{ row.delta }} |
| Total records evaluated | {{ taskResult.total_records }} | ||
Evaluated {{ taskResult.eligible_records || taskResult.total_records || 0 }} records and skipped {{ taskResult.skipped_records }} older records that were not eligible for the common comparison set.
Total records: {{ taskResult.total_records || 0 }}
Labeled records: {{ taskResult.labeled_records || 0 }}
Coverage: {{ backtestView.labeledShare | number:'1.1-1' }}%
Pairs scored: {{ backtestView.storedQualitySummary?.pair_count || 0 }}
Avg precision: {{ formatQualityMetric(backtestView.storedQualitySummary?.average_precision) }}
Avg recall: {{ formatQualityMetric(backtestView.storedQualitySummary?.average_recall) }}
Avg F1: {{ formatQualityMetric(backtestView.storedQualitySummary?.average_f1) }}
Best pair: {{ backtestView.storedQualitySummary?.best_pair || '—' }}
Pairs scored: {{ backtestView.proposedQualitySummary?.pair_count || 0 }}
Avg precision: {{ formatQualityMetric(backtestView.proposedQualitySummary?.average_precision) }}
Avg recall: {{ formatQualityMetric(backtestView.proposedQualitySummary?.average_recall) }}
Avg F1: {{ formatQualityMetric(backtestView.proposedQualitySummary?.average_f1) }}
Best pair: {{ backtestView.proposedQualitySummary?.best_pair || '—' }}
| Label | Count | Share of labeled |
|---|---|---|
| {{ row.label }} | {{ row.count }} | {{ row.share | number:'1.1-1' }}% |
0" class="border-t border-gray-100 bg-gray-50 px-3 py-2 text-xs text-gray-600"> Showing first {{ getBacktestRenderRowLimit() }} labels; {{ backtestView.hiddenLabelRowCount }} additional label{{ backtestView.hiddenLabelRowCount === 1 ? '' : 's' }} omitted from inline rendering.
Support columns show TP / FP / FN for each outcome→label pair.
| Outcome | Label | Current P | Current R | Current F1 | Current TP / FP / FN | Proposed P | Proposed R | Proposed F1 | Proposed TP / FP / FN |
|---|---|---|---|---|---|---|---|---|---|
| {{ row.outcome }} | {{ row.label }} | {{ formatQualityMetric(row.stored?.precision) }} | {{ formatQualityMetric(row.stored?.recall) }} | {{ formatQualityMetric(row.stored?.f1) }} | {{ row.stored?.true_positive || 0 }} / {{ row.stored?.false_positive || 0 }} / {{ row.stored?.false_negative || 0 }} | {{ formatQualityMetric(row.proposed?.precision) }} | {{ formatQualityMetric(row.proposed?.recall) }} | {{ formatQualityMetric(row.proposed?.f1) }} | {{ row.proposed?.true_positive || 0 }} / {{ row.proposed?.false_positive || 0 }} / {{ row.proposed?.false_negative || 0 }} |
0" class="border-t border-gray-100 bg-gray-50 px-3 py-2 text-xs text-gray-600"> Showing first {{ getBacktestRenderRowLimit() }} outcome-label pairs; {{ backtestView.hiddenQualityRowCount }} additional pair{{ backtestView.hiddenQualityRowCount === 1 ? '' : 's' }} omitted from inline rendering.
No shadow version exists for this rule. The following logic will be deployed to shadow:
A shadow version is already running. The diff below shows what will change in shadow:
{{ editedLogic }}
{{ change.value }}
Serve this candidate version to a stable percentage of live traffic while the current production version remains the control.
Logic is identical to the current production version.