# MA Star Ratings — measure cut points

`medicare_silver.stars_cutpoints` · Medicare Advantage, Part D, Medicaid · status live

The annual CMS cut points (thresholds) per measure, star-level and org-subtype. The inputs that turn a raw measure value into a star; consumed by the recompute.

**Grain.** One row per (Star Ratings measure x star level x rating year). 1,815 rows = 46 measures (not all present every year) x 5 star levels x the measure's applicable years. org_subtype is a constant ('ALL') so it is not a real grain dimension. Verified: distinct count of (measure_id, star_level, rating_year) = 1,815 = total row count. calculation_epoch and bronze_publication_id are 1:1 with rating_year so they are interchangeable as the year dimension, but rating_year is the cleanest.

**How to use it.** To find what 99-th-percentile-style band a plan needs for 5 stars on a measure: SELECT star_level, threshold_lower_op, threshold_lower_bound, threshold_upper_op, threshold_upper_bound, raw_threshold_text FROM medicare_silver.stars_cutpoints WHERE rating_year = 2026 AND measure_id = 'C01:' ORDER BY star_level. This returns the five score bands for that measure that year (e.g. star 1 '< 58%', star 5 '>= 84%'), letting an agent map any plan's raw measure score to its star rating. Always include the trailing colon in measure_id and read raw_threshold_text for the authoritative band edges.

**Traps.**
- Minimal grain is (measure_id, star_level, rating_year) = 1,815 rows. org_subtype looks like a dimension but is constant 'ALL'; calculation_epoch and bronze_publication_id look like keys but are just 1:1 aliases of rating_year (each is per-year, not per-row, so neither alone is the grain).
- The parsed numeric columns (threshold_lower_bound / threshold_upper_bound and their _op columns) are a LOSSY extraction of raw_threshold_text and are frequently NULL when the actual value exists. E.g. RY2026 C01 star 2 raw text '>= 58 % to < 71 %' is a closed band but threshold_upper_bound is NULL. To reconstruct correct score bands, parse raw_threshold_text - do not trust the numeric bound columns as complete or authoritative.
- Units are NOT uniform across measures: most thresholds are percentages 0-100, but some measures use small/negative decimals (e.g. '< -0.114'). Never assume a 0-100 scale; the meaning of a threshold depends on the measure_id (measure metadata is not in this table - you must join to a measure dictionary).
- raw_threshold_text has dirty tokens: a '?' character is corrupted mojibake for the '>=' sign (e.g. '? 87%' = '>= 87%'), plus 'NA', '*', and '100%'. Rows containing these have BOTH parsed bounds NULL - they are unparsed top-band (star 5) thresholds, a real data-quality hole, not genuinely-missing cutpoints. measure_id also carries a trailing colon ('C19:').
- Coverage holes: rating_year 2022 is entirely absent (COVID-disrupted CMS cycle, years jump 2021->2023). Part D drug measures (D01-D12) appear ONLY in rating_year 2026; for 2015-2025 only Part C (C-prefix) measures exist - so drug-plan cutpoints are essentially missing before RY2026.
- is_current is TRUE for 100% of rows, effective_period_end / restatement_of are 100% NULL, and cms_vintage_sequence / parse_revision are constant (1 / 0) - the versioning machinery is in place but no restatements or second vintages have happened yet, so today these columns add no filtering value (do not write WHERE is_current logic expecting it to remove duplicates). Also: asserted_at is pipeline load time (May 2026), not source date - use rating_year / effective_period_start for source timing.

| column | type | meaning |
|---|---|---|
| measure_id | string | CMS Star Ratings measure code, e.g. 'C01:', 'C19:', 'D04:'. C-prefix = Part C (Medicare Advantage health-plan) measures (C01-C34 observed); D-prefix = Part D (prescription-drug-plan) measures (D01-D12 observed). 46 distinct. GOTCHA: every value carries a trailing colon (parser artifact) - join/filter with the colon included or strip it first. The numeric suffix is just a sequential index within a year and is NOT stable across years (the measure behind 'C30:' can differ year to year). |
| star_level | int | The star band this threshold defines, integer 1-5 (exactly 363 rows at each level). 1 = lowest performance band, 5 = highest. Each (measure_id, rating_year) has all five levels, forming five contiguous score bands. |
| org_subtype | string | Organization subtype the cut point applies to. CONSTANT 'ALL' for every row (1,815/1,815) - cutpoints are not split by contract type in this table. Effectively a placeholder; do not use it as a grain or filter dimension. |
| threshold_lower_bound | double | Parsed numeric lower edge of the band (float). NULL means no lower bound (band is open at the bottom, typically star_level 1). Units vary by measure: most are percentages (0-100), but some measures (CAHPS/HOS-style) use small decimals incl. negatives (e.g. -0.114). GOTCHA: this is a LOSSY parse of raw_threshold_text - for many middle-band rows it is populated while the upper bound is left NULL even though both edges appear in the raw text. |
| threshold_upper_bound | double | Parsed numeric upper edge of the band (float). NULL means no upper bound (band open at top, typically star_level 5). GOTCHA: under-populated relative to raw_threshold_text - e.g. RY2026 C01 star_level 2 raw text is '>= 58 % to < 71 %' (a closed [58,71) band) but threshold_upper_bound is NULL and only the lower side was extracted. To reconstruct full bands reliably, parse raw_threshold_text yourself rather than trusting these numeric columns alone. |
| threshold_lower_op | string | Comparison operator for the lower bound: '>=' or '>' (or NULL when there is no lower bound). NULL exactly when threshold_lower_bound is NULL. |
| threshold_upper_op | string | Comparison operator for the upper bound: '<' or '<=' (or NULL when there is no upper bound). NULL exactly when threshold_upper_bound is NULL. Band logic by level: star 1 mostly '< X' (bottom-open), stars 2-4 mostly '>= X to < Y' (closed), star 5 mostly '>= X' (top-open). |
| raw_threshold_text | string | The verbatim threshold string as it appeared in the CMS source table, e.g. '< 77', '>= 61 to < 65', '>= 53 % to < 80 %', '< -0.114'. 1,151 distinct, never NULL - this is the audit/ground-truth value and is more complete than the parsed bound columns. GOTCHA: contains messy artifacts - inconsistent spacing ('< 27 %' vs '< 27%'), trailing '%', and a corrupted '?' character that is a mojibake of the >= sign (e.g. '? 87%' means '>= 87%'); rows with that '?' or with 'NA'/'*'/'100%' have BOTH parsed bounds NULL because the parser could not interpret them. |
| effective_period_start | date | Date this rating year's cutpoints take effect (the CMS publication/effective date). One distinct value per rating_year, 11 total, ranging 2014-10-09 (RY2015) to 2025-10-10 (RY2026), normally early October. ANOMALY: RY2024 is 2024-07-02 (a mid-year republication). This is the table's primary time column; periodicity ~402 days = annual. |
| effective_period_end | date | Date the cutpoints stop being effective. 100% NULL across all 1,815 rows - cutpoints are stored with an open-ended window and are never end-dated/superseded in this snapshot. |
| calculation_epoch | string | Logical version label for the cutpoint set, formatted 'ry<YYYY>_v<n>', e.g. 'ry2025_v1'. 11 distinct, 1:1 with rating_year, all '_v1' (no v2+ yet). Interchangeable with rating_year as the year key; the '_v' suffix is reserved for future CMS re-releases of the same year. |
| restatement_of | string | Pointer (id) to a prior row this row restates/corrects. 100% NULL - no restatements have occurred yet. Reserved provenance column for when CMS reissues a vintage. |
| parse_revision | int | Integer revision of the parser run that produced the row. CONSTANT 0 for all rows - only one parse generation exists. Bumps if the data is re-parsed from the same source. |
| parser_artifact_hash | string | Hash identifying the parser code/artifact version. 1 distinct value across the whole table - a single parser version produced every row. |
| source_url | string | URL of the official CMS Star Ratings ZIP the row was extracted from (one per rating_year, 11 distinct), e.g. 'https://www.cms.gov/files/zip/2025-star-ratings-data-tables.zip'. Confirms provenance as the CMS annual 'Star Ratings data tables' / 'star ratings and display measures' releases on cms.gov. |
| sha256_content_hash | string | SHA-256 of the source content the row came from. 11 distinct (one per source file / rating_year) - content-addressed provenance tying each year's rows to a specific bytes-exact source download. |
| bronze_publication_id | string | UUID of the bronze-layer publication batch. 11 distinct, 1:1 with rating_year. Identifies the ingestion event; usable as an alternate year key but rating_year is more legible. |
| asserted_at | timestamp | Timestamp Vlada ingested/asserted the row (UTC), ranging 2026-05-17 to 2026-05-28. This is the PIPELINE load time, NOT the CMS source date - do not use it for source recency; use effective_period_start / rating_year instead. |
| rating_year | int | The Star Ratings year these cutpoints belong to (the year the ratings are published/branded). Observed 2015-2026, 11 distinct. GOTCHA: 2022 is MISSING (jumps 2021 -> 2023; CMS disrupted the 2022 measurement cycle during COVID). This is the recommended primary year filter. |
| performance_year | int | The measurement/data-collection year the cutpoints score. Deterministically = rating_year - 2 in every row (e.g. RY2025 -> performance_year 2023). Fully derivable from rating_year; carries no independent information. |
| payment_year | int | The MA payment year tied to the ratings. Deterministically = rating_year in every row. Redundant with rating_year. |
| is_current | boolean | Whether this is the live/current version of the cutpoint. 100% TRUE for all 1,815 rows - no superseded/historical versions are retained, so this column is effectively a no-op today (but exists to support future versioning alongside calculation_epoch/cms_vintage_sequence). |
| cms_vintage_sequence | int | Sequence number for multiple CMS vintages of the same rating year (1 = first/original release). CONSTANT 1 for all rows - no year has a second vintage yet. Increments if CMS republishes corrected cutpoints for a year. |
| qbp_payment_year | int |  |

Tools that read it: get_stars_cutpoints

Query it: `query_substrate` with `SELECT ... FROM medicare_silver.stars_cutpoints WHERE ... LIMIT 100`; read `describe_data_source("medicare_silver.stars_cutpoints")` first.
