Skip to main content
This document describes the anomaly surveillance methodology implemented in toorow.

1. Simple Z-Score Methodology

For each (project_id, connector, metric, date) tuple, toorow computes a standard z-score:
Where:
  • rolling_mean and rolling_stddev are calculated over a trailing 30-day window (ANOMALY_BASELINE_WINDOW=29, 29 preceding days + current row).
  • Source data is sourced from fact_daily_kpi totals using single-canonical-dimension selection to prevent double-counting.
The exact SQL transformations are implemented in dbt/models/marts/metric_baselines.sql and dbt/models/marts/anomalies_daily.sql.

2. Anti-Double-Count Guard

fact_daily_kpi contains parallel breakdown dimension series (e.g. device_category and country) that independently total the day’s activity. Summing across all breakdown rows directly would produce values 2–5x too large. metric_baselines.sql enforces the canonical_dim pattern to select ONE breakdown dimension per (project, connector, metric) deterministically (MIN(breakdown_dimension)), aggregating exclusively over that dimension’s rows.

3. Thresholds & Severity Levels

An anomaly is flagged whenever |zscore| >= ANOMALY_Z_THRESHOLD (default 3.0):

4. Context Event Citations (AD-9)

Anomalies never assert causality (AD-9 requirement). When context events exist for an anomaly date, they are listed strictly as candidate context. Prohibited causal phrases in generated messages:
  • "caused by", "due to", "because of", "en raison de", "causé par".
Enforced by unit test test_causal_language_absent in server/tests/core/test_anomaly_alerts.py.

5. Environment Variables


Next Steps & Cross-References

Agentic Daily Insights

Learn how AI agents ingest anomaly notifications during morning briefings.

Semantic Layer

Explore the canonical marts providing baseline metric data.

Security & Constraints

Review AD-9 non-black-box provenance invariants.

Self-Hosting Guide

Configure ANOMALY_ALERTS_ENABLED in your .env deployment environment.