Context
The Child Poverty Impact Dashboard is adding a "Make refundable" checkbox for states whose EITC is nonrefundable (SC, MO, OH, UT), wired to the gov.contrib.states.{st}.child_poverty_impact_dashboard.eitc reforms. Two upstream gaps currently block enabling that feature. The dashboard gates each state behind a refundable_ready flag (all false today) until this is resolved.
Gap 1 — MO/OH/UT refundability reforms are broken
The three refundability reforms have two bugs:
a) add() path-string crash. Their *_refundable_credits.formula calls:
add(tax_unit, period, "gov.states.mo.tax.income.credits.refundable")
add() expects a List[str] of variable names, not a parameter-path string. PE-core iterates the string character-by-character, get_variable("g") returns None, and the sim raises AttributeError: 'NoneType' object has no attribute 'entity'. Net effect: household_net_income silently collapses to 0 under the reform.
b) Zero-refund bug. They pay the post-cap applied credit (mo_wftc / ut_eitc / oh_eitc) instead of the *_potential (uncapped-at-liability) amount — so exactly the zero-liability filers refundability is meant to help get $0.
Files:
policyengine_us/reforms/states/mo/eitc/mo_refundable_eitc_reform.py (~line 59)
policyengine_us/reforms/states/ut/child_poverty_eitc/ut_fully_refundable_eitc_reform.py
policyengine_us/reforms/states/oh/eitc/oh_refundable_eitc_reform.py
Fix PRs are already open and need review + merge + a release: MO #8642, UT #8645, OH #8657.
Gap 2 — SC has no full-refundability contrib reform
sc_eitc is nonrefundable (in gov.states.sc.tax.income.credits.non_refundable, 2021+) — a 125% federal match capped at $200/filer from 2026. SC only has the unrelated H.3492 partial reform (gov.contrib.states.sc.h3492, which refunds 25% of the excess over liability), not a full conversion.
Request: add a new contrib reform mirroring MO/UT:
- Factory
create_sc_refundable_eitc under policyengine_us/reforms/states/sc/....
- Parameters
gov.contrib.states.sc.child_poverty_impact_dashboard.eitc.{in_effect, match}.
- Make
sc_eitc fully refundable (pay sc_eitc_potential; move it from the non-refundable to the refundable credits list).
- Use the corrected
add(<resolved list>) pattern — resolve the parameter to its variable-name list first; do not reintroduce the path-string bug from Gap 1.
Dashboard coordination
The dashboard reads a per-state refundable_ready flag (in frontend/data/eitc-reforms.json), currently false for SC/MO/OH/UT, so the refundability checkboxes stay greyed. Once a policyengine-us release ships with the MO/UT/OH fixes and the new SC reform, we flip refundable_ready=true per state and bump the dashboard's pin. (SC's $200 EITC-cap control is a plain baseline lever and ships independently — no dependency on this issue.)
Context
The Child Poverty Impact Dashboard is adding a "Make refundable" checkbox for states whose EITC is nonrefundable (SC, MO, OH, UT), wired to the
gov.contrib.states.{st}.child_poverty_impact_dashboard.eitcreforms. Two upstream gaps currently block enabling that feature. The dashboard gates each state behind arefundable_readyflag (allfalsetoday) until this is resolved.Gap 1 — MO/OH/UT refundability reforms are broken
The three refundability reforms have two bugs:
a)
add()path-string crash. Their*_refundable_credits.formulacalls:add()expects aList[str]of variable names, not a parameter-path string. PE-core iterates the string character-by-character,get_variable("g")returnsNone, and the sim raisesAttributeError: 'NoneType' object has no attribute 'entity'. Net effect:household_net_incomesilently collapses to0under the reform.b) Zero-refund bug. They pay the post-cap applied credit (
mo_wftc/ut_eitc/oh_eitc) instead of the*_potential(uncapped-at-liability) amount — so exactly the zero-liability filers refundability is meant to help get$0.Files:
policyengine_us/reforms/states/mo/eitc/mo_refundable_eitc_reform.py(~line 59)policyengine_us/reforms/states/ut/child_poverty_eitc/ut_fully_refundable_eitc_reform.pypolicyengine_us/reforms/states/oh/eitc/oh_refundable_eitc_reform.pyFix PRs are already open and need review + merge + a release: MO #8642, UT #8645, OH #8657.
Gap 2 — SC has no full-refundability contrib reform
sc_eitcis nonrefundable (ingov.states.sc.tax.income.credits.non_refundable, 2021+) — a 125% federal match capped at $200/filer from 2026. SC only has the unrelated H.3492 partial reform (gov.contrib.states.sc.h3492, which refunds 25% of the excess over liability), not a full conversion.Request: add a new contrib reform mirroring MO/UT:
create_sc_refundable_eitcunderpolicyengine_us/reforms/states/sc/....gov.contrib.states.sc.child_poverty_impact_dashboard.eitc.{in_effect, match}.sc_eitcfully refundable (paysc_eitc_potential; move it from the non-refundable to the refundable credits list).add(<resolved list>)pattern — resolve the parameter to its variable-name list first; do not reintroduce the path-string bug from Gap 1.Dashboard coordination
The dashboard reads a per-state
refundable_readyflag (infrontend/data/eitc-reforms.json), currentlyfalsefor SC/MO/OH/UT, so the refundability checkboxes stay greyed. Once apolicyengine-usrelease ships with the MO/UT/OH fixes and the new SC reform, we fliprefundable_ready=trueper state and bump the dashboard's pin. (SC's $200 EITC-cap control is a plain baseline lever and ships independently — no dependency on this issue.)