apiVersion: 1

groups:
  # -- P0: Perf regression detection (24h rolling window) -----------------
  - orgId: 1
    name: oppi-perf-regression
    folder: Oppi Alerts
    interval: 5m
    rules:
      # 1. Timeline apply p95 > 40ms
      - uid: oppi-timeline-apply-p95
        title: "P0: Timeline apply p95 regression"
        condition: C
        for: 10m
        noDataState: OK
        execErrState: Error
        labels:
          severity: p0
          component: timeline
        annotations:
          summary: "timeline_apply_ms p95 exceeded 40ms (24h window)"
          description: >-
            The 95th percentile of chat.timeline_apply_ms over the last 24 hours
            exceeds 40ms. This indicates a render pipeline regression — each apply
            should complete within a 2-frame budget (33ms). Investigate recent
            commits touching ChatTimelineCollectionView+DataSource.swift or
            DeltaCoalescer.swift.
        data:
          - refId: A
            relativeTimeRange:
              from: 86400
              to: 0
            datasourceUid: oppi-telemetry-sqlite
            model:
              refId: A
              queryType: table
              rawQueryText: >-
                SELECT COALESCE(
                  (SELECT value FROM chat_metric_samples
                   WHERE metric = 'chat.timeline_apply_ms'
                     AND ts_ms BETWEEN $__from AND $__to
                   ORDER BY value
                   LIMIT 1
                   OFFSET (SELECT CAST(COUNT(*) * 0.95 AS INTEGER)
                           FROM chat_metric_samples
                           WHERE metric = 'chat.timeline_apply_ms'
                             AND ts_ms BETWEEN $__from AND $__to)),
                  0) AS value
          - refId: B
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: reduce
              expression: A
              reducer: last
              settings:
                mode: dropNN
          - refId: C
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: gt
                    params:
                      - 40
                  operator:
                    type: and

      # 2. Jank avg > 5%
      - uid: oppi-jank-avg
        title: "P0: Jank percentage regression"
        condition: C
        for: 10m
        noDataState: OK
        execErrState: Error
        labels:
          severity: p0
          component: timeline
        annotations:
          summary: "Average jank_pct exceeded 5% (24h window)"
          description: >-
            The average chat.jank_pct over the last 24 hours exceeds 5%.
            Current target is near 0%. Check the jank breakdown by phase
            on the Release Preflight dashboard. Common causes: main-thread
            work in snapshot apply, heavy cell configuration, layout thrash.
        data:
          - refId: A
            relativeTimeRange:
              from: 86400
              to: 0
            datasourceUid: oppi-telemetry-sqlite
            model:
              refId: A
              queryType: table
              rawQueryText: >-
                SELECT COALESCE(ROUND(AVG(value), 2), 0) AS value
                FROM chat_metric_samples
                WHERE metric = 'chat.jank_pct'
                  AND ts_ms BETWEEN $__from AND $__to
          - refId: B
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: reduce
              expression: A
              reducer: last
              settings:
                mode: dropNN
          - refId: C
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: gt
                    params:
                      - 5
                  operator:
                    type: and

      # 3. Streaming markdown p95 > 16ms (single frame budget)
      - uid: oppi-markdown-streaming-p95
        title: "P0: Streaming markdown p95 regression"
        condition: C
        for: 10m
        noDataState: OK
        execErrState: Error
        labels:
          severity: p0
          component: markdown
        annotations:
          summary: "markdown_streaming_ms p95 exceeded 16ms (24h window)"
          description: >-
            The 95th percentile of chat.markdown_streaming_ms over the last
            24 hours exceeds 16ms (one frame budget). This metric is actively
            iterated — the Mar 26 streaming markdown commit pushed over-budget
            applies from 25% to 41%. Check incremental markdown parser changes.
        data:
          - refId: A
            relativeTimeRange:
              from: 86400
              to: 0
            datasourceUid: oppi-telemetry-sqlite
            model:
              refId: A
              queryType: table
              rawQueryText: >-
                SELECT COALESCE(
                  (SELECT value FROM chat_metric_samples
                   WHERE metric = 'chat.markdown_streaming_ms'
                     AND ts_ms BETWEEN $__from AND $__to
                   ORDER BY value
                   LIMIT 1
                   OFFSET (SELECT CAST(COUNT(*) * 0.95 AS INTEGER)
                           FROM chat_metric_samples
                           WHERE metric = 'chat.markdown_streaming_ms'
                             AND ts_ms BETWEEN $__from AND $__to)),
                  0) AS value
          - refId: B
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: reduce
              expression: A
              reducer: last
              settings:
                mode: dropNN
          - refId: C
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: gt
                    params:
                      - 16
                  operator:
                    type: and

  # -- P1: Operational health (1h rolling window) -------------------------
  - orgId: 1
    name: oppi-operational-health
    folder: Oppi Alerts
    interval: 1m
    rules:
      # 4. Server turn errors > 3/h
      - uid: oppi-turn-errors
        title: "P1: Server turn error burst"
        condition: C
        for: 5m
        noDataState: OK
        execErrState: Error
        labels:
          severity: p1
          component: server
        annotations:
          summary: "More than 3 turn errors in the last hour"
          description: >-
            The server recorded more than 3 turn_error events in the last hour.
            This means agent sessions are failing. Check server logs for the
            error details — common causes: provider API errors, container OOM,
            session timeout.
        data:
          - refId: A
            relativeTimeRange:
              from: 3600
              to: 0
            datasourceUid: oppi-telemetry-sqlite
            model:
              refId: A
              queryType: table
              rawQueryText: >-
                SELECT COUNT(*) AS value
                FROM server_ops_metric_samples
                WHERE metric = 'server.turn_error'
                  AND ts_ms BETWEEN $__from AND $__to
          - refId: B
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: reduce
              expression: A
              reducer: last
              settings:
                mode: dropNN
          - refId: C
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: gt
                    params:
                      - 3
                  operator:
                    type: and

      # 5. WS ping timeouts > 5/h
      - uid: oppi-ws-ping-timeouts
        title: "P1: WebSocket ping timeout burst"
        condition: C
        for: 5m
        noDataState: OK
        execErrState: Error
        labels:
          severity: p1
          component: websocket
        annotations:
          summary: "More than 5 WS ping timeouts in the last hour"
          description: >-
            The server recorded more than 5 ws_ping_timeout events in the
            last hour. This indicates connection reliability issues — clients
            are experiencing disconnects. Check network conditions and server
            resource utilization (CPU/memory on the Server Health dashboard).
        data:
          - refId: A
            relativeTimeRange:
              from: 3600
              to: 0
            datasourceUid: oppi-telemetry-sqlite
            model:
              refId: A
              queryType: table
              rawQueryText: >-
                SELECT COUNT(*) AS value
                FROM server_ops_metric_samples
                WHERE metric = 'server.ws_ping_timeout'
                  AND ts_ms BETWEEN $__from AND $__to
          - refId: B
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: reduce
              expression: A
              reducer: last
              settings:
                mode: dropNN
          - refId: C
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: gt
                    params:
                      - 5
                  operator:
                    type: and

  # -- P2: Cost anomaly (24h vs 7d baseline) ------------------------------
  - orgId: 1
    name: oppi-cost-anomaly
    folder: Oppi Alerts
    interval: 15m
    rules:
      # 6. Token cost > 3x 7-day daily average
      - uid: oppi-cost-spike
        title: "P2: Token cost spike (3x baseline)"
        condition: C
        for: 30m
        noDataState: OK
        execErrState: Error
        labels:
          severity: p2
          component: cost
        annotations:
          summary: "Daily token cost exceeded 3x the 7-day average"
          description: >-
            The total server.turn_cost over the last 24 hours is more than
            3x the 7-day daily average. This could indicate runaway sessions,
            a model configuration change, or an unusually heavy workload.
            Check the Server Health dashboard for token usage breakdown.
        data:
          # Query returns ratio of current 24h cost to 7d daily average.
          # relativeTimeRange covers 8 days so $__from = 8d ago, $__to = now.
          # Baseline = 7 days before the current 24h window.
          # Returns 0 if no baseline exists (avoids false positive on first use).
          - refId: A
            relativeTimeRange:
              from: 691200
              to: 0
            datasourceUid: oppi-telemetry-sqlite
            model:
              refId: A
              queryType: table
              rawQueryText: >-
                SELECT CASE
                  WHEN baseline > 0
                    THEN ROUND(current_cost / baseline, 2)
                  ELSE 0.0
                END AS value
                FROM (
                  SELECT
                    COALESCE(
                      (SELECT SUM(value) FROM server_ops_metric_samples
                       WHERE metric = 'server.turn_cost'
                         AND ts_ms >= ($__to - 86400000)
                         AND ts_ms <= $__to), 0) AS current_cost,
                    COALESCE(
                      (SELECT SUM(value) / 7.0 FROM server_ops_metric_samples
                       WHERE metric = 'server.turn_cost'
                         AND ts_ms >= $__from
                         AND ts_ms < ($__to - 86400000)), 0) AS baseline
                )
          - refId: B
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: reduce
              expression: A
              reducer: last
              settings:
                mode: dropNN
          - refId: C
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: gt
                    params:
                      - 3
                  operator:
                    type: and
