[
  {
    "schema_version": "v1",
    "rule_id": "PL-001",
    "enabled": "TRUE",
    "rule_name": "Adobe Brief ID entered",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_BID",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Enter an Adobe Brief ID.",
    "fix_target": "val_BID",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-002",
    "enabled": "TRUE",
    "rule_name": "Trackline resolves from Brief ID",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_Trackline",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Trackline could not be found for this Brief ID.",
    "fix_target": "val_Trackline",
    "notes": "Should remain tied to named range rather than Start Here cell address."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-004",
    "enabled": "TRUE",
    "rule_name": "Parent Brand resolved",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_ParentBrand",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Parent Brand could not be determined.",
    "fix_target": "val_ParentBrand",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-005",
    "enabled": "TRUE",
    "rule_name": "Brand confirmed",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_Brand",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Confirm or select a brand.",
    "fix_target": "val_Brand",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-006",
    "enabled": "TRUE",
    "rule_name": "Business Function resolved",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_BusinessFunction",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Business Function is missing.",
    "fix_target": "val_BusinessFunction",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-007",
    "enabled": "TRUE",
    "rule_name": "Campaign Type selected",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_CampaignType",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Select a campaign type.",
    "fix_target": "val_CampaignType",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-008",
    "enabled": "TRUE",
    "rule_name": "Customer Type resolved",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_CustomerType",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Customer Type is missing.",
    "fix_target": "val_CustomerType",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-009",
    "enabled": "TRUE",
    "rule_name": "Campaign Name entered",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_CampaignName",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Enter a campaign name.",
    "fix_target": "val_CampaignName",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-010",
    "enabled": "TRUE",
    "rule_name": "Product resolved",
    "scope": "Plan",
    "severity": "Info",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_Product",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Product could not be determined from brand.",
    "fix_target": "val_Product",
    "notes": "Info-level rule in registry."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-011",
    "enabled": "TRUE",
    "rule_name": "Indication resolved",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_Indication",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Select an indication.",
    "fix_target": "val_Indication",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-012",
    "enabled": "TRUE",
    "rule_name": "Therapeutic Area resolved",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_TherapeuticArea",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Therapeutic Area could not be determined.",
    "fix_target": "val_TherapeuticArea",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-013",
    "enabled": "TRUE",
    "rule_name": "Market resolved",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_Country",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Select a market.",
    "fix_target": "val_Country",
    "notes": "Registry uses val_Country as the planner-facing market binding."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-014",
    "enabled": "TRUE",
    "rule_name": "Currency configured",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_TargetCurrency",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Currency is missing.",
    "fix_target": "val_TargetCurrency",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-015",
    "enabled": "TRUE",
    "rule_name": "FX Rate resolves",
    "scope": "Plan",
    "severity": "Warning",
    "applies_to": "Start Here",
    "binding_type": "named_range_pair",
    "target_object": "calc_AppliedUSDtoLC|calc_AppliedLCtoUSD",
    "target_field": "",
    "check_type": "positive_numeric_pair",
    "parameters": "",
    "message": "FX rate could not be determined.",
    "fix_target": "calc_AppliedUSDtoLC",
    "notes": "Should bind to calculation names rather than raw cells C38/C39."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-016",
    "enabled": "TRUE",
    "rule_name": "At least 1 channel selected",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range_set",
    "target_object": "control_*",
    "target_field": "",
    "check_type": "any_yes",
    "parameters": "names=control_PaidSearch|control_PaidSocial|control_Programmatic|control_Digital|control_Email|control_TVCinema|control_Print|control_OOH|control_Radio;true_value=Yes",
    "message": "Select at least one channel.",
    "fix_target": "control_*",
    "notes": "Uses existing control_* workbook names."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-017",
    "enabled": "TRUE",
    "rule_name": "At least 1 tactic entered",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "All channels (via PQ)",
    "binding_type": "output_table",
    "target_object": "Output_AllCampaigns",
    "target_field": "",
    "check_type": "has_rows",
    "parameters": "",
    "message": "No tactics entered yet.",
    "fix_target": "tab",
    "notes": "Registry rule based on Output_AllCampaigns row presence."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-018",
    "enabled": "TRUE",
    "rule_name": "Taxonomy string resolves",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_TaxonomyString",
    "target_field": "",
    "check_type": "not_error_nonblank",
    "parameters": "",
    "message": "Complete metadata to generate taxonomy.",
    "fix_target": "val_TaxonomyString",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-019",
    "enabled": "TRUE",
    "rule_name": "Branded-DTC compliance",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "Start Here",
    "binding_type": "named_range_pair",
    "target_object": "val_CampaignType|val_CustomerType",
    "target_field": "",
    "check_type": "branded_dtc_compliance",
    "parameters": "",
    "message": "Branded DTC plan - review compliance requirements.",
    "fix_target": "val_CampaignType",
    "notes": "Should surface existing VBA compliance logic in QA output."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-020",
    "enabled": "TRUE",
    "rule_name": "Plan-level market consistency",
    "scope": "Plan",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "mixed_binding",
    "target_object": "val_Country",
    "target_field": "Market",
    "check_type": "all_rows_equal_named_range_when",
    "parameters": "source_object=Output_AllCampaigns;gate_name=val_GeographyFunding;gate_value=Single Market",
    "message": "N tactics use a different market.",
    "fix_target": "val_Country",
    "notes": "Compares output-table tactic markets to plan market for single-market plans."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-021",
    "enabled": "TRUE",
    "rule_name": "All tactics costed (global)",
    "scope": "Plan",
    "severity": "Error",
    "applies_to": "All channels (via PQ)",
    "binding_type": "output_table_field",
    "target_object": "Output_AllCampaigns",
    "target_field": "Total Cost ($)",
    "check_type": "all_nonzero_on_nonempty",
    "parameters": "",
    "message": "N tactics have no cost.",
    "fix_target": "tab",
    "notes": "Global output-table cost completeness rule."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-022",
    "enabled": "TRUE",
    "rule_name": "Planner name entered",
    "scope": "Plan",
    "severity": "Warning",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_Planner",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Enter planner name.",
    "fix_target": "val_Planner",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "PL-023",
    "enabled": "TRUE",
    "rule_name": "Version set",
    "scope": "Plan",
    "severity": "Info",
    "applies_to": "Start Here",
    "binding_type": "named_range",
    "target_object": "val_PlanVersion",
    "target_field": "",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Version not set.",
    "fix_target": "val_PlanVersion",
    "notes": "Registry row imported from Validation_Rules_Registry.xlsx Plan-level sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-001",
    "enabled": "TRUE",
    "rule_name": "Media Subtype required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Media Subtype",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Media Subtype is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-002",
    "enabled": "TRUE",
    "rule_name": "Market required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Market",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Market is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-003",
    "enabled": "TRUE",
    "rule_name": "Start Date required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Start Date",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Start Date is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-004",
    "enabled": "TRUE",
    "rule_name": "End Date required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "End Date",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "End Date is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-005",
    "enabled": "TRUE",
    "rule_name": "Buy Type required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Buy Type",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Buy Type is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-006",
    "enabled": "TRUE",
    "rule_name": "Objective required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Objective",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Objective is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-007",
    "enabled": "TRUE",
    "rule_name": "Audience Segment required",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Audience Segment Name",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "Audience Segment is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-008",
    "enabled": "TRUE",
    "rule_name": "KPI required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "KPI",
    "check_type": "required_nonblank",
    "parameters": "",
    "message": "KPI is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-009",
    "enabled": "TRUE",
    "rule_name": "Net Media Cost required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field_choice",
    "target_object": "*",
    "target_field": "Net Media Cost|Gross Media Cost",
    "check_type": "required_positive",
    "parameters": "",
    "message": "Tactic has no media cost.",
    "fix_target": "row",
    "notes": "Column varies by channel."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-010",
    "enabled": "TRUE",
    "rule_name": "Start Date <= End Date",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field_pair",
    "target_object": "*",
    "target_field": "Start Date|End Date",
    "check_type": "date_order",
    "parameters": "",
    "message": "Start date is after end date.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-011",
    "enabled": "TRUE",
    "rule_name": "Start Date is a valid date",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Start Date",
    "check_type": "is_date",
    "parameters": "",
    "message": "Start Date is not a valid date.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-012",
    "enabled": "TRUE",
    "rule_name": "End Date is a valid date",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "End Date",
    "check_type": "is_date",
    "parameters": "",
    "message": "End Date is not a valid date.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-013",
    "enabled": "TRUE",
    "rule_name": "Negative cost",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "table_field_choice",
    "target_object": "*",
    "target_field": "Net Media Cost|Gross Media Cost",
    "check_type": "min_value",
    "parameters": "min=0",
    "message": "Negative media cost.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-014",
    "enabled": "TRUE",
    "rule_name": "Total Cost zero but cost entered",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Net Media Cost|Gross Media Cost|Total Cost ($)",
    "check_type": "dependent_nonzero",
    "parameters": "driver_fields=Net Media Cost|Gross Media Cost;dependent_field=Total Cost ($)",
    "message": "Media cost entered but Total Cost is zero - check FX/fee config.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-015",
    "enabled": "TRUE",
    "rule_name": "Tactic market matches plan market",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "mixed_binding",
    "target_object": "val_Country",
    "target_field": "Market",
    "check_type": "equals_named_range_when",
    "parameters": "gate_name=val_GeographyFunding;gate_value=Single Market",
    "message": "Market differs from plan market.",
    "fix_target": "row",
    "notes": "Row-level market consistency check."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-016",
    "enabled": "TRUE",
    "rule_name": "Creative deadline passed",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Creative Deadline",
    "check_type": "date_not_past",
    "parameters": "",
    "message": "Creative deadline has passed.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-017",
    "enabled": "TRUE",
    "rule_name": "Creative deadline after start",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "All channels",
    "binding_type": "table_field_pair",
    "target_object": "*",
    "target_field": "Creative Deadline|Start Date",
    "check_type": "date_not_after",
    "parameters": "",
    "message": "Creative deadline is after campaign start date.",
    "fix_target": "row",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-018",
    "enabled": "TRUE",
    "rule_name": "InName Site / DD valid",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "custom_existing",
    "target_object": "mod_modHelpers",
    "target_field": "InName Site|Publication|Vendor|Station",
    "check_type": "data_dictionary_valid",
    "parameters": "",
    "message": "Invalid Data Dictionary value.",
    "fix_target": "row",
    "notes": "Maps existing DD validation/watcher logic into registry."
  },
  {
    "schema_version": "v1",
    "rule_id": "XC-021",
    "enabled": "TRUE",
    "rule_name": "At least 1 tactic per channel",
    "scope": "Tab",
    "severity": "Error",
    "applies_to": "All visible channels",
    "binding_type": "table",
    "target_object": "*",
    "target_field": "",
    "check_type": "has_rows",
    "parameters": "",
    "message": "No tactics entered.",
    "fix_target": "tab",
    "notes": "Registry row imported from Cross-channel sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-001",
    "enabled": "TRUE",
    "rule_name": "Format required (Search)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Paid Search",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Format",
    "check_type": "required_nonblank",
    "parameters": "channels=Paid Search",
    "message": "Format is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-002",
    "enabled": "TRUE",
    "rule_name": "Ad Copy populated",
    "scope": "Tab",
    "severity": "Warning",
    "applies_to": "Paid Search Ad Copy",
    "binding_type": "table",
    "target_object": "*",
    "target_field": "Paid Search Ad Copy table",
    "check_type": "has_rows_when_channel_active",
    "parameters": "channels=Paid Search Ad Copy;gate_name=control_PaidSearch;gate_value=Yes",
    "message": "Paid Search active but no ad copy entered.",
    "fix_target": "tab",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-003",
    "enabled": "TRUE",
    "rule_name": "Placement required (Social)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Paid Social",
    "binding_type": "table_field_choice",
    "target_object": "*",
    "target_field": "Format|Placement",
    "check_type": "required_nonblank",
    "parameters": "channels=Paid Social",
    "message": "Placement is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-004",
    "enabled": "TRUE",
    "rule_name": "Buy Type required (Prog)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Programmatic",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Buy Type",
    "check_type": "required_nonblank",
    "parameters": "channels=Programmatic",
    "message": "Buy Type is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-005",
    "enabled": "TRUE",
    "rule_name": "InName Site specified (Prog)",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Programmatic",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "InName Site",
    "check_type": "required_nonblank",
    "parameters": "channels=Programmatic",
    "message": "InName Site is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-006",
    "enabled": "TRUE",
    "rule_name": "Spot Length required (TV)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "TV & Cinema",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Spot Length",
    "check_type": "required_nonblank",
    "parameters": "channels=TV & Cinema",
    "message": "Spot Length is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-007",
    "enabled": "TRUE",
    "rule_name": "Station required (TV)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "TV & Cinema",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Station",
    "check_type": "required_nonblank",
    "parameters": "channels=TV & Cinema",
    "message": "Station is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-008",
    "enabled": "TRUE",
    "rule_name": "Publication required (Print)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Print",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Publication",
    "check_type": "required_nonblank",
    "parameters": "channels=Print",
    "message": "Publication is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-009",
    "enabled": "TRUE",
    "rule_name": "Issue Date required (Print)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Print",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Issue Date",
    "check_type": "required_nonblank",
    "parameters": "channels=Print",
    "message": "Issue date is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-010",
    "enabled": "TRUE",
    "rule_name": "Vendor required (OOH)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "OOH",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Vendor",
    "check_type": "required_nonblank",
    "parameters": "channels=OOH",
    "message": "Vendor is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-011",
    "enabled": "TRUE",
    "rule_name": "Format required (OOH)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "OOH",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Format",
    "check_type": "required_nonblank",
    "parameters": "channels=OOH",
    "message": "Format is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-012",
    "enabled": "TRUE",
    "rule_name": "Station required (Radio)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Radio",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Station",
    "check_type": "required_nonblank",
    "parameters": "channels=Radio",
    "message": "Station is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-013",
    "enabled": "TRUE",
    "rule_name": "Spot Length required (Radio)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Radio",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Spot Length",
    "check_type": "required_nonblank",
    "parameters": "channels=Radio",
    "message": "Spot Length is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-014",
    "enabled": "TRUE",
    "rule_name": "Audience Size (Email)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Email",
    "binding_type": "table_field_choice",
    "target_object": "*",
    "target_field": "Audience Size|List Size",
    "check_type": "required_nonblank",
    "parameters": "channels=Email",
    "message": "Audience size is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-015",
    "enabled": "TRUE",
    "rule_name": "Ad Size required (Digital)",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Digital",
    "binding_type": "table_field_choice",
    "target_object": "*",
    "target_field": "Format|Ad Size",
    "check_type": "required_nonblank",
    "parameters": "channels=Digital",
    "message": "Ad Size is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "CS-017",
    "enabled": "TRUE",
    "rule_name": "Adserving Method required",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Digital channels",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Adserving Method|Third Party Ad Verification",
    "check_type": "all_required",
    "parameters": "channels=Paid Search|Paid Social|Programmatic|Digital|Email",
    "message": "Adserving method / verification is blank.",
    "fix_target": "row",
    "notes": "Registry row imported from Channel-specific sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-001",
    "enabled": "TRUE",
    "rule_name": "Unit Cost required (non-Flat Fee)",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "All channels",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Unit Cost (Planning Currency)",
    "check_type": "metric_required_when_buy_type_not",
    "parameters": "excluded_buy_type=Flat Fee;required_field=Unit Cost (Planning Currency)",
    "message": "Unit Cost is blank or zero - enter the rate for this buy type.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-002",
    "enabled": "TRUE",
    "rule_name": "CTR required for CPC buys",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Paid Search|Paid Social|Programmatic|Digital",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Clickthrough Rate",
    "check_type": "metric_required_for_buy_type",
    "parameters": "buy_type=CPC;required_field=Clickthrough Rate;channels=Paid Search|Paid Social|Programmatic|Digital",
    "message": "CPC buy type but no CTR entered - Clicks cannot be calculated.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-003",
    "enabled": "TRUE",
    "rule_name": "VTR required for CPV buys",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Paid Social|Programmatic|Digital",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Viewthrough Rate",
    "check_type": "metric_required_for_buy_type",
    "parameters": "buy_type=CPV;required_field=Viewthrough Rate;channels=Paid Social|Programmatic|Digital",
    "message": "CPV buy type but no VTR entered - Views cannot be calculated.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-004",
    "enabled": "TRUE",
    "rule_name": "CVR required for CPA buys",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Paid Search|Paid Social|Programmatic|Digital|Email",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Conversion Rate",
    "check_type": "metric_required_for_buy_type",
    "parameters": "buy_type=CPA;required_field=Conversion Rate;channels=Paid Search|Paid Social|Programmatic|Digital|Email",
    "message": "CPA buy type but no CVR entered - Conversions cannot be calculated.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-005",
    "enabled": "TRUE",
    "rule_name": "Open Rate required for Cost Per Open",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Email",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Open Rate",
    "check_type": "metric_required_for_buy_type",
    "parameters": "buy_type=Cost Per Open;required_field=Open Rate;channels=Email",
    "message": "Cost Per Open buy type but no Open Rate entered.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-006",
    "enabled": "TRUE",
    "rule_name": "Click to Open Rate required for CPC email",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Email",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Click to Open Rate",
    "check_type": "metric_required_for_buy_type",
    "parameters": "buy_type=CPC;required_field=Click to Open Rate;channels=Email",
    "message": "CPC buy type but no Click to Open Rate entered.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-007",
    "enabled": "TRUE",
    "rule_name": "Reach % required",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "TV & Cinema|Radio",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Reach %",
    "check_type": "metric_required_when_buy_type_not",
    "parameters": "excluded_buy_type=Flat Fee;required_field=Reach %;channels=TV & Cinema|Radio",
    "message": "Reach % is blank - GRPs cannot be calculated.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-008",
    "enabled": "TRUE",
    "rule_name": "Insertions required",
    "scope": "Row",
    "severity": "Error",
    "applies_to": "Print",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Insertions",
    "check_type": "required_positive",
    "parameters": "channels=Print",
    "message": "Insertions is blank or zero.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-009",
    "enabled": "TRUE",
    "rule_name": "Impressions required (OOH)",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "OOH",
    "binding_type": "table_field",
    "target_object": "*",
    "target_field": "Impressions",
    "check_type": "required_positive",
    "parameters": "channels=OOH",
    "message": "Impressions is blank - CPM cannot be calculated.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  },
  {
    "schema_version": "v1",
    "rule_id": "MET-010",
    "enabled": "TRUE",
    "rule_name": "Impressions populated for CPM buys",
    "scope": "Row",
    "severity": "Warning",
    "applies_to": "Paid Search|Paid Social|Programmatic|Digital|OOH",
    "binding_type": "table_field_group",
    "target_object": "*",
    "target_field": "Buy Type|Impressions",
    "check_type": "metric_required_for_buy_type",
    "parameters": "buy_type=CPM;required_field=Impressions;channels=Paid Search|Paid Social|Programmatic|Digital|OOH",
    "message": "CPM buy type but Impressions is zero - check Unit Cost and Net Media Cost.",
    "fix_target": "row",
    "notes": "Registry row imported from Metric validation sheet."
  }
]