Skip to content

Count public assistance and SSI supplements in New York CCAP income - #10827

Open
MaxGhenis wants to merge 14 commits into
mainfrom
ny-ccap-public-assistance-income
Open

MaxGhenis wants to merge 14 commits into
mainfrom
ny-ccap-public-assistance-income

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

PolicyEngine now counts Family Assistance, reported Safety Net Assistance payments and adults' state SSI supplements in the income that sets New York child care assistance eligibility and family shares. OCFS counts these payments under 18 NYCRR 404.5(b)(5)(vi) (OCFS compilation, October 2023 snapshot).

OCFS began excluding children's SSI and state supplements on October 1, 2023, through emergency rule CFS-42-23-00002-EP, and adopted the exclusion permanently on June 12, 2024. Before then, OCFS counted SSI and state supplements for every member (November 2021 compilation). PolicyEngine now counts a child's payments in each month before October 2023 and excludes them from that month. Main excluded children's SSI in every year.

New York waives the family share when a parent or caretaker relative receives public assistance (415.3(e)(1)). PolicyEngine now waives the share for a family that takes up a Family Assistance grant, as it does for a family that reports receipt, so a family whose grant counts as income pays no share.

For example, a New York County parent earns $12,000 in 2026, pays $1,000 a month in rent, and lives with a 4-year-old in care and a grandparent who receives $11,928 of SSI. The family receives $6,948 of Family Assistance, and its $30,876 of countable income exceeds the $27,320 state income standard for three by $3,556. The family pays no share. Without the waiver, it would pay the $4.33 monthly minimum.

This implements part 1 of #10239, covering CCAP income. Part 2 remains with the separate HEAP work.

Closes #10705

Merge order

This branch includes main with #10817, which added the Safety Net Assistance and veteran assistance receipt inputs, the preventive care route and the child-only exception. The family share waiver reads each of them beside ny_ccap_family_assistance > 0.

#10821 also edits New York's child care note in policyengine_us/programs.yaml. The second of the two PRs to merge needs a merge of main that keeps both sets of clauses.

Invariants

The property tests live in policyengine_us/tests/core/test_ny_ccap_public_assistance_income_invariants.py. The YAML cases live in ny_ccap_public_assistance_income.yaml and ny_ccap_family_share_exempt.yaml under policyengine_us/tests/policy/baseline/gov/states/ny/ocfs/ccap/.

  • Countable income rises dollar for dollar with the Family Assistance a family takes up, the Safety Net Assistance amount and an adult's state supplement. test_countable_income_weakly_rises_with_each_public_assistance_source checks each source, and a declined grant adds nothing.
  • When all three amounts equal zero, countable income, the family share and CCAP equal main's results from 2024 on. test_zero_public_assistance_amounts_preserve_main_income_and_ccap compares both formulas across generated families.
  • A child's SSI and supplement raise countable income by 12 months of payments in 2022, 9 months in 2023 and nothing in 2024. test_a_childs_ssi_and_supplement_count_only_before_october_2023 checks those counts, and YAML cases pin 2022 and 2023.
  • From 2024 on, a child's supplement changes neither countable income, the family share nor CCAP. test_a_childs_state_supplement_does_not_change_income_or_ccap checks that exclusion.
  • A family with reported Family Assistance enrollment pays no share, and its CCAP stays nonnegative. test_reported_public_assistance_keeps_the_family_share_zero checks those families, and a YAML case checks reported receipt with no computed grant.
  • The counted grant equals ny_tanf for a family that takes it up and zero otherwise, and every family with a counted grant pays no share. test_counted_family_assistance_keeps_the_family_share_zero checks families without reported enrollment. YAML cases check a three-person family above the state income standard with and without reported enrollment, and a family that declines the grant and pays its share.
  • A family that reports Safety Net Assistance receipt pays no share without Family Assistance. test_safety_net_receipt_alone_keeps_the_family_share_zero checks those families.
  • A family with a computed grant and child care expenses receives CCAP without the model requesting the federal tanf aggregate. test_computed_family_assistance_with_childcare_expenses_avoids_federal_tanf checks 2024, 2025 and 2026.
  • Abolishing TANF removes Family Assistance from countable income and leaves the other sources. ny_ccap_public_assistance_income_abolition.yaml checks that case.

Methodology choices

  • Count Family Assistance as ny_tanf for a family that takes it up, and as zero when gov.hhs.tanf.abolish_tanf applies. ny_ccap_family_assistance holds that amount. The federal tanf aggregate sums other states' programs, whose dependent care deductions read child care subsidies, so reading it would make CCAP depend on itself. A direct tanf input does not reach CCAP income; set ny_tanf instead.
  • Treat a Family Assistance grant the family takes up as a parent's or caretaker relative's receipt of public assistance under 415.3(e)(1). The SPM-unit grant does not say which members belong to the assistance unit, so a grant paid for children alone also waives the share. The public assistance reason-for-care route still reads reported receipt only.
  • Count the ny_safety_net_assistance amount as income without waiving the share. The SPM-unit amount can include another member's payments, so it does not show that a parent or caretaker relative receives them. The ny_safety_net_assistance_received input carries that fact. Household benefits and other programs' income leave the amount out.
  • Count an adult's ny_ssp beside the adult's SSI, and keep the is_child cutoff below age 18 for both payments. An 18-year-old's payments count.
  • Apply the child SSI exclusion month by month inside annual countable income. Monthly consumers read one twelfth of the annual total, so each 2023 month carries one twelfth of the payments counted from January to September.
  • ny_ssp amounts start on January 1, 2026, and the model copies each parameter's earliest value back to 2015. Supplements counted for years before 2026 therefore use the 2026 amounts.
  • Keep annual countable-income aggregation and the SPM unit as the family. This change adds no income-averaging period and no family-unit definition.
  • Record LII's copy of 404.5, which still shows the text in force before October 1, 2023, as us-ny:ccap-child-ssi-state-supplement-exclusion in source_conflicts/candidates.yaml. The candidate starts in 2023 and stays unreviewed. The captures under source_conflicts/sources/us-ny/ hold both OCFS compilations, LII's text and the three State Register notices.

We added the income sources to New York's coverage note and removed the public-assistance income omission. New York keeps its partial status and its other listed gaps.

We read web.archive.org copies of OCFS's Part 404 compilations, current as of November 24, 2021 and October 1, 2023, and of its Part 415 compilation, current as of February 13, 2024. We could not reach ocfs.ny.gov, so we have not confirmed that its live copies match. The Department of State served the three State Register notices directly.

Test fixtures

TANF reads earnings before labor supply responses, employment_income_before_lsr. In a YAML case that enters employment_income, TANF counts no earnings. In three existing cases with working parents, CCAP therefore counted a Family Assistance grant: integration.yaml cases 5 and 6 and court_supervision.yaml case 8. Those cases now enter the earnings TANF reads.

Other cases pin CCAP income and enter no earnings, so PolicyEngine computes a grant that waives the share. Two integration.yaml cases decline the grant. Five existing ny_ccap_family_share_exempt.yaml cases, the 24 ny_ccap.yaml cases from #10817 without reported TANF enrollment, and the families in #10817's property tests set ny_tanf to zero. Seven of those ny_ccap.yaml cases expect a share and fail without the input. The other 17 test another exception, which a computed grant would satisfy on its own. Every expected value in those files stays the same.

axiom: needed

Validation

We ran each file alone under policyengine-core 3.36.0 at this head, and the four files in the table's last row at 3147d74.

File Result
ny_ccap_public_assistance_income.yaml 15 passed
ny_ccap_public_assistance_income_abolition.yaml 1 passed
ny_ccap_family_share_exempt.yaml 10 passed
ny_ccap.yaml 37 passed
integration.yaml 6 passed
court_supervision.yaml 9 passed
ny_ccap_countable_income.yaml 16 passed
ny_ccap_family_share.yaml 8 passed
ny_ccap_activity_eligible.yaml 9 passed
ny_ccap_income_eligible.yaml 4 passed
ny_ccap_eligible_child.yaml 14 passed
test_ny_ccap_public_assistance_income_invariants.py 10 passed
test_ny_ccap_categorical_routes_invariants.py 4 passed
test_source_conflicts.py 103 passed
test_programs_registry.py 883 passed, 10 skipped
test_parameter_yaml_keys.py, test_reference_urls.py, test_no_concatenated_reference_urls.py, test_aggregate_list_integrity.py 34, 32, 48 and 38 passed

Nine mutants each fail at least one YAML case:

  • the waiver reads only reported receipt;
  • the waiver applies at a zero grant;
  • the waiver drops reported Family Assistance enrollment;
  • the waiver drops Safety Net Assistance receipt;
  • the child exclusion applies in every year;
  • the child exclusion starts a month late;
  • the child exclusion follows the year's parameter value, not each month's;
  • the counted grant ignores take-up;
  • the counted grant ignores TANF abolition.

Ruff's format check and lint pass on the changed Python files.

Microsimulation impact

To be measured before merge.

🤖 Generated with Claude Code

MaxGhenis and others added 6 commits November 12, 2026 00:37
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits November 13, 2026 19:39
… the child SSI exclusion

New York waives the child care family share when a parent or caretaker
relative receives public assistance (18 NYCRR 415.3(e)(1)). The waiver
read reported enrollment only, so a family whose computed Family
Assistance counted as income still paid a share. ny_ccap_family_assistance
now holds the ny_tanf grant the family takes up, zero when TANF is
abolished. Countable income counts it, and the waiver reads it beside
reported enrollment.

OCFS began excluding children's SSI and state supplements on October 1,
2023. Countable income now counts those payments in each month before
that date and excludes them from it.

The Safety Net Assistance input moves to the OTDA folder, and its
404.5(b)(5)(vi) entry follows (v) in the sources list. New York's coverage
note now says when children's payments count.

Two integration cases now enter earnings as employment_income_before_lsr,
which TANF reads. With employment_income alone, the YAML runner left TANF
with no earnings, and countable income counted the resulting grant.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LII still reproduces the 404.5 text in force before October 1, 2023,
which matches OCFS's November 2021 compilation. The candidate now starts
in 2023, says so and cites that compilation. Its state moves from ruled
to unreviewed, since no ruling covers it. Each capture holds whole pages
of the source text in the format the other captures use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TANF reads employment_income_before_lsr, and the YAML runner does not
copy employment_income into it. The model therefore computed a Family
Assistance grant for this family with $60,000 of earnings and counted
the grant in CCAP income. The case now enters the earnings TANF reads,
and its expected values stay the same.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
MaxGhenis and others added 3 commits November 14, 2026 09:23
Main now holds New York's categorical routes and family share exceptions
(#10817). Resolve two conflicts:

- programs.yaml: keep main's New York child care note, add the income
  sources this branch counts and drop the public assistance income gap
  this branch closes.
- ny_ccap_family_share_exempt.py: keep main's Safety Net Assistance,
  veteran assistance, preventive care and child-only exceptions, and read
  the Family Assistance grant the family takes up beside reported
  enrollment.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…lic assistance

Twenty-four ny_ccap.yaml cases, three ny_ccap_family_share_exempt.yaml
cases and the categorical-route property tests describe families without
Family Assistance but enter no earnings. PolicyEngine computes a grant
for those families, and that grant now waives the family share. Set
ny_tanf to zero in those fixtures, so each case tests the exception it
names. Seven of the ny_ccap.yaml cases expect a share, which a computed
grant waives. Every expected value stays the same.

Add a case in which reported Family Assistance receipt waives the share
with no computed grant. Run the Safety Net Assistance receipt property
test, which waited for the receipt input that main now has. Say in
ny_safety_net_assistance that household benefits and other programs'
income leave these payments out.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Main now holds South Dakota's hourly child care rates (#10815), whose
source-conflict candidate ends candidates.yaml, where this branch adds
New York's. Keep both candidates, South Dakota's first.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review November 14, 2026 19:31
OCFS excludes children's SSI and state supplements from child care
assistance income from October 1, 2023, under 18 NYCRR 404.5(b)(5)(vi)
and (b)(6)(xxi). The code follows that reading, which we record under
readings.statute, so pe_us.follows takes statute, as in South Dakota's
candidate. We keep gap-fill, as the file header defines it, for code
that follows a form where the statute is silent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main now holds New York's payment differentials, special-needs rate and
New York City enhanced rates (#10821). Resolve one conflict:

- programs.yaml: keep main's New York child care note, add the income
  sources this branch counts and drop the public assistance income gap
  this branch closes.

Git merges candidates.yaml and the New York integration test without
conflict. Keep every candidate and case from both sides.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New York CCAP: count public assistance in countable income

1 participant