{
  "schemaVersion": "1.0.0",
  "name": "CricketStudio Metric Registry",
  "description": "19 OKF-registered cricket metrics for T20 leagues. Each metric has a stable cs_metric_* ID, formula, sample floor, edge cases, and citation guidance.",
  "publishedAt": "2026-07-06T00:00:00.000Z",
  "totalMetrics": 19,
  "okfSource": "https://okf.cricketstudio.ai/metrics",
  "license": "CC-BY-4.0",
  "licenseUrl": "https://creativecommons.org/licenses/by/4.0/",
  "categories": {
    "batting": 10,
    "bowling": 7,
    "tournament": 2
  },
  "metrics": [
    {
      "id": "cs_metric_batting_strike_rate",
      "name": "Batting Strike Rate",
      "category": "batting",
      "formula": "(runs / balls_faced) × 100",
      "formulaLatex": "\\frac{\\text{runs}}{\\text{balls faced}} \\times 100",
      "unit": "runs_per_ball_x100",
      "sampleFloor": {
        "minimum": 30,
        "unit": "balls",
        "description": "Minimum 30 balls faced in the stated window"
      },
      "suppressionRule": "Suppress (do not publish) when balls_faced < 30. Return null, not 0.",
      "appliesTo": [
        "player",
        "batting_phase",
        "team"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "Retired hurt counts as not-out — excluded from average denominator, included in strike rate.",
        "Super Over balls are excluded from all T20 league aggregates.",
        "No-balls faced by the batter are counted in balls faced."
      ],
      "limitations": [
        "Does not account for match context (win/loss, target set, required rate).",
        "Phase-split strike rates require a per-phase sample floor of 30 balls each, independent of overall floor."
      ],
      "citationGuidance": "Cite as: \"{player} batting strike rate in {window}: {value} from {balls} balls.\" Always include sample size.",
      "okfRef": "https://okf.cricketstudio.ai/metrics/batting-strike-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_batting_average",
      "name": "Batting Average",
      "category": "batting",
      "formula": "runs / dismissals",
      "formulaLatex": "\\frac{\\text{runs}}{\\text{dismissals}}",
      "unit": "runs_per_wicket",
      "sampleFloor": {
        "minimum": 10,
        "unit": "innings",
        "description": "Minimum 10 innings in the stated window"
      },
      "suppressionRule": "Suppress when innings < 10. Not-outs reduce dismissal count but not innings count.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Infinite average (never dismissed) shown as \"—\" not as a numeric value.",
        "Retired hurt: not counted as a dismissal.",
        "T20 average is heavily influenced by not-out innings in short careers."
      ],
      "limitations": [
        "T20 averages are less meaningful than Test averages due to high not-out rate.",
        "Does not reflect opportunity (number of balls available)."
      ],
      "citationGuidance": "Cite as: \"{player} batting average in {window}: {value} across {innings} innings ({not_outs} not-outs).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/batting-average",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_boundary_percentage",
      "name": "Boundary Percentage",
      "category": "batting",
      "formula": "((fours + sixes) / balls_faced) × 100",
      "formulaLatex": "\\frac{\\text{fours} + \\text{sixes}}{\\text{balls faced}} \\times 100",
      "unit": "percentage",
      "sampleFloor": {
        "minimum": 30,
        "unit": "balls",
        "description": "Minimum 30 balls faced"
      },
      "suppressionRule": "Suppress when balls_faced < 30.",
      "appliesTo": [
        "player",
        "batting_phase"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "Overthrows that cross the boundary are counted as part of the total but not credited to the batter in this metric."
      ],
      "limitations": [
        "High boundary % in small samples is noisy. Always show sample size."
      ],
      "citationGuidance": "Cite as: \"{player} hit boundaries on {value}% of balls faced in {window} ({balls} balls).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/boundary-percentage",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_dot_ball_percentage_batting",
      "name": "Dot Ball Percentage (Batting)",
      "category": "batting",
      "formula": "(dot_balls_faced / balls_faced) × 100",
      "formulaLatex": "\\frac{\\text{dot balls faced}}{\\text{balls faced}} \\times 100",
      "unit": "percentage",
      "sampleFloor": {
        "minimum": 30,
        "unit": "balls",
        "description": "Minimum 30 balls faced"
      },
      "suppressionRule": "Suppress when balls_faced < 30.",
      "appliesTo": [
        "player",
        "batting_phase"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "Wides and no-balls are not counted as balls faced, so they do not affect this metric."
      ],
      "limitations": [
        "Context-blind: a number 11 batter defending is different from an opener doing the same."
      ],
      "citationGuidance": "Cite as: \"{player} scored off {100-value}% of balls faced in {window} ({balls} balls).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/dot-ball-percentage",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_powerplay_strike_rate",
      "name": "Powerplay Strike Rate",
      "category": "batting",
      "formula": "(pp_runs / pp_balls) × 100, where overs 1–6 only",
      "formulaLatex": "\\frac{\\text{PP runs}}{\\text{PP balls}} \\times 100",
      "unit": "runs_per_ball_x100",
      "sampleFloor": {
        "minimum": 30,
        "unit": "balls",
        "description": "Minimum 30 balls faced in powerplay overs (1–6)"
      },
      "suppressionRule": "Suppress when powerplay balls faced < 30.",
      "appliesTo": [
        "player",
        "team"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Only overs 1–6 (first powerplay in T20) are counted.",
        "A batter who never bats in the powerplay has no powerplay strike rate (suppress, not 0)."
      ],
      "limitations": [
        "Opener vs. middle-order distinction matters: compare only players with similar batting positions."
      ],
      "citationGuidance": "Cite as: \"{player} powerplay strike rate in {window}: {value} from {balls} balls (overs 1–6).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/powerplay-strike-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_death_overs_strike_rate",
      "name": "Death Overs Strike Rate (Batting)",
      "category": "batting",
      "formula": "(death_runs / death_balls) × 100, where overs 17–20 only",
      "formulaLatex": "\\frac{\\text{death runs}}{\\text{death balls}} \\times 100",
      "unit": "runs_per_ball_x100",
      "sampleFloor": {
        "minimum": 30,
        "unit": "balls",
        "description": "Minimum 30 balls faced in death overs (17–20)"
      },
      "suppressionRule": "Suppress when death balls faced < 30.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "In matches that end before over 17, no death-overs data exists.",
        "Super Overs are excluded."
      ],
      "limitations": [
        "Highly position-dependent: only finishers (positions 5–8 typically) accumulate sufficient sample."
      ],
      "citationGuidance": "Cite as: \"{player} death overs strike rate in {window}: {value} from {balls} balls (overs 17–20).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/batting-strike-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_net_run_rate",
      "name": "Net Run Rate",
      "category": "batting",
      "formula": "(total_runs_scored / total_overs_faced) − (total_runs_conceded / total_overs_bowled)",
      "formulaLatex": "\\frac{\\text{runs scored}}{\\text{overs faced}} - \\frac{\\text{runs conceded}}{\\text{overs bowled}}",
      "unit": "ratio",
      "sampleFloor": {
        "minimum": 3,
        "unit": "matches",
        "description": "Minimum 3 completed matches for a meaningful NRR"
      },
      "suppressionRule": "NRR from < 3 matches is not published as a standalone claim.",
      "appliesTo": [
        "team"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "All-out innings: overs faced = full 20 overs regardless of when dismissed.",
        "D/L method adjustments: use the revised target overs for both numerator and denominator."
      ],
      "limitations": [
        "Season NRR is a summary statistic — it does not predict future match outcomes."
      ],
      "citationGuidance": "Cite as: \"{team} NRR in {window}: {value} across {matches} matches.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/net-run-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_run_rate",
      "name": "Run Rate",
      "category": "batting",
      "formula": "runs_scored / overs_completed",
      "formulaLatex": "\\frac{\\text{runs scored}}{\\text{overs completed}}",
      "unit": "runs_per_over",
      "sampleFloor": {
        "minimum": 6,
        "unit": "balls",
        "description": "Minimum 1 complete over (6 balls)"
      },
      "suppressionRule": "Suppress for < 1 complete over.",
      "appliesTo": [
        "team",
        "player"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "Wides and no-balls are counted in the over total but add to runs conceded.",
        "Partial last over: runs / (balls / 6) gives a rate from a fractional over."
      ],
      "limitations": [
        "Point-in-time run rate during an innings does not account for wickets in hand."
      ],
      "citationGuidance": "Cite as: \"{team/player} run rate of {value} rpo in {window} ({overs} overs).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/run-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_partnership_value",
      "name": "Partnership Value",
      "category": "batting",
      "formula": "sum(runs_added_while_both_batters_present) for a given wicket stand",
      "formulaLatex": "\\sum_{\\text{balls shared}} \\text{runs scored}",
      "unit": "count",
      "sampleFloor": {
        "minimum": 5,
        "unit": "balls",
        "description": "Minimum 5 balls shared to publish as a partnership record"
      },
      "suppressionRule": "Single-ball partnerships (run-outs off 1st ball) are excluded from partnership leaderboards.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Byes and leg byes are NOT credited to the partnership total.",
        "Wides count toward the partnership total (they add to team score while the pair is together)."
      ],
      "limitations": [
        "Partnership value ignores run rate context — a 50-run stand in the powerplay is different to one in the death."
      ],
      "citationGuidance": "Cite as: \"{player1} and {player2} put on {runs} for the {wicket} wicket in {match}, {window}.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/partnership-value",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_average_vs_strike_rate",
      "name": "Average vs Strike Rate Index",
      "category": "batting",
      "formula": "batting_average × (batting_strike_rate / 100)",
      "formulaLatex": "\\text{avg} \\times \\frac{\\text{SR}}{100}",
      "unit": "ratio",
      "sampleFloor": {
        "minimum": 30,
        "unit": "balls",
        "description": "Both constituent metrics (average and strike rate) must individually meet their floors"
      },
      "suppressionRule": "Suppress if either constituent metric is suppressed.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Not a standard cricket statistic — it is a CricketStudio/OKF composite for balanced T20 batter assessment."
      ],
      "limitations": [
        "Should not be used for inter-era comparisons.",
        "Composite; not directly verifiable from scorecards without the individual components."
      ],
      "citationGuidance": "Cite the components separately and label this explicitly as a composite index.",
      "okfRef": "https://okf.cricketstudio.ai/metrics/average-vs-strike-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_bowling_economy",
      "name": "Bowling Economy Rate",
      "category": "bowling",
      "formula": "runs_conceded / overs_bowled",
      "formulaLatex": "\\frac{\\text{runs conceded}}{\\text{overs bowled}}",
      "unit": "runs_per_over",
      "sampleFloor": {
        "minimum": 15,
        "unit": "balls",
        "description": "Minimum 15 balls bowled (2.5 overs) in the stated window"
      },
      "suppressionRule": "Suppress when balls_bowled < 15.",
      "appliesTo": [
        "player",
        "bowling_phase",
        "team"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "Wides and no-balls are counted in runs conceded but NOT in balls bowled.",
        "A bowler who completes only wides in an over has 0 legal deliveries — that over does not contribute to economy."
      ],
      "limitations": [
        "Economy alone does not indicate wicket-taking ability.",
        "Powerplay economy vs. death economy are not comparable directly."
      ],
      "citationGuidance": "Cite as: \"{player} bowling economy in {window}: {value} rpo from {overs} overs ({balls} legal balls).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/bowling-economy",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_bowling_average",
      "name": "Bowling Average",
      "category": "bowling",
      "formula": "runs_conceded / wickets_taken",
      "formulaLatex": "\\frac{\\text{runs conceded}}{\\text{wickets taken}}",
      "unit": "runs_per_wicket",
      "sampleFloor": {
        "minimum": 15,
        "unit": "balls",
        "description": "Minimum 15 balls bowled"
      },
      "suppressionRule": "Suppress when balls_bowled < 15 OR wickets = 0 (infinite average — show as \"no wickets\" not as a number).",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Run-outs are NOT credited to the bowler — do not include in wickets_taken.",
        "Obstructions and handled-the-ball are counted as bowler wickets."
      ],
      "limitations": [
        "A bowler with 1 wicket for 6 runs has a very good average but meaningless in T20 context.",
        "T20 bowling averages are noisier than Test averages; always report with wicket count."
      ],
      "citationGuidance": "Cite as: \"{player} bowling average in {window}: {value} from {wickets} wickets across {balls} balls.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/batting-average",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_bowling_strike_rate",
      "name": "Bowling Strike Rate",
      "category": "bowling",
      "formula": "balls_bowled / wickets_taken",
      "formulaLatex": "\\frac{\\text{balls bowled}}{\\text{wickets taken}}",
      "unit": "ratio",
      "sampleFloor": {
        "minimum": 15,
        "unit": "balls",
        "description": "Minimum 15 balls bowled"
      },
      "suppressionRule": "Suppress when balls_bowled < 15 OR wickets = 0.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Lower is better. A bowling strike rate of 12 means a wicket every 2 overs."
      ],
      "limitations": [
        "Does not account for the cost of those wickets (economy)."
      ],
      "citationGuidance": "Cite as: \"{player} bowling strike rate in {window}: {value} balls/wicket from {wickets} wickets.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/bowling-strike-rate",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_dot_ball_percentage_bowling",
      "name": "Dot Ball Percentage (Bowling)",
      "category": "bowling",
      "formula": "(dot_balls_bowled / legal_balls_bowled) × 100",
      "formulaLatex": "\\frac{\\text{dot balls bowled}}{\\text{legal balls}} \\times 100",
      "unit": "percentage",
      "sampleFloor": {
        "minimum": 15,
        "unit": "balls",
        "description": "Minimum 15 legal balls bowled"
      },
      "suppressionRule": "Suppress when legal_balls_bowled < 15.",
      "appliesTo": [
        "player",
        "bowling_phase"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "Wides and no-balls are not legal deliveries — excluded from both numerator and denominator."
      ],
      "limitations": [
        "High dot-ball percentage does not distinguish between taking wickets and being blocked."
      ],
      "citationGuidance": "Cite as: \"{player} bowled dot balls on {value}% of deliveries in {window} ({balls} legal balls).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/dot-ball-percentage",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_death_overs_economy",
      "name": "Death Overs Economy",
      "category": "bowling",
      "formula": "death_runs_conceded / death_overs_bowled, where overs 17–20 only",
      "formulaLatex": "\\frac{\\text{death runs conceded}}{\\text{death overs bowled}}",
      "unit": "runs_per_over",
      "sampleFloor": {
        "minimum": 15,
        "unit": "balls",
        "description": "Minimum 15 balls bowled in overs 17–20"
      },
      "suppressionRule": "Suppress when death_balls < 15.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Includes Super Over? No — Super Overs are excluded from all phase metrics.",
        "A bowler who only bowls overs 1–4 never accumulates death economy."
      ],
      "limitations": [
        "Death economy is captain-assigned, not player-driven — a bowler can only be compared to others given the same role."
      ],
      "citationGuidance": "Cite as: \"{player} death overs economy in {window}: {value} rpo from {balls} balls (overs 17–20).\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/death-overs-economy",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_phase_split_economy",
      "name": "Phase-Split Economy",
      "category": "bowling",
      "formula": "Separate economy calculations for each T20 phase: PP (1–6), middle (7–16), death (17–20)",
      "formulaLatex": "\\text{economy}_{\\text{phase}} = \\frac{\\text{runs in phase}}{\\text{overs in phase}}",
      "unit": "runs_per_over",
      "sampleFloor": {
        "minimum": 15,
        "unit": "balls",
        "description": "Minimum 15 balls bowled in EACH phase independently"
      },
      "suppressionRule": "Each phase economy is suppressed independently. A bowler can have PP economy but not death economy if they lack sample in death overs.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Middle overs span 10 overs — most bowlers accumulate middle sample faster than death sample."
      ],
      "limitations": [
        "Three separate numbers; not combinable into a single \"overall phase economy\" without re-weighting."
      ],
      "citationGuidance": "Cite each phase explicitly: \"{player} PP economy {pp}, middle {mid}, death {death} in {window}.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/phase-split-economy",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_win_probability",
      "name": "Win Probability",
      "category": "bowling",
      "formula": "Model-derived probability (0–1) of the batting team winning given current match state",
      "formulaLatex": "P(\\text{win} | \\text{state}) = f(\\text{runs needed, wickets, balls, venue, format})",
      "unit": "probability",
      "sampleFloor": {
        "minimum": 30,
        "unit": "matches",
        "description": "Model trained on minimum 30 comparable match states (Phase B metric — requires expected-value model)"
      },
      "suppressionRule": "Phase B only (§21.1). Not published until expected-value model is trained, versioned, and published at /methodology/model/.",
      "appliesTo": [
        "team",
        "player"
      ],
      "phaseApplicable": true,
      "edgeCases": [
        "D/L method matches require state adjustment before applying model."
      ],
      "limitations": [
        "Phase B metric: requires a published model card at /methodology/model/expected-value-v1/ before any claim is published.",
        "See doctrine §21.1 and §3.3-model for provenance requirements."
      ],
      "citationGuidance": "Phase B only. Every win-probability claim must cite the model version and link to the model card.",
      "okfRef": "https://okf.cricketstudio.ai/metrics/win-probability",
      "version": "0.1.0-draft",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_orange_cap",
      "name": "Orange Cap",
      "category": "tournament",
      "formula": "player with the most runs scored in a single T20 league season",
      "formulaLatex": "\\text{Orange Cap} = \\arg\\max_{\\text{player}} \\text{season runs}",
      "unit": "count",
      "sampleFloor": {
        "minimum": 5,
        "unit": "matches",
        "description": "Must have appeared in at least 5 matches to be eligible"
      },
      "suppressionRule": "Not applicable — Orange Cap is the winner, not a rate stat.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Ties resolved by the official league standing (typically strike rate, then highest score)."
      ],
      "limitations": [
        "A player who opens every match accumulates runs faster than a finisher; do not use Orange Cap as a per-innings quality indicator."
      ],
      "citationGuidance": "Cite as: \"{player} won the {season} Orange Cap with {runs} runs from {matches} matches.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/orange-cap",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    },
    {
      "id": "cs_metric_purple_cap",
      "name": "Purple Cap",
      "category": "tournament",
      "formula": "player with the most wickets taken in a single T20 league season",
      "formulaLatex": "\\text{Purple Cap} = \\arg\\max_{\\text{player}} \\text{season wickets}",
      "unit": "count",
      "sampleFloor": {
        "minimum": 5,
        "unit": "matches",
        "description": "Must have appeared in at least 5 matches to be eligible"
      },
      "suppressionRule": "Not applicable — Purple Cap is the winner, not a rate stat.",
      "appliesTo": [
        "player"
      ],
      "phaseApplicable": false,
      "edgeCases": [
        "Run-outs are NOT counted as bowler wickets.",
        "Ties resolved by the official league standing (typically economy rate)."
      ],
      "limitations": [
        "Wicket counts favour high-over bowlers (pace options who regularly bowl 4 overs) over part-timers."
      ],
      "citationGuidance": "Cite as: \"{player} won the {season} Purple Cap with {wickets} wickets from {matches} matches.\"",
      "okfRef": "https://okf.cricketstudio.ai/metrics/purple-cap",
      "version": "1.0.0",
      "publishedAt": "2026-07-06"
    }
  ]
}