Count Federal Public Housing Assistance receipt in Lifeline categorical eligibility - #9378
Conversation
…al eligibility 47 CFR 54.409(a)(2) lists Federal Public Housing Assistance as a categorical qualifying program, but the Lifeline list covered only Medicaid, SNAP and SSI. Add receives_housing_assistance so households reporting Section 8, public housing or project-based rental assistance qualify regardless of income. ACP inherits the change through the shared list. Fixes PolicyEngine#9376 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rd programs 47 CFR 54.409(b) makes the Tribal-specific list additive: a consumer on Tribal lands qualifies through paragraph (a) or through a Tribal program. The formulas swapped the lists instead, denying the standard route to Tribal households. Fix both is_lifeline_eligible and is_acp_eligible, and flip the two tests that had locked the swap in. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…into lifeline-fpha-categorical
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9378 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 3 2 -1
Lines 46 36 -10
=========================================
- Hits 46 36 -10
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…r Lifeline 47 CFR 54.409(b) lists Bureau of Indian Affairs General Assistance as a Tribal qualifying program. The model has no BIA-specific variable, so agency cash aid reported under general_assistance by a household on Tribal land stands in for it (25 CFR 20.300-20.303). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tance for Lifeline" This reverts commit 34b33d6.
The middle household lives on Tribal land and is enrolled in Medicaid, so under 47 CFR 54.409(b) it is eligible. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
DTrim99
left a comment
There was a problem hiding this comment.
Review — PR #9378: FCC Lifeline/ACP categorical eligibility
Add Federal Public Housing Assistance (FPHA) as a Lifeline/ACP categorical-eligibility
route and fix Tribal eligibility from exclusive to additive.
Headline: Both changes are regulatorily verified correct against 47 CFR §54.409, and
CI is green (33/33). There are no critical findings. The should-address items are
citation-precision and ACP test coverage — none of them block correctness.
Program review
Two changes, both in the FCC federal rule tree (gov/fcc/...):
-
FPHA categorical eligibility. Adds the pre-existing
receives_housing_assistance
(bool, SPMUnit;variables/gov/hud/receives_housing_assistance.py) to the non-tribal
list ingov.fcc.lifeline.categorical_eligibility, encoding §54.409(a)(2)'s "Federal
Public Housing Assistance". The variable is reused, not reinvented, and is already the
accepted FPHA proxy elsewhere in the model (LIHEAP, CT TFA, RI Works, CA OC general
relief). Becauseis_acp_eligible.pyreads the same Lifeline list, FPHA flows into ACP
automatically — regulatorily correct (47 U.S.C. §1752(a)(6)(A) qualifies a consumer who
participates in a Lifeline-qualifying program). -
Tribal-additive fix. Replaces the exclusive
np.where(is_on_tribal_land, tribal>0, non_tribal>0)with the additive
(non_tribal>0) | (is_on_tribal_land & (tribal>0))in BOTHis_lifeline_eligible.py
andis_acp_eligible.py. The old exclusive form was a genuine pre-existing bug: a
Tribal-land household enrolled in a standard program (Medicaid/SNAP/SSI/FPHA) read ONLY
the Tribal list and was wrongly denied. The new form encodes §54.409(b) exactly — meets
(a) OR participates in a Tribal-specific program — and correctly guards the Tribal branch
withis_on_tribal_land &so off-reservation households are not granted eligibility via
the Tribal-only list.
Source documents
- 47 CFR §54.409 — Consumer qualification for Lifeline. Verified via eCFR
(versioner 2026-01-01). §54.409(a)(2) enumerates exactly five program-based routes:
Medicaid; SNAP; SSI; Federal Public Housing Assistance; Veterans and Survivors Pension
Benefit. §54.409(b) makes the Tribal list additive to (a), not a replacement. Both changes
are corroborated by the confirmed regulatory text. - 47 U.S.C. §1752 — ACP statute; a Lifeline-qualifying program qualifies a consumer for
ACP, so the §54.409(b) rule and the FPHA route both carry over to ACP correctly.
Critical
None.
Note on reclassification: the test-coverage review initially flagged two ACP-coverage items
as CRITICAL (the ACP Tribal-additive fix guarded only by a monkeypatched unit test, and the
FPHA→ACP flow untested). Per the review rules, "missing edge-case tests for an
already-tested variable" is SHOULD ADDRESS, not CRITICAL: is_acp_eligible is covered by
test_vectorization.py, and the regulatory review confirms the ACP logic is correct — so
there is no zero-coverage formula and no confirmed defect. Both items are downgraded to
SHOULD ADDRESS below.
Should address
1. categorical_eligibility.yaml reference is section-level, not (a)(2) (reference precision)
parameters/gov/fcc/lifeline/categorical_eligibility.yaml carries a valid structured
title/href dict citing §54.409, and it corroborates the whole list — but it stops at the
section, not the (a)(2) subsection where the five-program list (including FPHA) actually
lives. Tighten the title, e.g.:
title: 47 CFR § 54.409(a)(2) - Program-based qualification (Federal Public Housing Assistance).
The Cornell href already resolves; no URL-health issue.
2. §54.409(b) Tribal-additive basis is comment-only — not in any structured reference (reference precision)
The substantive logic change encodes §54.409(b), but that basis is cited only in inline code
comments (and the changelog):
is_lifeline_eligible.py:referenceis section-level §54.409 (contains (b), but does
not pinpoint the subsection).is_acp_eligible.py:referencecites only 47 U.S.C. §1752 and does not reference
§54.409 at all, despite now running its (b) logic.
Add a §54.409(b) CFR reference to the bare-string ref list in both variables (bare strings
may be a list), e.g."https://www.law.cornell.edu/cfr/text/47/54.409#b".
3. ACP Tribal-additive fix has no end-to-end YAML test (downgraded from CRITICAL)
The ACP formula change is guarded only by
test_vectorization.py::test_acp_lifeline_categorical_eligibility_is_vectorized, which uses
a monkeypatched fake parameter tree and fake_add. It exercises the boolean algebra but
bypasses the real parameter list and add()/entity plumbing, so a parameter-list regression
would slip through. Add a YAML case to acp/is_acp_eligible.yaml for a Tribal-land household
that qualifies via a standard (non-tribal) Lifeline program (e.g. Medicaid) above 200% FPG —
is_acp_eligible: true. This case fails under the old exclusive np.where.
4. FPHA→ACP flow is untested (downgraded from CRITICAL)
FPHA now flows into ACP via the shared Lifeline list, but there is no test — not in
is_acp_eligible.yaml, not in integration.yaml, and not in the Python unit test (whose
fake tree hardcodes the Lifeline list as ["medicaid_enrolled"]). Add a YAML case to
acp/is_acp_eligible.yaml: receives_housing_assistance: true above 200% FPG →
is_acp_eligible: true. Fails before FPHA was added to the list.
5. No FPHA negative control in Lifeline
The Lifeline suite proves FPHA → eligible but has no paired control showing the SAME
above-135%-FPG household WITHOUT receives_housing_assistance is ineligible. The existing
"no categorical eligibility >135% FPG is ineligible" case is close but does not set
receives_housing_assistance: false. Either add that input to the existing case, or add a
control mirroring the new lifeline.yaml $60k case with receives_housing_assistance: false
and is_lifeline_eligible: false. Related hardening: two control cases (the Lifeline
"no categorical eligibility" and "Tribal + no categorical eligibility" cases) do not zero the
new inputs (snap, ssi, receives_housing_assistance), so a future default-input change
could silently flip them eligible via FPHA.
Suggestions
- Veterans & Survivors Pension Benefit (follow-up). §54.409(a)(2)'s fifth program-based
route remains unimplemented — a clearly-labeled in-file comment in
categorical_eligibility.yaml. This is a pre-existing, documented gap the PR does not
worsen (the PR is net-additive), and there is no modeled VA-pension-receipt input to wire
up today. Track as a follow-up issue (add an upstream input, then append it here); do not
block this PR. - Deep-link anchors. Cornell CFR pages support subsection anchors (
#a_2,#b) so a
click lands on the exact provision. Minor polish. - Optional FR provenance. eCFR CITA shows §54.409 amended through 88 FR 84447 (Dec 5
2023) and 89 FR 70124 (Aug 29 2024); a Federal Register cite could be added if desired.
Not required — the standing CFR text is authoritative. - Optional documentation. A one-line comment in
is_acp_eligible.pynoting the Lifeline
categorical list (incl. FPHA) is intentionally inherited would make the ACP side-effect
explicit. - Pre-existing code tidiness (not introduced).
is_acp_eligible.pystill computes its
own ACP list vianp.any([add(...) for ...], axis=0)while the edited Lifeline block uses
the cleaneradd(...) > 0; a future cleanup could align them.npis now unused in
is_lifeline_eligible.py(no lint impact — F401 ignored). No action needed.
Validation summary
- CI: 33/33 green.
- Both regulatory changes verified correct against the eCFR text of §54.409(a)(2) and (b).
- FPHA path (Lifeline) is well-pinned at both unit (
is_lifeline_eligible.yaml) and
integration (lifeline.yaml: MA, $60k, housing assistance → full $9.25×12) layers, and
fails under old code. - Tribal-additive fix (Lifeline) is pinned by YAML that flips
false→trueunder the fix. - Code change is fully vectorized, identical across both files, correctly parenthesized;
entity levels consistent; no hard-coded values; changelog.fixedfragment present and
cites §54.409(a)(2) and (b). - Gaps are ACP end-to-end coverage (items 3–4) and Lifeline FPHA negative control (item 5).
Review severity
REQUEST_CHANGES — 0 critical, but several should-address items (2 citation-precision,
3 test-coverage). Per the standing rule, any should-address item maps to request-changes.
The correctness of both changes is not in question and CI is green; the requested changes are
reference precision and ACP test coverage.
Counts: 0 critical / 5 should-address / 5 suggestions.
Next steps
Run /fix-pr 9378 to apply the should-address items: tighten the two §54.409 references
(item 1–2), add the two ACP YAML cases (items 3–4), and add the Lifeline FPHA negative
control plus zero the new inputs on the two control cases (item 5). Open a follow-up issue
for the Veterans & Survivors Pension route.
🤖 Generated with Claude Code /review-program
…controls - Cite 47 CFR 54.409(a)(2) on the Lifeline categorical list and 54.409(b) on is_lifeline_eligible and is_acp_eligible. - Add ACP YAML cases for a Tribal-land household qualifying through Medicaid and for the FPHA route. - Zero the new inputs on the Lifeline no-categorical-eligibility controls and add a no-housing-assistance mirror of the $60k integration case. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Program Review (re-review) — FCC Lifeline FPHA categorical eligibilitySource
Response to prior reviewThe author pushed commit
Critical (Must Fix)None. The two formula variables ( Should Address
Suggestions
Validation Summary
Branch Status⚠ PR branch is 15 commits behind main. Consider rebasing before merging. Review was scoped to the PR's actual changes — staleness did not affect findings. Review Severity: APPROVENo critical findings. FPHA is correctly modeled as a §54.409(a)(2) base qualifier, the Tribal OR-logic fix is regulatorily correct and provably non-regressive, and all four of the prior review's blocking test/citation gaps (Items 1, 3, 4, 5) are resolved. The two remaining should-address items are minor and non-blocking: a supplementary CFR pinpoint on the ACP variable (residual of Item 2) and an explicit-zero on one ACP negative control. Recommend approving with those two as follow-ups. 🤖 /review-program |
DTrim99
left a comment
There was a problem hiding this comment.
Approving — the prior blocking items (regulatory correctness, the FPHA→ACP and Tribal-additive end-to-end tests, and the Lifeline FPHA negative control) are resolved. The two remaining should-address items (a supplementary §54.409(a)(2) pinpoint on the ACP variable, and an explicit receives_housing_assistance: false on one ACP control) are minor, non-blocking follow-ups. Full findings posted above. 🤖 /review-program
Summary
Adds
receives_housing_assistancetogov.fcc.lifeline.categorical_eligibilityso households reporting Federal Public Housing Assistance (Section 8 Housing Choice Vouchers, public housing, project-based rental assistance) qualify for Lifeline regardless of income, per 47 CFR § 54.409(a)(2).Fixes #9376
Fixes #9385
Background
The regulation lists five categorical qualifying programs: Medicaid, SNAP, SSI, Federal Public Housing Assistance, and the Veterans and Survivors Pension. The list covered only the first three. Reproduced in the household API: a single adult at $60k with
receives_housing_assistance: truereturnedlifeline = 0, while the same household withreceives_snap: truereturned 111.Design notes
period: monthlist is fine.medicaid_enrolledis already YEAR-defined and in the list;is_lifeline_eligibleis a YEAR variable that sums each entry over the year withadd. Verified locally: the $60k case returns 111 after the change and 0 without the flag.housing_assistancedeliberately not added. It is positive for any renter under 80% AMI with takeup defaulted to true, and vouchers are not an entitlement, so a modeled amount would auto-qualify renters well above 135% FPG. Reported receipt is the only receipt signal in the model.is_acp_eligiblewidens correspondingly for the years ACP was in effect. Correct under 47 U.S.C. § 1752(a)(6).Tribal households (#9385, review follow-up)
Review pointed out that the new Tribal test locked in a pre-existing bug. 47 CFR § 54.409(b) makes the Tribal-specific list additive: a consumer on Tribal lands qualifies through paragraph (a) or through a Tribal program.
is_lifeline_eligibleandis_acp_eligibleusedwhere(is_on_tribal_land, tribal > 0, non_tribal > 0), which swapped the lists and denied the standard route to Tribal households. Both formulas now readnon_tribal > 0 | (is_on_tribal_land & tribal > 0).Test changes: the Tribal SSI case and the new Tribal housing case flip to eligible, the Tribal "no categorical eligibility" case now also zeros SNAP, SSI and Medicaid since the standard route is read, and the ACP vectorization test expects the Tribal Medicaid household to be eligible.
Files
parameters/gov/fcc/lifeline/categorical_eligibility.yaml— one entryvariables/gov/fcc/lifeline/is_lifeline_eligible.py,variables/gov/fcc/acp/is_acp_eligible.py— Tribal list is additive per 54.409(b)tests/policy/baseline/gov/fcc/lifeline/is_lifeline_eligible.yaml— reported receipt above 135% FPG qualifies, for non-Tribal and Tribal householdstests/policy/baseline/gov/fcc/lifeline/lifeline.yaml— the partner's $60k MA case pays 9.25 × 12changelog.d/lifeline-fpha-categorical.fixed.mdTest plan
🤖 Generated with Claude Code