Skip to content

Subtract the Massachusetts TAFDC dependent care deduction once per unit - #10257

Open
PavelMakarchuk wants to merge 2 commits into
mainfrom
fix-9983-ma-tafdc-dependent-care-once
Open

PavelMakarchuk wants to merge 2 commits into
mainfrom
fix-9983-ma-tafdc-dependent-care-once

Conversation

@PavelMakarchuk

Copy link
Copy Markdown
Collaborator

Summary

ma_tafdc_partially_disregarded_earned_income (Person) subtracted the SPM unit's whole ma_tafdc_dependent_care_deduction from each member's half-disregarded earnings, or half of it for each member on a joint return. It then floored each member's result at zero. As a result:

  • On a one-earner joint return, half of the deduction went to the spouse with no earnings and was lost to the floor.
  • Two earners who are not on one joint return each had the full deduction subtracted, so a $200 cost reduced countable income by $400.

106 CMR 704.275(A) says the deduction "is made after the 50% disregard has been deducted". It also says: "In all situations, the amount allowed for dependent care is the actual expenditure for dependent care ... or the maximum allowable deduction, whichever is less". So the unit's deduction comes off once.

With this PR, each member carries a share of the unit's deduction in proportion to their earnings after the 50% disregard. The members' amounts therefore add up to max(unit earnings after the disregard - deduction, 0). The variable stays person-level, so ma_tafdc_countable_earned_income and the six-month full disregard are unchanged. The filing-status split is removed.

The issue's examples, now matching the expected values:

  • One earner on a joint return in 2025: $200/month after deductions instead of $300; ma_tafdc is $9,878 instead of $9,278.
  • Two earners on separate returns: $150 + $150 instead of $50 + $50; ma_tafdc is $9,278 instead of $10,478.

The single-earner, single-return case is unchanged.

Interaction with #9477: #9477 (the work-related expense deduction, #9469) changes ma_tafdc_work_related_expense_deduction and integration.yaml, which this PR does not touch. Its diff applies cleanly on top of this branch. With both applied, ma/dta has 178 tests and all pass. The new cases here have no expectations on the financial eligibility test, which is the part #9477 moves.

Tests

Six cases are added to ma_tafdc_partially_disregarded_earned_income.yaml (2026, full-time work, child age 1, $250/month care, so the deduction is $200):

Case With this fix On main
One earner, joint return $200 / $0 / $0 $300 / $0 / $0
Two equal earners, separate returns $150 / $150 $50 / $50
Unequal earners ($400 and $100 after the disregard) $240 / $60 $200 / $0
Single parent (control) $200 $200 (unchanged)
Annual grant, joint return $1,200 countable, ma_tafdc $10,112 fails
Annual grant, separate returns $900 each, ma_tafdc $9,512 fails

The unequal-earner split is 400/500 and 100/500 of the $200 deduction. The grants are ($901 - countable/12) x 12, plus the $500 clothing allowance.

The 5 new non-control cases fail on main. ma/dta has 169 passed and all of states/ma has 740 passed.

Fixes #9983

🤖 Generated with Claude Code

ma_tafdc_partially_disregarded_earned_income subtracted the unit's whole
dependent care deduction from each member (half for each spouse on a joint
return), and floored each result at zero. Two earners on separate returns
deducted the cost twice, and a one-earner joint return lost half of it.
106 CMR 704.275(A) allows the unit's actual expenditure up to the maximum,
after the 50% disregard. The deduction is now shared among members by their
earnings after the 50% disregard, so it is subtracted once in total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PavelMakarchuk
PavelMakarchuk marked this pull request as ready for review October 23, 2026 17:03
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DTrim99

DTrim99 commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Subtract the Massachusetts TAFDC dependent care deduction once per unit

Summary

The PR changes one formula, ma_tafdc_partially_disregarded_earned_income (Person, MONTH):

  • Before. Main subtracted the SPM unit's whole ma_tafdc_dependent_care_deduction from each member's half-disregarded earnings. On a joint return it subtracted half from each spouse. Each member was then floored at zero.
  • Now. The formula computes each member's earnings after the $200 work expense and the 50% disregard. It then subtracts the unit's deduction times the member's share of the unit's total, and floors at zero. The members' amounts add up to max(unit earnings after the disregard − deduction, 0). The filing-status split is gone.

Six YAML cases are added. The other changes are a reference to 106 CMR 704.275 and a fixed changelog fragment.

  • Law. The fix is right.
    • 106 CMR 704.275(A) makes the deduction "after the 50% disregard has been deducted". It caps the deduction "in all situations" at "the actual expenditure for dependent care ... or the maximum allowable deduction, whichever is less".
    • 106 CMR 704.500(A) sets the grant order: each member's earnings less the work-related expense and 50% (Step 2), then the dependent care deduction (Step 3), then the total over all members (Step 4).
    • Neither section ties the deduction to federal tax filing status. So the old per-earner subtraction counted one $200 cost twice for two earners on separate returns, and the old half-per-spouse split lost half of it on a one-earner joint return. Both were modeling artifacts.
  • What was wrong. Main's grant path gave $400 of deduction for a $200 cost when the two earners had separate tax units. It gave only $100 on a one-earner joint return.
  • Order of operations. The order is the $200 work expense per earner (704.270(A), 704.281(B)), then 50%, then dependent care, then the total. That matches 704.500(A) Steps 2-4. The deduction is capped at actual cost per dependent (unchanged person variable) and at the unit's earnings after the disregard (the floor).
  • Code. The formula is vectorized. person.spm_unit.sum projects back to persons, np.divide(..., where=unit > 0) guards the zero-earnings unit, and shares are in [0, 1] because earnings after the work expense are floored at zero first. No state-gated variable is used as a parameter key, so the NH Add New Hampshire state supplementation for 2026 #10156 pattern doesn't apply.
  • Tests. I hand-checked 13 expectations, and all are correct. I also traced two cases the PR doesn't have (two children of different ages, and expenses below the cap).
  • CI. All 27 checks pass. The merge with main is clean.
  • One thing needs fixing: the axiom: line is missing. rulespec-us already encodes this provision correctly, so encoded-correct is available (see "Axiom line assessment").

The suggestions cover one more test, a 704.500 citation, and pre-existing items for a follow-up issue.

Critical (must fix)

None.

Should address

1. Add the axiom: line to the PR body.

The body (head 26a7ba299d, last edited 2026-10-23) has no line starting with axiom in any format. Pavel is staff and this is a policy fix, so the line is required, and axiom: needed isn't available.

encoded-correct is available:

  • The grant module. rulespec-us us-ma/regulations/106-cmr/704/500/block-1.yaml ("Encode Massachusetts TAFDC grant calculation", 2026-07-01) computes, per member:

    tafdc_member_countable_earned_income = max(0, (g − work) − 0.5 × (g − work) − dependent_care_deduction)

    It then sums that over the filing unit (tafdc_filing_unit_countable_earned_income, Step 4). It has no filing-status split.

  • The deduction. dependent_care_deduction is imported from us-ma/regulations/106-cmr/704/275/block-1.yaml. That module computes min(max(0, actual_dependent_care_expenditure_including_transportation), applicable maximum), with $200 under age two and $175 for age two or older or an incapacitated individual.

  • The module's own test. $1,000 gross, the $200 work expense, 50%, and $100 of care give 300. That matches this PR's structure.

Fix: add axiom: us-ma/regulations/106-cmr/704/500 encoded-correct (imports 704/275 block-1), or name both modules.

The modules do differ from PolicyEngine on points outside this PR. They take the hours band from the member's own hours, give $0 at zero hours, apply the 100% disregard per member, and round the grant down with a $10 minimum (Suggestion 3). None of these is the provision this PR changes, so they don't block encoded-correct.

Suggestions

  1. Add one multi-earner case with two children and expenses below the cap. The new cases all use one age-1 child with $250 of care against the $200 cap, so they never reach the under-cap branch or a mixed-age deduction with shares. They also don't cover a multi-earner unit whose deduction exceeds its earnings after the disregard. Suggested case: copy "Two earners with unequal earnings" ($1,000 and $400 a month, 40 hours each, separate returns). Add a second child age 5 to tax_unit1 and the SPM unit, and set care to $4,200 a year.

    • pre_subsidy_childcare_expenses splits that $175 a month to each child.
    • Deduction: min(200, 175) + min(175, 175) = 350.
    • Each parent's earnings after the disregard: parent1 400, parent2 100.
    • Members: 400 − 350 × 0.8 = 120 and 100 − 350 × 0.2 = 30, so [120, 30, 0, 0]. The sum is 150 = 500 − 350.
    • Main gives [50, 0, 0, 0].

    A second option is two $300-a-month earners with the same child, which gives [0, 0, 0]. That pins the multi-earner floor (each has 50 after the disregard, the unit has 100, and the deduction is 200).

  2. Cite 106 CMR 704.500(A) for the order. It is the section that spells out the grant computation:

    • Step 2: "subtract, in this order, from the remaining gross earnings of each member ... (a) the work-related expense deduction ... and (b) ... 50% of the remainder";
    • Step 3: "Subtract the appropriate dependent-care deduction as provided in 106 CMR 704.275";
    • Step 4: "Total the countable earned income of all members of the filing unit".

    Step 3 comes before Step 4, which is why the PR's per-member allocation, flooring and then summing fits (106 CMR 704.500). Add it to the reference tuple, and add "704.500(A) Steps 2-4" to the comment at ma_tafdc_partially_disregarded_earned_income.py:29.

  3. Pre-existing gaps for a follow-up issue (outside this diff).

    • Hours band. ma_tafdc_dependent_care_deduction_person sets the band from the SPM unit's summed weekly hours. 704.275(A) ties it to "an applicant or client who is employed full-time" or "less than full-time". The bracket parameters also start at 0 hours, so an earner with no reported hours gets $44/$50, although the table starts at "1 - 10" hours (rulespec-us gives $0 there).
    • 100% disregard per member. 704.281(A) and 704.500(A) Step 2 apply the 100% disregard per member, but ma_tafdc_full_earned_income_disregard_eligible is unit-wide. If that becomes per member, compute this PR's shares only over members outside the 100% window. Their earnings are zero at Step 3, so the deduction should fall on the others.
    • Rounding and the $10 minimum. 704.500(A) Step 7 rounds the grant "down to the next whole dollar". If the result is under $10, the unit counts as receiving assistance "but will not receive a monthly grant". ma_tafdc_potential_main_benefit does neither.
    • Parameter descriptions. dependent_care_expenses/amount/older.yaml and younger.yaml say the amount is deducted "from the unearned income". It is deducted from earned income.

Verified correct

  • Regulation text (106 CMR 704.275, amended eff. 1/4/2022 and 5/10/2024):
    • (A): "If the applicant or client is eligible for a 50% TAFDC disregard (see 106 CMR 704.280 or 106 CMR 704.281), the dependent care deduction is made after the 50% disregard has been deducted."
    • The cap: "shall not exceed $175 per dependent child, age two or older, or incapacitated individual per month. For children under the age of two, the monthly maximum allowable deduction shall not exceed $200."
    • The actual-cost limit: "In all situations, the amount allowed for dependent care is the actual expenditure for dependent care, including the cost of transporting dependents to and from dependent care, or the maximum allowable deduction, whichever is less."
    • The part-time table is $44/$50, $88/$100, $132/$150 and $175/$200 for 1-10, 11-20, 21-30 and 31+ weekly hours.
  • The maximum is per dependent, not per employed member. An incapacitated individual gets $175, not $200. The code matches:
    • young_child = monthly_age < 2 selects younger;
    • incapacitated adults use older;
    • each care recipient is capped at min_(amount, pre_subsidy_childcare_expenses + care_expenses).
  • Order.
    • 704.281(B): "a working client shall be eligible for the $200 work-related expense and a 50% earned income disregard".
    • 704.270(A): a "$200 monthly work-related-expense deduction from gross wages". MA TAFDC uses $200, not $90.
    • The formula applies the work expense per earner (floored), then p.percentage (0.5), then the deduction share. That is 704.500(A) Steps 2-4.
    • The eligibility path (ma_tafdc_earned_income_after_deductions) already subtracted the unit's deduction once. This PR doesn't touch it, and 704.280 puts dependent care after the 50% there too.
  • Arithmetic identity. Write U for the unit's earnings after the disregard and D for the deduction. Each member gets max(0, eᵢ(1 − D/U)). That is non-negative for every member when D ≤ U and zero for all when D > U, so the sum is max(U − D, 0). U = 0 gives share 0 and output 0.
  • Callers. Only ma_tafdc_countable_earned_income reads the variable. Only ma_tafdc_applicable_income_grant_amount sums that, so the per-member split affects nothing but the unit total.
  • Years. The PR claims no date. The variable has no period logic, and the tests (2026) and the body's examples (2025) fall under the current regulation text. No version of the rule splits the deduction by tax filing status. The removed filing_status == JOINT branch had no legal basis in any year.
  • Hand-checked expectations (13). Assumptions: $200 work expense, 50%, care $3,000 / 12 = $250 a month, cap $200 (child age 1; summed hours ≥ 31), payment standard $901 (size 3, private housing, from 2025-04-01), and clothing allowance $500 (from 2024-09-01).
    • One earner, joint: deduction 200. Parent1: (1,000 − 200) × 0.5 = 400, share 1, 400 − 200 = 200. The others are 0 (main: 300).
    • Two earners, separate: deduction 200. Each has (700 − 200) × 0.5 = 250, share ½, so 250 − 100 = 150 each (main: 50 each).
    • Unequal earners: 400 and 100, U = 500, so 400 − 160 = 240 and 100 − 40 = 60 (main: 200 and 0).
    • Single parent: 400 − 200 = 200. The control is unchanged.
    • Annual, joint:
      • The full disregard applies: eligibility income 12,000 − (7,200 + 2,400) = 2,400, which is under 200% of FPG.
      • Countable: 200 × 12 / 12 × 6 = 1,200, and 0 for the others.
      • ma_tafdc: (901 − 100) × 12 + 500 = 10,112. The unit is eligible (200 ≤ 901 a month).
    • Annual, separate:
      • Countable: 150 × 6 = 900 each.
      • ma_tafdc: (901 − 150) × 12 + 500 = 9,512. Eligible: 7,200 / 12 = 600 ≤ 901.
    • Existing cases, still share 1:
      • 2023, $10,000: (833.33 − 200) × 0.5 − 33.33 = 283.33 a month = 3,400.
      • "Income fully reduced": (208.33 − 200) × 0.5 = 4.17 < 33.33, so 0.
      • "No income": the U = 0 guard gives 0.
    • The body's 2025 examples:
      • Joint: 3 × (823 − 100) + 9 × (901 − 100) + 500 = 9,878 (main 9,278).
      • Separate: 3 × (823 − 150) + 9 × (901 − 150) + 500 = 9,278 (main 10,478).
    • "The 5 new non-control cases fail on main". This is right; only the single-parent control passes.
    • Monthly periods. Every monthly case is January, so the non-January YEAR-input crash doesn't arise.
  • Count the MA TAFDC work-related expense deduction once per earner #9477 interaction. Count the MA TAFDC work-related expense deduction once per earner #9477 touches ma_tafdc_work_related_expense_deduction, its test, integration.yaml and an EAEDC test, and none of this PR's files. Under it, the annual cases' eligibility income would be (12,000 − 2,400 − 2,400) / 12 = 600 and (16,800 − 4,800 − 2,400) / 12 = 800. Both are ≤ 901 and under 200% of FPG, so the grant expectations still hold.
  • Source-conflict ratchet (Tie source-conflict markers to the register shared with Axiom #10287). The added comment lines and the removed "Attributing ... equally to each spouse" line match neither CONFLICT_COMMENT_RE nor ATTEMPT_RE. No MA DTA file is in KNOWN_UNMARKED, and the test YAML is outside the scanned roots. The CI run started after Tie source-conflict markers to the register shared with Axiom #10287 and Count the FL and SD LIHEAP comments in the source-conflict ratchet baseline #10334.
  • Changelog. changelog.d/fix-9983-ma-tafdc-dependent-care-once.fixed.md is a top-level fragment with the fixed type.
  • References. The variable reference tuple has no titles, as required.
  • Partner tests. No files under tests/policy/baseline/partners/** are touched, and Household API Partners passes.
  • Issue closure. Fixes #9983 is right: the issue covers only this split.

Axiom line assessment

The line is missing (Should 1). The correct line is axiom: us-ma/regulations/106-cmr/704/500 encoded-correct. The rulespec-us TAFDC grant module subtracts each member's 704.275 dependent care deduction after the work expense and 50%, floors per member and sums (Steps 2-4), with no filing-status split. That is the behavior this PR moves PolicyEngine to.

Searches of rulespec-us issues for "TAFDC", "704.275", "9983" and "10257" find only #1087 (a 704.230 attestation issue). So no new issue is needed for this provision. The remaining PolicyEngine/rulespec differences in Suggestion 3 belong in a policyengine-us follow-up issue.

CI status

All 27 checks pass at 26a7ba299d (gh pr checks 10257; the workflow run on that SHA was created 2026-10-23 18:43 UTC). That includes the four Baseline states shards, Household API Partners, PR validation, Microsimulation and Quick Feedback. None is pending or failing.

Branch status

The branch is 2 commits ahead of main (the change on 2026-10-16 and a merge of main on 2026-10-23) and 48 behind. git merge-tree --write-tree PolicyEngine/main 26a7ba299d merges cleanly.

Verdict: REQUEST_CHANGES

@DTrim99 DTrim99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is right: 106 CMR 704.275(A) applies the deduction after the 50% disregard, capped at actual cost, and 704.500(A) Steps 2-4 go per member and then total. The proportional shares sum to max(U - D, 0), and all 13 expectations hand-check. One should-address item: there's no axiom line, and rulespec already encodes this, so add 'axiom: us-ma/regulations/106-cmr/704/500 encoded-correct'. Three suggestions, including a two-earner, two-child case below the cap. Full report in the comment above.

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.

Massachusetts TAFDC: the dependent care deduction is subtracted per earner (twice for two non-joint earners, half lost for a one-earner joint return)

2 participants