> For the complete documentation index, see [llms.txt](https://docs.dataplex-consulting.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.dataplex-consulting.com/data-catalog/cms-nh-compliance-dataset/methodology-flags.md).

# Flag Methodology

This page documents exactly how each of the five computable compliance flags (and the `operational_stress_indicator_count` composite) is calculated in the Nursing Home Compliance Intelligence dataset: the formula as implemented, the threshold values it reads, what makes a value evaluable, and what the flag cannot see. It is written for a buyer who needs to cite the product in a diligence memo, an underwriting model, or a compliance review with confidence.

## Signal, not prediction

Every flag in this product is a **published, deterministic formula computed over CMS's own data**. A flag is a signal about what the federal record shows, never a prediction about what a facility will do, and never a judgment about the quality of care. The formulas are fixed, the thresholds are versioned in a published seed, and every result carries the evidence needed to reproduce it. We date what CMS published and we quote what the record says; we do not infer, score, or forecast.

The flags live on the `FACILITY_MONTH` table, one set per facility (CCN) per observed month.

### The 0 / 1 / NULL contract

Every flag takes exactly one of three values:

| Value  | Meaning                                                                                       |
| ------ | --------------------------------------------------------------------------------------------- |
| `1`    | The condition is met, on the evidence available for this facility-month.                      |
| `0`    | The condition is **not** met, and we had enough evidence to say so.                           |
| `NULL` | **Not evaluable**: the inputs needed to decide were missing, suppressed, or outside coverage. |

**`NULL` is never a silent `0`.** A facility that never reported payroll staffing for a quarter gets `NULL` on the staffing flag, not `0`, because "we could not evaluate this" is a different statement from "we evaluated this and found no shortfall." Confusing the two is the single most common way compliance signals get misread, so we keep them structurally distinct. Every flag is therefore paired with two companion columns:

* `<flag>_reason`: a compact code explaining the value (why it is 1, why it is 0, or why it is NULL).
* `<flag>_inputs_coverage`: a boolean. Were the inputs this flag needs actually present for this facility-month?

Every flag row also stamps `method_version` (currently `v1`), so a recomputed number can always be tied back to the formula and thresholds that produced it.

### Thresholds are seed-versioned

Every numeric threshold below comes from a published threshold seed, keyed by `threshold_name` and carrying its own `method_version`. Changing a threshold is a versioned change to the seed, not an edit buried in query logic. The `v1` values are the pre-registered defaults.

| threshold\_name                               | Value  | Used by                                 |
| --------------------------------------------- | ------ | --------------------------------------- |
| `staffing_shortfall_hprd_ratio`               | `0.85` | staffing\_shortfall\_flag               |
| `repeat_deficiency_min_tag_occurrences`       | `3`    | repeat\_deficiency\_flag                |
| `ownership_disclosure_min_disclosed_owners`   | `1`    | ownership\_disclosure\_gap\_flag        |
| `enforcement_escalation_fine_ratio`           | `1.5`  | enforcement\_escalation\_flag           |
| `closure_signal_precision_min`                | `0.90` | deactivation\_signal\_flag (audit gate) |
| `pbj_census_decline_gt20pct_yoy`              | `20`   | composite component 4                   |
| `chow_within_months`                          | `12`   | composite component 5                   |
| `operational_stress_min_evaluable_components` | `4`    | composite NULL semantics                |

***

## Flag 1: `staffing_shortfall_flag`

**What it means:** the facility's payroll-based reported nurse staffing for the quarter fell materially below what CMS's own case-mix model expects for that facility.

**Formula (as implemented):** on `FACILITY_MONTH`, the facility-month's calendar quarter is joined to its `STAFFING_COMPLIANCE` row. Then:

```
IF   pbj_submission_status = 'reported_full'
 AND pbj_total_nurse_hprd IS NOT NULL
 AND case_mix_expected_total_nurse_hprd IS NOT NULL
THEN 1 if  pbj_total_nurse_hprd < 0.85 * case_mix_expected_total_nurse_hprd
     else 0
ELSE NULL
```

**Inputs:**

* `pbj_total_nurse_hprd`: total nurse hours per resident day for the quarter, from the Payroll Based Journal (PBJ). HPRD = (RN + LPN + CNA hours, employee + contract, summed across the quarter) ÷ resident-days, where resident-days is the sum of daily census. It is `NULL` when no resident-days were reported, never `0`.
* `case_mix_expected_total_nurse_hprd`: CMS's case-mix-adjusted expected total nurse HPRD, passed through verbatim from the provider-information snapshot inside the quarter. This is the baseline; the flag is a comparison against CMS's own expectation, not an external standard.
* `pbj_submission_status`: `reported_full` requires that the quarter's days are substantially present in PBJ; otherwise `partial` or `missing`.

**Evaluability:** the flag is only evaluable when `pbj_submission_status = 'reported_full'`. If PBJ is `partial`, `missing`, or the HPRD/case-mix inputs are suppressed, the flag is `NULL` and `staffing_shortfall_inputs_coverage = FALSE`.

**Reason codes:**

| Value  | `staffing_shortfall_reason`                                                                  |
| ------ | -------------------------------------------------------------------------------------------- |
| `1`    | `below_casemix_x_ratio`                                                                      |
| `0`    | `at_or_above_expected`                                                                       |
| `NULL` | `not_evaluable_pbj_<status>` (e.g. `not_evaluable_pbj_partial`, `not_evaluable_pbj_missing`) |

**Worked example.** A facility reports PBJ for a quarter as `reported_full`. Its total nurse HPRD works out to 3.10, and CMS's case-mix expected total nurse HPRD for the facility is 3.85. The threshold ratio is 0.85, so the shortfall line is 0.85 × 3.85 = 3.27. Because 3.10 < 3.27, `staffing_shortfall_flag = 1`, reason `below_casemix_x_ratio`, and all three months of that quarter carry the value on `FACILITY_MONTH`. A neighboring facility whose PBJ that quarter was only `partial` gets `NULL` with reason `not_evaluable_pbj_partial`, not a `0`, because its staffing simply cannot be judged.

**Limitations:**

* PBJ is quarterly and lags roughly two quarters, so the same quarterly value repeats across all three months of the quarter on `FACILITY_MONTH`.
* The comparison is against CMS's case-mix expectation, not any statutory minimum. The rescinded April-2024 federal HPRD minimum appears nowhere in this product.
* A ratio below 0.85 is a reported-hours signal, not a finding about staffing adequacy or care.

***

## Flag 2: `repeat_deficiency_flag`

**What it means:** the same health-deficiency tag has been cited at this facility across enough separate standard surveys to constitute a recurring pattern rather than a one-off.

**Formula (as implemented):** built from `ENFORCEMENT_EVENTS`, restricted to standard-survey health deficiencies (`event_type = 'health_deficiency'` and `standard_deficiency` in {Y, YES, TRUE, 1, T}). For each facility, the same tag is followed across its **distinct standard-survey dates**, keyed on `(ccn, tag)`, **regardless of scope/severity**. Splitting a tag by severity would dilute true recurrence, so a tag re-cited at a different severity still counts toward the same series. Per facility:

* `repeat_hit_month` = the earliest `first_reported_month` at which a tag reaches its **Nth distinct standard-survey date** (N = `repeat_deficiency_min_tag_occurrences`, default 3).
* `first_std_def_month` = the earliest month any standard health deficiency was reported.

Then on each facility-month:

```
IF   first_std_def_month IS NULL OR first_std_def_month > observed_month
THEN NULL                    -- no standard-survey coverage observed yet
ELSE 1 if repeat_hit_month IS NOT NULL AND repeat_hit_month <= observed_month
     else 0
```

**Evaluability:** `NULL` until the facility has an observed standard survey as of the month in question (`repeat_deficiency_inputs_coverage` requires `first_std_def_month` present and reached). This prevents a facility that simply has not been surveyed yet from reading as "no repeats."

**Reason codes:**

| Value  | `repeat_deficiency_reason`    |
| ------ | ----------------------------- |
| `1`    | `tag_recurred_ge_n_surveys`   |
| `0`    | `no_qualifying_repeat`        |
| `NULL` | `no_standard_survey_coverage` |

**Worked example.** A facility is cited for deficiency tag F-684 (quality of care) on three separate standard-survey dates (say 2022-05, 2023-06, and 2024-07) even though the scope/severity differed across them. Counting distinct survey dates for `(ccn, F-684)`, the third distinct date reaches N = 3, and its `first_reported_month` is, say, 2024-09. From September 2024 onward, `repeat_deficiency_flag = 1` (reason `tag_recurred_ge_n_surveys`); for every month before that the flag is `0` (the facility had standard-survey coverage but had not yet accumulated three distinct survey dates for the same tag).

**Limitations (read carefully; this is a deliberate v1 simplification):**

* The threshold is **three distinct standard-survey dates citing the same tag**, counted regardless of scope/severity. It is **not** a check that the surveys were literally consecutive with no clean survey in between; the flag is *recurring*, not necessarily consecutive. A facility cited for the same tag on three separate surveys years apart, with clean surveys between them, meets the condition.
* Because severity is not part of the series key, the same tag cited at two different severities counts toward one recurring series, not two.
* Only standard-survey health deficiencies count; complaint-only and fire-safety deficiencies do not drive this flag.

***

## Flag 3: `ownership_disclosure_gap_flag`

**What it means:** for a month inside PECOS ownership coverage, the facility's federal ownership disclosure is either empty, points to another organization with no further disclosure, or (from the facility's most recent PECOS vintage forward) dead-ends in an undisclosed upstream owner.

**Formula (as implemented):** per PECOS vintage month, from the curated PECOS ownership data, we compute `disclosed_owner_count` (distinct owners holding an ownership interest) and `has_owned_by_another` (any owner flagged owned-by-another-org-or-individual). Separately we carry `has_undisclosed_upstream_owner`, the current-state, facility-level dead-end measure (the same figure FacilityGuard reports). Then:

```
IF   NOT in_pecos_coverage  OR  pecos_prev_spans_gap  THEN NULL   -- outside coverage / gap vintage
IF   disclosed_owner_count IS NULL                     THEN NULL
ELSE 1 if  disclosed_owner_count < 1
       OR  has_owned_by_another
       OR  (has_undisclosed_upstream_owner AND observed_month >= latest_pecos_vintage_month)
     else 0
```

`ownership_disclosure_min_disclosed_owners = 1`, so `disclosed_owner_count < 1` means zero disclosed owners while enrolled.

**Evaluability:** `NULL` for any month before PECOS interval coverage begins (Feb 2023) and for gap vintages (`ownership_disclosure_gap_inputs_coverage` requires PECOS coverage, a non-gap previous vintage, and a non-null owner count). Ownership disclosure gaps are never inferred outside the window where CMS actually publishes the interval data.

**Reason codes.** For a `1`, the reason is a pipe-composed code naming which trigger(s) fired: any of `low_disclosed|`, `owned_by_another|`, `undisclosed_upstream_current|`:

| Value  | `ownership_disclosure_gap_reason`                                                           |
| ------ | ------------------------------------------------------------------------------------------- |
| `1`    | pipe-composed, e.g. `owned_by_another\|` or `low_disclosed\|undisclosed_upstream_current\|` |
| `0`    | `owners_disclosed`                                                                          |
| `NULL` | `outside_pecos_coverage_or_gap`                                                             |

**Worked example.** For a non-gap PECOS vintage inside coverage, a facility has two disclosed owners, but one is flagged as owned by another organization whose own upstream owner is not disclosed to CMS. `disclosed_owner_count = 2`, but `has_owned_by_another = TRUE`, so `ownership_disclosure_gap_flag = 1` with reason `owned_by_another|`. For a vintage that CMS did not publish (a gap month), the same facility carries `NULL` with reason `outside_pecos_coverage_or_gap`.

**Limitations:**

* The flag fires on **three** conditions: zero disclosed owners, owned-by-another, **or** the current-state `has_undisclosed_upstream_owner` dead-end.
* `has_undisclosed_upstream_owner` is a **current-state** measure. It therefore contributes to the flag **only from the facility's most recent observed PECOS vintage month forward**; it is never back-dated onto earlier vintages. A facility that dead-ends today does *not* read as a disclosure gap for months before that dead-end was observed (the per-vintage triggers still apply to those earlier months).
* Self-reported disclosure is a floor, not a census: absence of a disclosed owner is a gap in the federal record, not proof of no owner.

***

## Flag 4: `enforcement_escalation_flag`

**What it means:** the facility's federal monetary penalties escalated sharply from one penalty year to the next.

**Formula (as implemented):** from `ENFORCEMENT_EVENTS`, penalty events (`event_type = 'penalty'`) are summed into an annual fine total per `(ccn, YEAR(event_date))`. Across those annual totals, ordered by year, the prior observed penalty year's total is compared. Per facility:

* `escalation_month` = the earliest January-1 of a year whose fine total ≥ `1.5 ×` the prior observed penalty year's total, where the prior total was > 0.
* `observed_fine_years` = the count of distinct penalty years observed.

Then on each facility-month:

```
IF   observed_fine_years < 2   THEN NULL          -- fewer than two cycles to compare
ELSE 1 if escalation_month IS NOT NULL AND escalation_month <= observed_month
     else 0
```

**Evaluability:** `NULL` until at least two penalty years have been observed for the facility (`enforcement_escalation_inputs_coverage = observed_fine_years >= 2`).

**Reason codes:**

| Value  | `enforcement_escalation_reason`  |
| ------ | -------------------------------- |
| `1`    | `fine_total_escalated_x_ratio`   |
| `0`    | `no_escalation`                  |
| `NULL` | `fewer_than_two_observed_cycles` |

**Worked example.** A facility has penalty fine totals of $12,000 in 2022 and $31,500 in 2023. 31,500 ≥ 1.5 × 12,000 = 18,000, so `escalation_month = 2023-01-01`. From January 2023 onward, `enforcement_escalation_flag = 1` (reason `fine_total_escalated_x_ratio`); for months in 2022 it is `0` (two years were not yet both observable). A facility with penalties in only one year carries `NULL` (reason `fewer_than_two_observed_cycles`).

**Limitations (v1 is narrower than a literal reading of the definition):**

* "Cycle" is implemented as a **calendar year of penalties**, not a survey cycle. The comparison is year-over-year fine totals.
* Only **fine totals** drive escalation. A scope/severity-mix escalation path is **not** implemented in `v1`; a facility whose citations grew more severe without a 1.5× fine increase does not flag here.
* The comparison uses adjacent *observed* penalty years. If a facility had penalties in 2021 and 2024 but not 2022–2023, those two years are treated as adjacent for the ratio.

***

## Flag 5: `deactivation_signal_flag`

**What it means:** an observed, fixed-rubric closure-type signal fired for the facility: it disappeared from the snapshots (across adjacent months), a certification termination was recorded in the Provider of Services file, or its certified beds went to zero.

**Formula (as implemented):** from `CLOSURE_SIGNALS`, per facility we take the earliest observed signal month and the earliest pending-confirmation signal month. Then:

```
IF   first_observed_signal_month IS NOT NULL AND <= observed_month           THEN 1
IF   first_pending_signal_month  IS NOT NULL AND <= observed_month
 AND (first_observed_signal_month IS NULL OR > observed_month)               THEN NULL
ELSE 0
```

**Closure-signal rubric (`CLOSURE_SIGNALS`, observed-only):**

* `snapshot_disappearance` (top tier): present at the previous *available* provider-information vintage, absent at this one, and the two vintages are **adjacent** (no gap between them). A disappearance across a data gap is unattributable and emits nothing.
* `pos_termination` (corroborating): a Provider of Services certification termination.
* `bed_count_zero` (corroborating): certified beds transition from > 0 to 0.

A signal within CMS's official change-of-ownership publication lag, with no official CHOW yet explaining it, is held at `signal_status = 'pending_confirmation'`; it cannot yet be distinguished from a change-of-ownership re-enrollment. During that window the flag is `NULL`, not `1`.

**Evaluability:** `deactivation_signal_inputs_coverage` is always `TRUE`: a facility present in the snapshots is always evaluable for whether a signal has fired. Absence of a signal is a genuine `0`, not a coverage gap.

**Reason codes:**

| Value  | `deactivation_signal_reason` |
| ------ | ---------------------------- |
| `1`    | `observed_closure_signal`    |
| `0`    | `no_signal`                  |
| `NULL` | `pending_confirmation`       |

**Worked example.** A facility appears in one provider-information snapshot and is absent from the adjacent next snapshot, with no official CHOW on file. During the publication-lag window the signal is `pending_confirmation`, so `deactivation_signal_flag = NULL`. Once the window passes with no CHOW explanation, the signal becomes `observed` and the flag reads `1` (reason `observed_closure_signal`) from that month forward.

**Limitations:**

* **Termination is not physical closure.** A certification termination or a snapshot disappearance is a change in the federal record; the building may still operate under a new CCN, a new owner, or a different program. This is a signal about the record, not about the facility's doors.
* The top signal tier (`snapshot_disappearance`) is subject to a 30-facility precision audit (`closure_signal_precision_min = 0.90`). If precision falls below 0.90 the top tier is excluded from delivery until it clears the audit.

***

## Composite: `operational_stress_indicator_count`

**What it means:** a simple count, 0–5, of how many of five fixed operational-stress components fired for a facility-month. It is deliberately named a *count of indicators*, not a "distress score" or "closure risk", because that is exactly what it is. It is a count, not a prediction.

**Components (exactly five, equal weight):**

1. `staffing_shortfall_flag = 1`
2. `enforcement_escalation_flag = 1`
3. `sff_or_abuse_icon`: Special Focus Facility / SFF-candidate status, **or** the abuse icon set, in the month's snapshot. Always evaluable.
4. `pbj_census_decline_gt20pct_yoy`: PBJ average daily census down more than 20% versus the same quarter a year earlier. `NULL` unless **both** quarters are `reported_full`; never a silent `0`.
5. `chow_within_12m`: this facility has an official, confirmed change-of-ownership with an effective date within the trailing 12 months. Always evaluable.

**Two published columns, plus the count:**

* `stress_indicators_evaluated` (0–5) is the denominator: how many of the five components were evaluable this month. Components 3 and 5 are always evaluable, so this is always at least 2.
* `operational_stress_indicator_count` (0–5) is the numerator (fired components), **but NULL unless at least `operational_stress_min_evaluable_components = 4` of the 5 components were evaluable.** A count built on too few evaluable inputs is not published as a number.
* `stress_indicator_reason`: either `insufficient_evaluable_components`, or a pipe-delimited code of which components fired, using the tokens `STAFF|`, `ENF|`, `SFF|`, `PBJDECL|`, `CHOW12|`.

**Formula (as implemented):**

```
stress_indicators_evaluated =
      (staffing_shortfall_flag IS NOT NULL)      -- comp 1
    + (enforcement_escalation_flag IS NOT NULL)  -- comp 2
    + 1                                          -- comp 3 always evaluable
    + (pbj_census_decline_gt20pct_yoy IS NOT NULL) -- comp 4
    + 1                                          -- comp 5 always evaluable

stress_raw_count =
      COALESCE(staffing_shortfall_flag, 0)
    + COALESCE(enforcement_escalation_flag, 0)
    + sff_or_abuse_icon
    + COALESCE(pbj_census_decline_gt20pct_yoy, 0)
    + chow_within_12m

operational_stress_indicator_count =
    stress_raw_count  IF stress_indicators_evaluated >= 4  ELSE NULL
```

**Worked example.** In a given month a facility has: `staffing_shortfall_flag = 1` (PBJ was `reported_full` and below the case-mix line); `enforcement_escalation_flag = 0` (two penalty years observed, no 1.5× jump); `sff_or_abuse_icon = 1` (SFF status in the snapshot); `pbj_census_decline_gt20pct_yoy = 0` (both quarters `reported_full`, census down only 6%); and `chow_within_12m = 0` (no confirmed CHOW). All five components are evaluable, so `stress_indicators_evaluated = 5` and `operational_stress_indicator_count = 2`, with reason `STAFF|SFF|`. Now take a facility where PBJ was `partial` (component 1 NULL) *and* the prior-year PBJ quarter was `missing` (component 4 NULL): only components 2, 3, and 5 are evaluable, `stress_indicators_evaluated = 3`, which is below 4, so `operational_stress_indicator_count` is `NULL` with reason `insufficient_evaluable_components`, even though some components fired.

**Limitations:**

* The count is an unweighted tally of five specific, published components. It is not calibrated to any outcome and must not be read as a probability, a grade, or a ranking of care quality.
* Because components 4 (census decline) and 1 (staffing) depend on PBJ, facility-months outside the PBJ coverage window are more likely to fall below the 4-of-5 evaluability floor and read as `NULL`. A `NULL` count means "not enough evaluable inputs," not "no stress."
* Component 5 (`chow_within_12m`) is treated as always evaluable: a facility with no CHOW on file contributes `0`, never `NULL`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.dataplex-consulting.com/data-catalog/cms-nh-compliance-dataset/methodology-flags.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
