{
  "$schema_note": "KPI Studio tile-transfer lifecycle fixture. HIPAA-safe: contains NO PHI, only tile/metric/dashboard configuration and query payloads. Bound to the redacted sample CSVs in this folder. Field/measure/dimension IDs match server/studioQuery.ts (CHARGE_COLUMNS / APPOINTMENT_COLUMNS) and StudioQueryRequest. Use this to exercise Creator -> Editor -> tile transfer -> dashboard reload -> export without touching real reports.",
  "generated_for": "KPI Studio Creator / Editor / tile-transfer debugging",
  "hipaa": "redacted fixtures only; do not point these dataSources at the real /assistant-lab/.../reports CSVs during shared debugging",
  "datasets": [
    {
      "id": "charges",
      "dataSource": "charges",
      "label": "Charges (redacted sample)",
      "file": "docs/examples/redacted_charge_report_sample.csv",
      "row_count": 600,
      "measures": ["count", "total_collected", "billed", "balance", "pri_paid_amt", "bal_amt"],
      "dimensions": ["payer_category", "attending_provider", "location", "enc_type", "division", "date_of_service"],
      "filter_fields": ["payer_category", "location", "attending_provider", "enc_type"]
    },
    {
      "id": "appointments",
      "dataSource": "appointments",
      "label": "Appointments (redacted sample)",
      "file": "docs/examples/redacted_appointment_report_sample.csv",
      "row_count": 600,
      "measures": ["count"],
      "dimensions": ["status", "provider_name", "encounter_type", "payer_category", "gender", "appointment_date"],
      "filter_fields": ["status", "provider_name", "encounter_type", "payer_category"]
    }
  ],
  "tiles": [
    {
      "case": "charge-collections-by-payer",
      "description": "Primary tile-transfer happy path: build a collections-by-payer bar in Creator, retitle/refilter in Editor, drop on a dashboard, reload, export.",
      "stage_1_creator_draft": {
        "id": "metric_collections_by_payer",
        "label": "Collections by Payer",
        "dataset": "charges",
        "aggregation": { "kind": "sum", "field": "total_collected" },
        "group_by": ["payer_category"],
        "visualization": "bar",
        "format": "currency",
        "unit": "USD",
        "filters": [],
        "time_bucket": { "field": "date_of_service", "grain": "month", "window": "present" }
      },
      "stage_2_editor_edit": {
        "title_override": "Collections by Payer (YTD)",
        "overrides": {
          "visualization": "bar",
          "limit": 8,
          "filters": [
            { "field": "location", "op": "in", "values": ["Core Medical Center Blue Springs"] }
          ]
        },
        "edit_intent": "rename + scope to one location + cap to top 8 payers"
      },
      "stage_3_dashboard_card": {
        "dashboard_id": "dash_revenue_redacted",
        "tab": "overview",
        "card": { "metric_id": "metric_collections_by_payer", "size": "lg", "title_override": "Collections by Payer (YTD)" }
      },
      "stage_4_query_request": {
        "endpoint": "POST /api/studio/query",
        "body": {
          "dataSource": "charges",
          "measure": "total_collected",
          "summaryFunction": "sum",
          "dimensions": ["payer_category"],
          "xDimension": "payer_category",
          "timePeriod": "ytd",
          "timeGranularity": "month",
          "datasetFilters": { "location": ["Core Medical Center Blue Springs"] },
          "limit": 8
        }
      },
      "expected_signals": {
        "non_empty_series": true,
        "value_kind": "currency",
        "transfer_invariants": [
          "metric_id is identical across creator -> editor -> dashboard card",
          "Editor title_override survives the transfer and appears on the dashboard card",
          "dataset/dataSource binding (charges) is preserved end to end",
          "measure total_collected maps to summed Pri/Sec/Ter/Pat Paid Amt columns"
        ]
      },
      "stage_5_reload_and_export": {
        "reload": "GET /api/studio/dashboards then re-run stage_4 query; series and title must match pre-reload",
        "export": { "format": "csv", "expect_columns": ["payer_category", "total_collected"] }
      }
    },
    {
      "case": "appointment-no-shows-by-provider",
      "description": "Second dataSource (appointments) tile-transfer with a status filter, to catch dataset-bleed bugs where a transferred tile keeps the charges binding.",
      "stage_1_creator_draft": {
        "id": "metric_no_shows_by_provider",
        "label": "No-Shows by Provider",
        "dataset": "appointments",
        "aggregation": { "kind": "count", "field": "count" },
        "group_by": ["provider_name"],
        "visualization": "bar",
        "format": "number",
        "unit": "appointments",
        "filters": [{ "field": "status", "op": "in", "values": ["no show"] }],
        "time_bucket": { "field": "appointment_date", "grain": "month", "window": "present" }
      },
      "stage_2_editor_edit": {
        "title_override": "Monthly No-Show Count",
        "overrides": { "visualization": "line", "seriesDimension": "provider_name" },
        "edit_intent": "switch bar->line and trend no-shows monthly per provider"
      },
      "stage_3_dashboard_card": {
        "dashboard_id": "dash_access_redacted",
        "tab": "access",
        "card": { "metric_id": "metric_no_shows_by_provider", "size": "md", "title_override": "Monthly No-Show Count" }
      },
      "stage_4_query_request": {
        "endpoint": "POST /api/studio/query",
        "body": {
          "dataSource": "appointments",
          "measure": "count",
          "dimensions": ["provider_name"],
          "xDimension": "appointment_date",
          "seriesDimension": "provider_name",
          "timePeriod": "last_12_months",
          "timeGranularity": "month",
          "datasetFilters": { "status": ["no show"] }
        }
      },
      "expected_signals": {
        "non_empty_series": true,
        "value_kind": "count",
        "transfer_invariants": [
          "dataSource stays appointments after the visualization edit (no bleed to charges)",
          "status=no show filter survives Editor -> dashboard transfer",
          "appointment status normalization (no show / cancelled / complete) is applied via canonicalFilterValue"
        ]
      },
      "stage_5_reload_and_export": {
        "reload": "re-run stage_4 after dashboard reload; provider series count must be stable",
        "export": { "format": "csv", "expect_columns": ["appointment_date", "provider_name", "count"] }
      }
    },
    {
      "case": "charge-billed-vs-collected-edit-regression",
      "description": "Editor measure-swap regression: change the measure in Editor and confirm the transferred tile recomputes (guards against the tile keeping the Creator measure).",
      "stage_1_creator_draft": {
        "id": "metric_billed_by_location",
        "label": "Billed by Location",
        "dataset": "charges",
        "aggregation": { "kind": "sum", "field": "billed" },
        "group_by": ["location"],
        "visualization": "bar",
        "format": "currency",
        "filters": [],
        "time_bucket": { "field": "date_of_service", "grain": "month", "window": "present" }
      },
      "stage_2_editor_edit": {
        "title_override": "Collected by Location",
        "overrides": { "measure": "total_collected" },
        "edit_intent": "swap measure billed -> total_collected; values must drop to collected amounts"
      },
      "stage_3_dashboard_card": {
        "dashboard_id": "dash_revenue_redacted",
        "tab": "overview",
        "card": { "metric_id": "metric_billed_by_location", "size": "md", "title_override": "Collected by Location" }
      },
      "stage_4_query_request": {
        "endpoint": "POST /api/studio/query",
        "body": {
          "dataSource": "charges",
          "measure": "total_collected",
          "summaryFunction": "sum",
          "dimensions": ["location"],
          "xDimension": "location",
          "timePeriod": "ytd",
          "timeGranularity": "month"
        }
      },
      "expected_signals": {
        "non_empty_series": true,
        "value_kind": "currency",
        "transfer_invariants": [
          "post-edit query uses total_collected, NOT billed",
          "collected totals <= billed totals for the same grouping"
        ]
      },
      "stage_5_reload_and_export": {
        "reload": "re-run after reload; measure stays total_collected",
        "export": { "format": "csv", "expect_columns": ["location", "total_collected"] }
      }
    }
  ],
  "dashboards": [
    {
      "id": "dash_revenue_redacted",
      "label": "Revenue (redacted)",
      "owner": "debug",
      "tabs": [
        { "id": "overview", "label": "Overview", "cards": [
          { "metric_id": "metric_collections_by_payer", "size": "lg" },
          { "metric_id": "metric_billed_by_location", "size": "md" }
        ] }
      ]
    },
    {
      "id": "dash_access_redacted",
      "label": "Access (redacted)",
      "owner": "debug",
      "tabs": [
        { "id": "access", "label": "Access", "cards": [
          { "metric_id": "metric_no_shows_by_provider", "size": "md" }
        ] }
      ]
    }
  ]
}
