{
  "panels": [
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 0
      },
      "id": 100,
      "title": "Session Overview",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 4,
        "x": 0,
        "y": 1
      },
      "id": 1,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT COUNT(*) as value FROM events;",
          "queryType": "table",
          "rawQueryText": "SELECT COUNT(*) as value FROM events;",
          "rawSql": "SELECT COUNT(*) as value FROM events;",
          "refId": "A"
        }
      ],
      "title": "Total Events",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 4,
        "x": 4,
        "y": 1
      },
      "id": 2,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT COUNT(*) as value FROM events WHERE event_type='task_completed';",
          "queryType": "table",
          "rawQueryText": "SELECT COUNT(*) as value FROM events WHERE event_type='task_completed';",
          "rawSql": "SELECT COUNT(*) as value FROM events WHERE event_type='task_completed';",
          "refId": "A"
        }
      ],
      "title": "Tasks Completed",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 4,
        "x": 8,
        "y": 1
      },
      "id": 3,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT COUNT(*) as value FROM events WHERE event_type='task_auto_merged';",
          "queryType": "table",
          "rawQueryText": "SELECT COUNT(*) as value FROM events WHERE event_type='task_auto_merged';",
          "rawSql": "SELECT COUNT(*) as value FROM events WHERE event_type='task_auto_merged';",
          "refId": "A"
        }
      ],
      "title": "Auto-Merged",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 4,
        "x": 12,
        "y": 1
      },
      "id": 4,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT COALESCE(SUM(discord_events_sent), 0) as value FROM session_summary;",
          "queryType": "table",
          "rawQueryText": "SELECT COALESCE(SUM(discord_events_sent), 0) as value FROM session_summary;",
          "rawSql": "SELECT COALESCE(SUM(discord_events_sent), 0) as value FROM session_summary;",
          "refId": "A"
        }
      ],
      "title": "Discord Events Sent",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "steps": [
              {
                "color": "red",
                "value": null
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 4,
        "x": 16,
        "y": 1
      },
      "id": 5,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT COUNT(*) as value FROM task_metrics tm WHERE tm.completed_at IS NOT NULL AND NOT EXISTS (SELECT 1 FROM events e WHERE e.task_id = tm.task_id AND e.event_type IN ('task_auto_merged', 'task_manual_merged', 'task_reworked') AND e.timestamp >= tm.completed_at);",
          "queryType": "table",
          "rawQueryText": "SELECT COUNT(*) as value FROM task_metrics tm WHERE tm.completed_at IS NOT NULL AND NOT EXISTS (SELECT 1 FROM events e WHERE e.task_id = tm.task_id AND e.event_type IN ('task_auto_merged', 'task_manual_merged', 'task_reworked') AND e.timestamp >= tm.completed_at);",
          "rawSql": "SELECT COUNT(*) as value FROM task_metrics tm WHERE tm.completed_at IS NOT NULL AND NOT EXISTS (SELECT 1 FROM events e WHERE e.task_id = tm.task_id AND e.event_type IN ('task_auto_merged', 'task_manual_merged', 'task_reworked') AND e.timestamp >= tm.completed_at);",
          "refId": "A"
        }
      ],
      "title": "Merge Queue Depth",
      "type": "stat"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "thresholds": {
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 4,
        "x": 20,
        "y": 1
      },
      "id": 6,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT ROUND(MAX(json_extract(payload, '$.uptime_secs')) / 3600.0, 1) as value FROM events WHERE event_type='daemon_heartbeat';",
          "queryType": "table",
          "rawQueryText": "SELECT ROUND(MAX(json_extract(payload, '$.uptime_secs')) / 3600.0, 1) as value FROM events WHERE event_type='daemon_heartbeat';",
          "rawSql": "SELECT ROUND(MAX(json_extract(payload, '$.uptime_secs')) / 3600.0, 1) as value FROM events WHERE event_type='daemon_heartbeat';",
          "refId": "A"
        }
      ],
      "title": "Uptime (hrs)",
      "type": "stat"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 5
      },
      "id": 101,
      "title": "Pipeline Health",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "max": 100,
          "min": 0,
          "thresholds": {
            "steps": [
              {
                "color": "red",
                "value": null
              },
              {
                "color": "yellow",
                "value": 50
              },
              {
                "color": "green",
                "value": 80
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 6,
        "x": 0,
        "y": 6
      },
      "id": 7,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT ROUND(1.0 * SUM(notification_latency_total_secs) / NULLIF(SUM(notification_latency_samples), 0), 1) as value FROM session_summary;",
          "queryType": "table",
          "rawQueryText": "SELECT ROUND(1.0 * SUM(notification_latency_total_secs) / NULLIF(SUM(notification_latency_samples), 0), 1) as value FROM session_summary;",
          "rawSql": "SELECT ROUND(1.0 * SUM(notification_latency_total_secs) / NULLIF(SUM(notification_latency_samples), 0), 1) as value FROM session_summary;",
          "refId": "A"
        }
      ],
      "title": "Notification Delivery Latency",
      "type": "gauge"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "max": 100,
          "min": 0,
          "thresholds": {
            "steps": [
              {
                "color": "red",
                "value": null
              },
              {
                "color": "yellow",
                "value": 50
              },
              {
                "color": "green",
                "value": 80
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 6,
        "x": 6,
        "y": 6
      },
      "id": 8,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT ROUND(100.0 * CAST((SELECT COUNT(*) FROM events WHERE event_type='task_auto_merged') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='task_completed')), 1) as value;",
          "queryType": "table",
          "rawQueryText": "SELECT ROUND(100.0 * CAST((SELECT COUNT(*) FROM events WHERE event_type='task_auto_merged') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='task_completed')), 1) as value;",
          "rawSql": "SELECT ROUND(100.0 * CAST((SELECT COUNT(*) FROM events WHERE event_type='task_auto_merged') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='task_completed')), 1) as value;",
          "refId": "A"
        }
      ],
      "title": "Auto-Merge Rate",
      "type": "gauge"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "max": 100,
          "min": 0,
          "thresholds": {
            "steps": [
              {
                "color": "red",
                "value": null
              },
              {
                "color": "yellow",
                "value": 50
              },
              {
                "color": "green",
                "value": 80
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 6,
        "x": 12,
        "y": 6
      },
      "id": 9,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT ROUND(100.0 * CAST((SELECT COUNT(*) FROM events WHERE event_type='task_completed') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='task_assigned')), 1) as value;",
          "queryType": "table",
          "rawQueryText": "SELECT ROUND(100.0 * CAST((SELECT COUNT(*) FROM events WHERE event_type='task_completed') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='task_assigned')), 1) as value;",
          "rawSql": "SELECT ROUND(100.0 * CAST((SELECT COUNT(*) FROM events WHERE event_type='task_completed') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='task_assigned')), 1) as value;",
          "refId": "A"
        }
      ],
      "title": "Completion Rate",
      "type": "gauge"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "max": 100,
          "min": 0,
          "thresholds": {
            "steps": [
              {
                "color": "red",
                "value": null
              },
              {
                "color": "yellow",
                "value": 50
              },
              {
                "color": "green",
                "value": 80
              }
            ]
          }
        }
      },
      "gridPos": {
        "h": 4,
        "w": 6,
        "x": 18,
        "y": 6
      },
      "id": 10,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT ROUND(100.0 * (1.0 - CAST((SELECT COUNT(*) FROM events WHERE event_type='member_crashed') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='agent_spawned'))), 1) as value;",
          "queryType": "table",
          "rawQueryText": "SELECT ROUND(100.0 * (1.0 - CAST((SELECT COUNT(*) FROM events WHERE event_type='member_crashed') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='agent_spawned'))), 1) as value;",
          "rawSql": "SELECT ROUND(100.0 * (1.0 - CAST((SELECT COUNT(*) FROM events WHERE event_type='member_crashed') AS REAL) / MAX(1, (SELECT COUNT(*) FROM events WHERE event_type='agent_spawned'))), 1) as value;",
          "refId": "A"
        }
      ],
      "title": "Agent Survival",
      "type": "gauge"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 10
      },
      "id": 102,
      "title": "Activity Over Time",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 11
      },
      "id": 11,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as events FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as events FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as events FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Events Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 11
      },
      "id": 12,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as completions FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_completed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as completions FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_completed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as completions FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_completed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        },
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as crashes FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='member_crashed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as crashes FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='member_crashed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as crashes FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='member_crashed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "B",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Completions & Crashes Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 19
      },
      "id": 13,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as messages FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='message_routed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as messages FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='message_routed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as messages FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='message_routed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Messages Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 19
      },
      "id": 14,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as assigned FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_assigned' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as assigned FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_assigned' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as assigned FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_assigned' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        },
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as merged FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_auto_merged' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as merged FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_auto_merged' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as merged FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_auto_merged' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "B",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Assignments & Merges Per Hour",
      "type": "timeseries"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 27
      },
      "id": 103,
      "title": "Agent Performance",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 28
      },
      "id": 15,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT role, completions, failures, restarts, idle_polls, working_polls FROM agent_metrics ORDER BY completions DESC;",
          "queryType": "table",
          "rawQueryText": "SELECT role, completions, failures, restarts, idle_polls, working_polls FROM agent_metrics ORDER BY completions DESC;",
          "rawSql": "SELECT role, completions, failures, restarts, idle_polls, working_polls FROM agent_metrics ORDER BY completions DESC;",
          "refId": "A"
        }
      ],
      "title": "Agent Metrics",
      "type": "table"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 28
      },
      "id": 16,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT json_extract(payload, '$.from') || ' -> ' || json_extract(payload, '$.to') as route, COUNT(*) as count FROM events WHERE event_type='message_routed' GROUP BY route ORDER BY count DESC LIMIT 10;",
          "queryType": "table",
          "rawQueryText": "SELECT json_extract(payload, '$.from') || ' -> ' || json_extract(payload, '$.to') as route, COUNT(*) as count FROM events WHERE event_type='message_routed' GROUP BY route ORDER BY count DESC LIMIT 10;",
          "rawSql": "SELECT json_extract(payload, '$.from') || ' -> ' || json_extract(payload, '$.to') as route, COUNT(*) as count FROM events WHERE event_type='message_routed' GROUP BY route ORDER BY count DESC LIMIT 10;",
          "refId": "A"
        }
      ],
      "title": "Top Message Routes",
      "type": "barchart"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 36
      },
      "id": 104,
      "title": "Event Breakdown",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 8,
        "x": 0,
        "y": 37
      },
      "id": 17,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type ORDER BY count DESC;",
          "queryType": "table",
          "rawQueryText": "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type ORDER BY count DESC;",
          "rawSql": "SELECT event_type, COUNT(*) as count FROM events GROUP BY event_type ORDER BY count DESC;",
          "refId": "A"
        }
      ],
      "title": "Event Type Distribution",
      "type": "piechart"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 8,
        "x": 8,
        "y": 37
      },
      "id": 18,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT role as agent, COUNT(*) as tasks FROM events WHERE event_type='task_completed' GROUP BY role ORDER BY tasks DESC;",
          "queryType": "table",
          "rawQueryText": "SELECT role as agent, COUNT(*) as tasks FROM events WHERE event_type='task_completed' GROUP BY role ORDER BY tasks DESC;",
          "rawSql": "SELECT role as agent, COUNT(*) as tasks FROM events WHERE event_type='task_completed' GROUP BY role ORDER BY tasks DESC;",
          "refId": "A"
        }
      ],
      "title": "Completions by Agent",
      "type": "piechart"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 8,
        "x": 16,
        "y": 37
      },
      "id": 19,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT role as agent, COUNT(*) as crashes FROM events WHERE event_type='member_crashed' GROUP BY role ORDER BY crashes DESC;",
          "queryType": "table",
          "rawQueryText": "SELECT role as agent, COUNT(*) as crashes FROM events WHERE event_type='member_crashed' GROUP BY role ORDER BY crashes DESC;",
          "rawSql": "SELECT role as agent, COUNT(*) as crashes FROM events WHERE event_type='member_crashed' GROUP BY role ORDER BY crashes DESC;",
          "refId": "A"
        }
      ],
      "title": "Crashes by Agent",
      "type": "piechart"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 45
      },
      "id": 105,
      "title": "Recent Activity",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 46
      },
      "id": 20,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT datetime(timestamp, 'unixepoch', 'localtime') as time, role, task_id FROM events WHERE event_type='task_completed' ORDER BY timestamp DESC LIMIT 20;",
          "queryType": "table",
          "rawQueryText": "SELECT datetime(timestamp, 'unixepoch', 'localtime') as time, role, task_id FROM events WHERE event_type='task_completed' ORDER BY timestamp DESC LIMIT 20;",
          "rawSql": "SELECT datetime(timestamp, 'unixepoch', 'localtime') as time, role, task_id FROM events WHERE event_type='task_completed' ORDER BY timestamp DESC LIMIT 20;",
          "refId": "A"
        }
      ],
      "title": "Recent Completions",
      "type": "table"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 46
      },
      "id": 21,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT datetime(timestamp, 'unixepoch', 'localtime') as time, role, task_id, ROUND(json_extract(payload, '$.load'), 2) as confidence, json_extract(payload, '$.reason') as reason FROM events WHERE event_type='merge_confidence_scored' ORDER BY timestamp DESC LIMIT 20;",
          "queryType": "table",
          "rawQueryText": "SELECT datetime(timestamp, 'unixepoch', 'localtime') as time, role, task_id, ROUND(json_extract(payload, '$.load'), 2) as confidence, json_extract(payload, '$.reason') as reason FROM events WHERE event_type='merge_confidence_scored' ORDER BY timestamp DESC LIMIT 20;",
          "rawSql": "SELECT datetime(timestamp, 'unixepoch', 'localtime') as time, role, task_id, ROUND(json_extract(payload, '$.load'), 2) as confidence, json_extract(payload, '$.reason') as reason FROM events WHERE event_type='merge_confidence_scored' ORDER BY timestamp DESC LIMIT 20;",
          "refId": "A"
        }
      ],
      "title": "Recent Confidence Scores",
      "type": "table"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 54
      },
      "id": 106,
      "title": "Throughput Over Time",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 15,
            "lineWidth": 2
          },
          "max": 100,
          "min": 0,
          "unit": "percent"
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 55
      },
      "id": 107,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, ROUND(metrics.avg_cycle_time_mins, 1) as cycle_time_minutes, ROUND(metrics.avg_lead_time_mins, 1) as lead_time_minutes FROM hours LEFT JOIN (SELECT (completed_at / 3600) * 3600 as hour_start, AVG(cycle_time_mins) as avg_cycle_time_mins, AVG(lead_time_mins) as avg_lead_time_mins FROM task_cycle_times GROUP BY 1) metrics ON metrics.hour_start = h * 3600 ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, ROUND(metrics.avg_cycle_time_mins, 1) as cycle_time_minutes, ROUND(metrics.avg_lead_time_mins, 1) as lead_time_minutes FROM hours LEFT JOIN (SELECT (completed_at / 3600) * 3600 as hour_start, AVG(cycle_time_mins) as avg_cycle_time_mins, AVG(lead_time_mins) as avg_lead_time_mins FROM task_cycle_times GROUP BY 1) metrics ON metrics.hour_start = h * 3600 ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, ROUND(metrics.avg_cycle_time_mins, 1) as cycle_time_minutes, ROUND(metrics.avg_lead_time_mins, 1) as lead_time_minutes FROM hours LEFT JOIN (SELECT (completed_at / 3600) * 3600 as hour_start, AVG(cycle_time_mins) as avg_cycle_time_mins, AVG(lead_time_mins) as avg_lead_time_mins FROM task_cycle_times GROUP BY 1) metrics ON metrics.hour_start = h * 3600 ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Average Cycle and Lead Time Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 55
      },
      "id": 108,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, COALESCE(counts.completed, 0) as completed FROM hours LEFT JOIN (SELECT (completed_at / 3600) * 3600 as hour_start, COUNT(*) as completed FROM task_cycle_times GROUP BY 1) counts ON counts.hour_start = h * 3600 ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, COALESCE(counts.completed, 0) as completed FROM hours LEFT JOIN (SELECT (completed_at / 3600) * 3600 as hour_start, COUNT(*) as completed FROM task_cycle_times GROUP BY 1) counts ON counts.hour_start = h * 3600 ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, COALESCE(counts.completed, 0) as completed FROM hours LEFT JOIN (SELECT (completed_at / 3600) * 3600 as hour_start, COUNT(*) as completed FROM task_cycle_times GROUP BY 1) counts ON counts.hour_start = h * 3600 ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Tasks Completed Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 20,
            "gradientMode": "scheme",
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 63
      },
      "id": 109,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, (SELECT COUNT(*) FROM task_cycle_times t2 WHERE t2.completed_at <= (h + 1) * 3600) as total_completed FROM hours ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, (SELECT COUNT(*) FROM task_cycle_times t2 WHERE t2.completed_at <= (h + 1) * 3600) as total_completed FROM hours ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(completed_at) / 3600 FROM task_cycle_times), strftime('%s', 'now') / 3600)\n) SELECT h * 3600 as time, (SELECT COUNT(*) FROM task_cycle_times t2 WHERE t2.completed_at <= (h + 1) * 3600) as total_completed FROM hours ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Cumulative Tasks Completed",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "points",
            "lineWidth": 1,
            "pointSize": 5
          },
          "max": 1,
          "min": 0,
          "unit": "percentunit"
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 63
      },
      "id": 110,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT timestamp as time, CAST(json_extract(payload, '$.load') AS REAL) as confidence FROM events WHERE event_type='merge_confidence_scored' ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "SELECT timestamp as time, CAST(json_extract(payload, '$.load') AS REAL) as confidence FROM events WHERE event_type='merge_confidence_scored' ORDER BY time;",
          "rawSql": "SELECT timestamp as time, CAST(json_extract(payload, '$.load') AS REAL) as confidence FROM events WHERE event_type='merge_confidence_scored' ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Merge Confidence Over Time",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 71
      },
      "id": 111,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as spawned FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='agent_spawned' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as spawned FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='agent_spawned' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as spawned FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='agent_spawned' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        },
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as crashed FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='member_crashed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as crashed FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='member_crashed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as crashed FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='member_crashed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "B",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Agent Spawns vs Crashes Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 71
      },
      "id": 112,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as completed FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_completed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as completed FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_completed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT MIN(timestamp) / 3600 FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT MAX(timestamp) / 3600 FROM events)\n) SELECT h * 3600 as time, COALESCE(e.cnt, 0) as completed FROM hours LEFT JOIN (SELECT timestamp / 3600 as hr, COUNT(*) as cnt FROM events WHERE event_type='task_completed' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Messages Per Task (Efficiency)",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          },
          "max": 1,
          "min": 0,
          "unit": "percentunit"
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 79
      },
      "id": 113,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events)\n), narration AS (\n  SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='narration_rejection' GROUP BY hr\n), claims AS (\n  SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type IN ('narration_rejection', 'task_completed') GROUP BY hr\n) SELECT h * 3600 AS time, CASE WHEN COALESCE(claims.cnt, 0) = 0 THEN 0.0 ELSE CAST(COALESCE(narration.cnt, 0) AS REAL) / claims.cnt END AS narration_rejection_rate FROM hours LEFT JOIN narration ON hours.h = narration.hr LEFT JOIN claims ON hours.h = claims.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events)\n), narration AS (\n  SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='narration_rejection' GROUP BY hr\n), claims AS (\n  SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type IN ('narration_rejection', 'task_completed') GROUP BY hr\n) SELECT h * 3600 AS time, CASE WHEN COALESCE(claims.cnt, 0) = 0 THEN 0.0 ELSE CAST(COALESCE(narration.cnt, 0) AS REAL) / claims.cnt END AS narration_rejection_rate FROM hours LEFT JOIN narration ON hours.h = narration.hr LEFT JOIN claims ON hours.h = claims.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events)\n), narration AS (\n  SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='narration_rejection' GROUP BY hr\n), claims AS (\n  SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type IN ('narration_rejection', 'task_completed') GROUP BY hr\n) SELECT h * 3600 AS time, CASE WHEN COALESCE(claims.cnt, 0) = 0 THEN 0.0 ELSE CAST(COALESCE(narration.cnt, 0) AS REAL) / claims.cnt END AS narration_rejection_rate FROM hours LEFT JOIN narration ON hours.h = narration.hr LEFT JOIN claims ON hours.h = claims.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Narration Rejection Rate Per Hour (%)",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          },
          "max": 1,
          "min": 0,
          "unit": "percentunit"
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 79
      },
      "id": 114,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(started_at) / 3600 FROM session_summary), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(started_at) / 3600 FROM session_summary), strftime('%s', 'now') / 3600)\n), summary AS (\n  SELECT (started_at / 3600) * 3600 AS hour_start,\n         SUM(verification_passes) AS passes,\n         SUM(verification_failures) AS failures\n  FROM session_summary\n  GROUP BY 1\n) SELECT h * 3600 AS time,\n         CASE\n           WHEN COALESCE(summary.passes, 0) + COALESCE(summary.failures, 0) = 0 THEN 100.0\n           ELSE ROUND(100.0 * COALESCE(summary.passes, 0) / (COALESCE(summary.passes, 0) + COALESCE(summary.failures, 0)), 1)\n         END AS verification_pass_rate\nFROM hours\nLEFT JOIN summary ON hours.h * 3600 = summary.hour_start\nORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(started_at) / 3600 FROM session_summary), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(started_at) / 3600 FROM session_summary), strftime('%s', 'now') / 3600)\n), summary AS (\n  SELECT (started_at / 3600) * 3600 AS hour_start,\n         SUM(verification_passes) AS passes,\n         SUM(verification_failures) AS failures\n  FROM session_summary\n  GROUP BY 1\n) SELECT h * 3600 AS time,\n         CASE\n           WHEN COALESCE(summary.passes, 0) + COALESCE(summary.failures, 0) = 0 THEN 100.0\n           ELSE ROUND(100.0 * COALESCE(summary.passes, 0) / (COALESCE(summary.passes, 0) + COALESCE(summary.failures, 0)), 1)\n         END AS verification_pass_rate\nFROM hours\nLEFT JOIN summary ON hours.h * 3600 = summary.hour_start\nORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS (\n  SELECT COALESCE((SELECT MIN(started_at) / 3600 FROM session_summary), strftime('%s', 'now') / 3600)\n  UNION ALL\n  SELECT h + 1 FROM hours WHERE h < COALESCE((SELECT MAX(started_at) / 3600 FROM session_summary), strftime('%s', 'now') / 3600)\n), summary AS (\n  SELECT (started_at / 3600) * 3600 AS hour_start,\n         SUM(verification_passes) AS passes,\n         SUM(verification_failures) AS failures\n  FROM session_summary\n  GROUP BY 1\n) SELECT h * 3600 AS time,\n         CASE\n           WHEN COALESCE(summary.passes, 0) + COALESCE(summary.failures, 0) = 0 THEN 100.0\n           ELSE ROUND(100.0 * COALESCE(summary.passes, 0) / (COALESCE(summary.passes, 0) + COALESCE(summary.failures, 0)), 1)\n         END AS verification_pass_rate\nFROM hours\nLEFT JOIN summary ON hours.h * 3600 = summary.hour_start\nORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Verification Pass Rate Over Time",
      "type": "timeseries"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 87
      },
      "id": 115,
      "title": "Tact Engine",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 12,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 88
      },
      "id": 116,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS triggered FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='tact_cycle_triggered' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS triggered FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='tact_cycle_triggered' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS triggered FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='tact_cycle_triggered' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Planning Cycles Triggered Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {}
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 88
      },
      "id": 117,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.restart_count') AS INTEGER), 0) AS tasks_created FROM events WHERE event_type='tact_tasks_created' AND json_extract(payload, '$.reason')='success' ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.restart_count') AS INTEGER), 0) AS tasks_created FROM events WHERE event_type='tact_tasks_created' AND json_extract(payload, '$.reason')='success' ORDER BY time;",
          "rawSql": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.restart_count') AS INTEGER), 0) AS tasks_created FROM events WHERE event_type='tact_tasks_created' AND json_extract(payload, '$.reason')='success' ORDER BY time;",
          "refId": "A"
        }
      ],
      "title": "Tasks Created Per Planning Cycle",
      "type": "barchart"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 10,
            "lineWidth": 2
          },
          "unit": "s"
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 96
      },
      "id": 118,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.uptime_secs') AS INTEGER), 0) AS latency_secs FROM events WHERE event_type='tact_tasks_created' ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.uptime_secs') AS INTEGER), 0) AS latency_secs FROM events WHERE event_type='tact_tasks_created' ORDER BY time;",
          "rawSql": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.uptime_secs') AS INTEGER), 0) AS latency_secs FROM events WHERE event_type='tact_tasks_created' ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Planning Cycle Latency",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {}
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 96
      },
      "id": 119,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT CASE COALESCE(json_extract(payload, '$.reason'), 'unknown') WHEN 'success' THEN 'success' WHEN 'failure' THEN 'failure' ELSE 'unknown' END AS metric, COUNT(*) AS value FROM events WHERE event_type='tact_tasks_created' GROUP BY metric ORDER BY value DESC;",
          "queryType": "table",
          "rawQueryText": "SELECT CASE COALESCE(json_extract(payload, '$.reason'), 'unknown') WHEN 'success' THEN 'success' WHEN 'failure' THEN 'failure' ELSE 'unknown' END AS metric, COUNT(*) AS value FROM events WHERE event_type='tact_tasks_created' GROUP BY metric ORDER BY value DESC;",
          "rawSql": "SELECT CASE COALESCE(json_extract(payload, '$.reason'), 'unknown') WHEN 'success' THEN 'success' WHEN 'failure' THEN 'failure' ELSE 'unknown' END AS metric, COUNT(*) AS value FROM events WHERE event_type='tact_tasks_created' GROUP BY metric ORDER BY value DESC;",
          "refId": "A"
        }
      ],
      "title": "Planning Cycle Success vs Failure",
      "type": "piechart"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 104
      },
      "id": 120,
      "title": "Health Signals",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "fillOpacity": 10,
            "lineWidth": 2,
            "stacking": {
              "mode": "normal",
              "group": "A"
            }
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 105
      },
      "id": 121,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT timestamp AS time, COUNT(*) AS detections, role AS metric FROM events WHERE event_type='narration_loop_detected' GROUP BY timestamp, role ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "SELECT timestamp AS time, COUNT(*) AS detections, role AS metric FROM events WHERE event_type='narration_loop_detected' GROUP BY timestamp, role ORDER BY time;",
          "rawSql": "SELECT timestamp AS time, COUNT(*) AS detections, role AS metric FROM events WHERE event_type='narration_loop_detected' GROUP BY timestamp, role ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Narration Events Detected Per Agent",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 12,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 105
      },
      "id": 122,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS restarts FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='agent_restarted' AND json_extract(payload, '$.reason')='narration' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS restarts FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='agent_restarted' AND json_extract(payload, '$.reason')='narration' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS restarts FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='agent_restarted' AND json_extract(payload, '$.reason')='narration' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Narration-Triggered Restarts Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "unit": "s",
          "min": 0
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 113
      },
      "id": 123,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT COALESCE(ROUND(AVG(n.timestamp - a.timestamp), 1), 0) AS value FROM events n LEFT JOIN events a ON a.role = n.role AND a.task_id = n.task_id AND a.event_type='task_assigned' AND a.timestamp <= n.timestamp WHERE n.event_type='narration_loop_detected';",
          "queryType": "table",
          "rawQueryText": "SELECT COALESCE(ROUND(AVG(n.timestamp - a.timestamp), 1), 0) AS value FROM events n LEFT JOIN events a ON a.role = n.role AND a.task_id = n.task_id AND a.event_type='task_assigned' AND a.timestamp <= n.timestamp WHERE n.event_type='narration_loop_detected';",
          "rawSql": "SELECT COALESCE(ROUND(AVG(n.timestamp - a.timestamp), 1), 0) AS value FROM events n LEFT JOIN events a ON a.role = n.role AND a.task_id = n.task_id AND a.event_type='task_assigned' AND a.timestamp <= n.timestamp WHERE n.event_type='narration_loop_detected';",
          "refId": "A"
        }
      ],
      "title": "Average Narration Duration Before Detection",
      "type": "gauge"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "fillOpacity": 10,
            "lineWidth": 2,
            "stacking": {
              "mode": "normal",
              "group": "B"
            }
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 113
      },
      "id": 124,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT timestamp AS time, COUNT(*) AS warnings, role AS metric FROM events WHERE event_type='context_pressure_warning' GROUP BY timestamp, role ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "SELECT timestamp AS time, COUNT(*) AS warnings, role AS metric FROM events WHERE event_type='context_pressure_warning' GROUP BY timestamp, role ORDER BY time;",
          "rawSql": "SELECT timestamp AS time, COUNT(*) AS warnings, role AS metric FROM events WHERE event_type='context_pressure_warning' GROUP BY timestamp, role ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Context Pressure Warnings Per Agent",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 12,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 121
      },
      "id": 125,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS restarts FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='agent_restarted' AND json_extract(payload, '$.reason')='context_pressure' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS restarts FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='agent_restarted' AND json_extract(payload, '$.reason')='context_pressure' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS restarts FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='agent_restarted' AND json_extract(payload, '$.reason')='context_pressure' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Context-Triggered Restarts Per Hour",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "drawStyle": "line",
            "fillOpacity": 8,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 121
      },
      "id": 126,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.load') AS REAL), 0) AS pressure_score, role AS metric FROM events WHERE event_type='context_pressure_warning' ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.load') AS REAL), 0) AS pressure_score, role AS metric FROM events WHERE event_type='context_pressure_warning' ORDER BY time;",
          "rawSql": "SELECT timestamp AS time, COALESCE(CAST(json_extract(payload, '$.load') AS REAL), 0) AS pressure_score, role AS metric FROM events WHERE event_type='context_pressure_warning' ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Context Pressure Score",
      "type": "timeseries"
    },
    {
      "collapsed": false,
      "gridPos": {
        "h": 1,
        "w": 24,
        "x": 0,
        "y": 129
      },
      "id": 127,
      "title": "Board Health",
      "type": "row"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 14,
            "lineWidth": 2,
            "stacking": {
              "mode": "normal",
              "group": "C"
            }
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 130
      },
      "id": 128,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='task_assigned' AND e2.timestamp <= (h + 1) * 3600) - (SELECT COUNT(*) FROM events e3 WHERE e3.event_type='task_completed' AND e3.timestamp <= (h + 1) * 3600) AS in_progress FROM hours ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='task_assigned' AND e2.timestamp <= (h + 1) * 3600) - (SELECT COUNT(*) FROM events e3 WHERE e3.event_type='task_completed' AND e3.timestamp <= (h + 1) * 3600) AS in_progress FROM hours ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='task_assigned' AND e2.timestamp <= (h + 1) * 3600) - (SELECT COUNT(*) FROM events e3 WHERE e3.event_type='task_completed' AND e3.timestamp <= (h + 1) * 3600) AS in_progress FROM hours ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        },
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='task_completed' AND e2.timestamp <= (h + 1) * 3600) - (SELECT COUNT(*) FROM events e3 WHERE e3.event_type='board_task_archived' AND e3.timestamp <= (h + 1) * 3600) AS done FROM hours ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='task_completed' AND e2.timestamp <= (h + 1) * 3600) - (SELECT COUNT(*) FROM events e3 WHERE e3.event_type='board_task_archived' AND e3.timestamp <= (h + 1) * 3600) AS done FROM hours ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='task_completed' AND e2.timestamp <= (h + 1) * 3600) - (SELECT COUNT(*) FROM events e3 WHERE e3.event_type='board_task_archived' AND e3.timestamp <= (h + 1) * 3600) AS done FROM hours ORDER BY time;",
          "refId": "B",
          "timeColumns": [
            "time"
          ]
        },
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='board_task_archived' AND e2.timestamp <= (h + 1) * 3600) AS archived FROM hours ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='board_task_archived' AND e2.timestamp <= (h + 1) * 3600) AS archived FROM hours ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, (SELECT COUNT(*) FROM events e2 WHERE e2.event_type='board_task_archived' AND e2.timestamp <= (h + 1) * 3600) AS archived FROM hours ORDER BY time;",
          "refId": "C",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Board Task Count by Status Over Time",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "unit": "s"
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 12,
        "y": 130
      },
      "id": 129,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH stage_metrics AS ( SELECT 'in_progress' AS stage, AVG(completed_at - started_at) AS avg_secs FROM task_metrics WHERE started_at IS NOT NULL AND completed_at IS NOT NULL UNION ALL SELECT 'done' AS stage, AVG(a.timestamp - tm.completed_at) AS avg_secs FROM task_metrics tm JOIN events a ON a.task_id = tm.task_id AND a.event_type='board_task_archived' WHERE tm.completed_at IS NOT NULL ) SELECT stage, ROUND(COALESCE(avg_secs, 0), 1) AS value FROM stage_metrics;",
          "queryType": "table",
          "rawQueryText": "WITH stage_metrics AS ( SELECT 'in_progress' AS stage, AVG(completed_at - started_at) AS avg_secs FROM task_metrics WHERE started_at IS NOT NULL AND completed_at IS NOT NULL UNION ALL SELECT 'done' AS stage, AVG(a.timestamp - tm.completed_at) AS avg_secs FROM task_metrics tm JOIN events a ON a.task_id = tm.task_id AND a.event_type='board_task_archived' WHERE tm.completed_at IS NOT NULL ) SELECT stage, ROUND(COALESCE(avg_secs, 0), 1) AS value FROM stage_metrics;",
          "rawSql": "WITH stage_metrics AS ( SELECT 'in_progress' AS stage, AVG(completed_at - started_at) AS avg_secs FROM task_metrics WHERE started_at IS NOT NULL AND completed_at IS NOT NULL UNION ALL SELECT 'done' AS stage, AVG(a.timestamp - tm.completed_at) AS avg_secs FROM task_metrics tm JOIN events a ON a.task_id = tm.task_id AND a.event_type='board_task_archived' WHERE tm.completed_at IS NOT NULL ) SELECT stage, ROUND(COALESCE(avg_secs, 0), 1) AS value FROM stage_metrics;",
          "refId": "A"
        }
      ],
      "title": "Average Time in Status by Lifecycle Stage",
      "type": "barchart"
    },
    {
      "datasource": {
        "type": "frser-sqlite-datasource",
        "uid": "batty-telemetry"
      },
      "fieldConfig": {
        "defaults": {
          "custom": {
            "fillOpacity": 12,
            "lineWidth": 2
          }
        }
      },
      "gridPos": {
        "h": 8,
        "w": 12,
        "x": 0,
        "y": 138
      },
      "id": 130,
      "targets": [
        {
          "datasource": {
            "type": "frser-sqlite-datasource",
            "uid": "batty-telemetry"
          },
          "queryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS archived FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='board_task_archived' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "queryType": "table",
          "rawQueryText": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS archived FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='board_task_archived' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "rawSql": "WITH RECURSIVE hours(h) AS ( SELECT COALESCE(MIN(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events UNION ALL SELECT h + 1 FROM hours WHERE h < (SELECT COALESCE(MAX(timestamp) / 3600, strftime('%s', 'now') / 3600) FROM events) ) SELECT h * 3600 AS time, COALESCE(e.cnt, 0) AS archived FROM hours LEFT JOIN (SELECT timestamp / 3600 AS hr, COUNT(*) AS cnt FROM events WHERE event_type='board_task_archived' GROUP BY hr) e ON hours.h = e.hr ORDER BY time;",
          "refId": "A",
          "timeColumns": [
            "time"
          ]
        }
      ],
      "title": "Tasks Archived Per Hour",
      "type": "timeseries"
    }
  ],
  "refresh": "30s",
  "schemaVersion": 39,
  "time": {
    "from": "now-24h",
    "to": "now"
  },
  "title": "Batty — Nether Earth",
  "uid": "batty-project"
}
