{{ error }}
Rule deployed to shadow successfully!
{{ shadowDeployError }}
Rule rollout updated successfully!
{{ rolloutDeployError }}
Rule saved successfully!
You are viewing Revision {{ revisionNumber }} of this rule (read-only).
{{ saveError }}
Field warnings
Reason: {{ testResult.reason }}
Rule Result: {{ testResult.rule_outcome | json }}
{{ testError }}
Compare the current rule logic against your proposed changes using recent event data.
{{ backtestError }}
Backtest is running...
{{ getTaskResult(bt.task_id)?.error || 'Backtest failed' }}
{{ change.value }}
| Outcome | Current | Proposed | Delta |
|---|---|---|---|
| {{ outcome }} | {{ taskResult.stored_result?.[outcome] || 0 }} ({{ (taskResult.stored_result_rate?.[outcome] || 0) | number:'1.1-1' }}%) | {{ taskResult.proposed_result?.[outcome] || 0 }} ({{ (taskResult.proposed_result_rate?.[outcome] || 0) | number:'1.1-1' }}%) | 0, 'text-red-600': (taskResult.proposed_result?.[outcome] || 0) - (taskResult.stored_result?.[outcome] || 0) < 0, 'text-gray-500': (taskResult.proposed_result?.[outcome] || 0) - (taskResult.stored_result?.[outcome] || 0) === 0 }"> {{ (taskResult.proposed_result?.[outcome] || 0) - (taskResult.stored_result?.[outcome] || 0) > 0 ? '+' : '' }}{{ (taskResult.proposed_result?.[outcome] || 0) - (taskResult.stored_result?.[outcome] || 0) }} |
| 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: {{ getLabeledShare(taskResult) | number:'1.1-1' }}%
Pairs scored: {{ getQualitySummary(taskResult, 'stored')?.pair_count || 0 }}
Avg precision: {{ formatQualityMetric(getQualitySummary(taskResult, 'stored')?.average_precision) }}
Avg recall: {{ formatQualityMetric(getQualitySummary(taskResult, 'stored')?.average_recall) }}
Avg F1: {{ formatQualityMetric(getQualitySummary(taskResult, 'stored')?.average_f1) }}
Best pair: {{ getQualitySummary(taskResult, 'stored')?.best_pair || '—' }}
Pairs scored: {{ getQualitySummary(taskResult, 'proposed')?.pair_count || 0 }}
Avg precision: {{ formatQualityMetric(getQualitySummary(taskResult, 'proposed')?.average_precision) }}
Avg recall: {{ formatQualityMetric(getQualitySummary(taskResult, 'proposed')?.average_recall) }}
Avg F1: {{ formatQualityMetric(getQualitySummary(taskResult, 'proposed')?.average_f1) }}
Best pair: {{ getQualitySummary(taskResult, 'proposed')?.best_pair || '—' }}
| Label | Count | Share of labeled |
|---|---|---|
| {{ label }} | {{ taskResult.label_counts?.[label] || 0 }} | {{ (((taskResult.label_counts?.[label] || 0) * 100) / (taskResult.labeled_records || 1)) | number:'1.1-1' }}% |
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 |
|---|---|---|---|---|---|---|---|---|---|
| {{ pair.outcome }} | {{ pair.label }} | {{ formatQualityMetric(getQualityMetric(taskResult, 'stored', pair.outcome, pair.label)?.precision) }} | {{ formatQualityMetric(getQualityMetric(taskResult, 'stored', pair.outcome, pair.label)?.recall) }} | {{ formatQualityMetric(getQualityMetric(taskResult, 'stored', pair.outcome, pair.label)?.f1) }} | {{ getQualityMetric(taskResult, 'stored', pair.outcome, pair.label)?.true_positive || 0 }} / {{ getQualityMetric(taskResult, 'stored', pair.outcome, pair.label)?.false_positive || 0 }} / {{ getQualityMetric(taskResult, 'stored', pair.outcome, pair.label)?.false_negative || 0 }} | {{ formatQualityMetric(getQualityMetric(taskResult, 'proposed', pair.outcome, pair.label)?.precision) }} | {{ formatQualityMetric(getQualityMetric(taskResult, 'proposed', pair.outcome, pair.label)?.recall) }} | {{ formatQualityMetric(getQualityMetric(taskResult, 'proposed', pair.outcome, pair.label)?.f1) }} | {{ getQualityMetric(taskResult, 'proposed', pair.outcome, pair.label)?.true_positive || 0 }} / {{ getQualityMetric(taskResult, 'proposed', pair.outcome, pair.label)?.false_positive || 0 }} / {{ getQualityMetric(taskResult, 'proposed', pair.outcome, pair.label)?.false_negative || 0 }} |
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.