Skip to content

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

Merged
PavelMakarchuk merged 6 commits into
mainfrom
fix-9983-ma-tafdc-dependent-care-once
Oct 27, 2026
Merged

PavelMakarchuk merged 6 commits into
mainfrom
fix-9983-ma-tafdc-dependent-care-once

Conversation

@PavelMakarchuk

@PavelMakarchuk PavelMakarchuk commented Oct 16, 2026 •

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. 106 CMR 704.500(A) Steps 2-4 apply the work expense and the 50% disregard to each member, then the dependent care deduction, then total the members.

With this PR, the unit's deduction is subtracted once, from the earnings (after the 50% disregard) of the member who pays for the care: max(0, e_payer - D). 704.275(A) gives the deduction to "an employed applicant or client", and DTA's BEACON help applies it "as a deduction for the client incurring the expense"; no source moves an unused part to another earner, so it is not used. A new input, ma_tafdc_dependent_care_payer (Person, YEAR), names the payer, because the SPM unit's care expense does not record who pays. Its default is an assumption: the head or spouse with the highest gross earnings (the first on a tie). If more than one member is set as payer, they share the deduction equally. 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 equal earners on separate returns: $50 (the payer) + $250 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 had 178 tests and all passed (2026-10-23, before the two cases added on 2026-10-27). The new cases here have no expectations on the financial eligibility test, which is the part #9477 moves.

Tests

Cases are added to ma_tafdc_partially_disregarded_earned_income.yaml, and ma_tafdc_dependent_care_payer.yaml has four cases for the default payer (one earner, the higher earner listed second, equal earners, a dependent teen with higher earnings who is not the payer). Unless a row says otherwise: 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 ($250 each after the disregard; the first pays) $50 / $250 $50 / $50
Unequal earners ($400 and $100 after the disregard), payer not named (the higher earner pays) $200 / $100 $200 / $0
Unequal earners, the lower earner pays $400 / $0 ($100 of the deduction not used) $200 / $0
Both set as payers $300 / $0 —
Unequal earners, children age 1 and 5, $350/month care (deduction $175 + $175 = $350) $50 / $100 $50 / $0
Two $50 earners after the disregard, below the deduction $0 / $50 $0 / $0
Single parent (control) $200 $200 (unchanged)
Annual grant, joint return $1,200 countable, ma_tafdc $10,112 fails
Annual grant, two equal earners on separate returns $300 / $1,500, ma_tafdc $9,512 fails
Annual grant, the lower earner pays $2,400 / $0, ma_tafdc $8,912 fails

The grants are ($901 - countable/12) x 12, plus the $500 clothing allowance. ma/dta: 178 passed.

Axiom

axiom: TheAxiomFoundation/rulespec-us#1943 queued

  • us-ma/regulations/106-cmr/704/500/block-1.yaml encodes Steps 2-4 with no filing-status split, but its .test.yaml has no case with two earning members or two dependents. Its 704.275 import computes the deduction per person, with one dependent's maximum per person, and the grant step floors each member at zero.
  • An earlier run of this PR's situations through that module (axiom-encode test, rulespec-us main 021d96906, a local engine build) used the proportional split this PR first had. With the payer rule, the cost on the lower earner gives 400, as the module does; the other two-earner cases need a new run. rulespec-us#1943 is updated with the payer rule.
  • rulespec-us#1943 (pe-parity) has the law, the required outputs and eight companion cases. The blocker is the approval of a billed signed-encoder run.

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.

Add two cases from review: two earners with two children and care below
the per-child cap (deduction $175 + $175, shares 400/500 and 100/500),
and two $300 earners whose earnings after the disregard are below the
deduction. Cite 106 CMR 704.500(A) Steps 2-4 for the order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PavelMakarchuk

Copy link
Copy Markdown
Collaborator Author

Thanks for the review, @DTrim99. New head: ff8655ea34. Each item:

Should address 1: axiom: line — added, as queued, not encoded-correct

The body now has axiom: TheAxiomFoundation/rulespec-us#1943 queued.

encoded-correct needs a companion case in the module's .test.yaml that exercises the same situation as this PR's tests (CONTRIBUTING.md, Axiom parity). us-ma/regulations/106-cmr/704/500/block-1.test.yaml has four cases: one single-member 50% case, a one-member filing unit, an empty unit and an EAEDC case. None has two earning members or two dependents.

So I ran this PR's situations through the module myself. I appended them to a copy of block-1.test.yaml from rulespec-us main 021d96906 and ran axiom-encode test (local engine build b06df40, not the pinned 89571cc2):

Case (unit countable earned income) Expected Engine
One earner $1,000 + spouse not employed, child age 1, care $250 200 200
Two $700 earners, child age 1, $250 entered on earner 1 300 300
Same, $250 entered as $125 / $125 300 250
$1,000 and $400 earners, child age 1, $250 entered on the $400 earner 300 400
$1,000 and $400 earners, children 1 and 5, $175 each, one child per parent 150 225
Single parent $1,000, child age 1, care $250 200 200
Single parent $1,000, children 1 and 5, $175 each 50 200

The causes are in the modules, not in this PR:

  • The 704.275 dependent_care_deduction is per person, with one dependent_is_child_under_two flag and one maximum per person. A parent who pays for two children gets at most $200, not $175 + $175 ("per dependent child").
  • Two members can each claim up to the $200 maximum for the same child, so one child under two can give $250.
  • tafdc_member_countable_earned_income floors each member at zero, so the unit total depends on which earner is entered as the payer. 704.500(A) Step 3 doesn't say how a unit's deduction is split between earners.

The module matches this PR for one earner, and for two earners when one earner with enough earnings is entered as the payer. It doesn't match the other multi-earner and multi-child cases, and no entry of the payer gives 150 for the two-child case. rulespec-us#1943 (pe-parity) has the law, the required outputs and eight companion cases hand-computed from 704.275(A) and 704.500(A). The test files are hashed in their signed manifests, so I didn't append the cases by hand. The blocker is the approval of a billed signed-encoder run. No encoder run was started and no RuleSpec was written.

Suggestion 1: two-earner, two-child case below the cap — added

"Two earners with two children below the cap share the deduction by earnings": $1,000 and $400 a month, children 1 and 5, care $4,200 a year. Deduction $175 + $175 = $350; result [120, 30, 0, 0] (main [50, 0, 0, 0]), as you computed.

I also added your second option, "Two earners whose earnings after the disregard are below the deduction": two $300 earners, $50 each after the disregard, deduction $200, result [0, 0, 0]. It passes on main too; it pins the multi-earner floor.

On main's formula 6 of the 8 new cases fail; the single-parent control and the floor case pass. ma/dta has 171 passed, and test_source_conflicts.py passes.

Suggestion 2: cite 704.500(A) — done

The 704.500 link is in the reference tuple, and the comment now says that 704.500(A) Steps 2-4 apply the work expense and the 50% disregard per member, then the dependent care deduction, then total the members.

Suggestion 3: pre-existing gaps — filed as #10489

I checked each one against main: the hours band from the SPM unit's summed hours (and $50 / $44 at zero hours), the unit-wide 100% disregard test, no rounding or $10 minimum in ma_tafdc_potential_main_benefit, and the "unearned income" wording in the two parameter descriptions. All four are in #10489. They are outside this diff, so this PR doesn't change them.

@DTrim99

DTrim99 commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

PR Review (round 2): Subtract the Massachusetts TAFDC dependent care deduction once per unit

Summary

This round covers one author commit since our round-1 review at 26a7ba299d: ff8655ea34 ("Test MA TAFDC dependent care shares with two children and the unit floor"). The commit adds two YAML cases, a 106 CMR 704.500 reference and a longer comment. The formula itself is unchanged since round 1, and I re-confirmed my round-1 finding that it is correct under 106 CMR 704.275(A) and 704.500(A) Steps 2-4.

  • Round-1 Should 1 (axiom line) is resolved. The body now has axiom: TheAxiomFoundation/rulespec-us#1943 queued. In round 1 I proposed encoded-correct. Pavel declined that, and he is right.
    • The rulespec-us 704.275 module computes dependent_care_deduction per Person, from one dependent_is_child_under_two flag and one maximum per person.
    • So a single parent who pays for two children gets one dependent's maximum, not $175 + $175 "per dependent child".
    • The module also floors each member's earnings at zero. As a result, a multi-earner unit's total depends on which member is entered as paying.
    • The module therefore doesn't encode this provision correctly, and encoded-correct would have been wrong. rulespec-us#1943 is OPEN, labelled pe-parity, dispatch-ready and in line with the head.
  • All three suggestions were taken.
  • Hand checks. I checked all four new expectations, and all are correct. CI ran these tests at this head, merged with current main, and the file passed (11 of 11 cases).
  • New findings. None.
  • CI. One failure, Rest Python shard 3 (test_mt_state_agi_invariants), comes from main (Add Montana's 2021–2023 partial pension, annuity, and IRA income exemption #10392; the fix is Check Montana's pension exemption in the Montana AGI pooling test #10496), so it is not a finding. The gate job "Check Rest Python shards" fails only because of that shard. When last checked (15:58 UTC), 28 checks passed and three Contrib shards were still pending.
  • Branch. The branch is 70 commits behind main and merges cleanly. No commit on main since the merge base touches an MA file.

Prior findings

Finding Status Evidence
Should 1. Add the axiom: line (round 1 proposed encoded-correct on us-ma/regulations/106-cmr/704/500) Fixed, with queued instead of encoded-correct. The reason for declining encoded-correct is valid. The body has axiom: TheAxiomFoundation/rulespec-us#1943 queued. I read rulespec-us us-ma/regulations/106-cmr/704/275/block-1.yaml on main. dependent_care_deduction is entity: Person, with formula min(max(0, actual_dependent_care_expenditure_including_transportation), applicable_dependent_care_maximum_deduction). applicable_dependent_care_maximum_deduction picks a single maximum from the person's own dependent_is_child_under_two flag. 704.275(A) instead caps the deduction "per dependent child" and gives the table "per child, or incapacitated individual". So the module's single-parent, two-child result (200 instead of 50) and its payer-dependent multi-earner totals (Pavel's cases 2b, 3 and 4) are wrong under the law. Round 1 overlooked this: the module's own tests have one dependent and one earner. queued is the correct status. See "Axiom line assessment".
Suggestion 1. Add a multi-earner case with two children and care below the cap (plus an optional multi-earner floor case) Fixed Two cases were added: "Two earners with two children below the cap share the deduction by earnings" (ma_tafdc_dependent_care_deduction: 350, [120, 30, 0, 0]) and "Two earners whose earnings after the disregard are below the deduction" (200, [0, 0, 0]). Both match my round-1 computation and the hand checks below.
Suggestion 2. Cite 106 CMR 704.500(A) for the order Fixed ma_tafdc_partially_disregarded_earned_income.py adds ".../106-CMR-704-500", # (A) to the reference tuple, with no title, as required. The comment now says that 704.500(A) Steps 2-4 apply the work expense and the 50% disregard per member, then the dependent care deduction, then total the members. That matches the regulation text (fetched today): "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".
Suggestion 3. File a follow-up for the pre-existing gaps (hours band, 100% disregard per member, rounding and the $10 minimum, "unearned income" wording) Fixed (filed) #10489 is OPEN, titled "Massachusetts TAFDC: dependent care hours band per earner, 100% disregard per member, grant rounding and the $10 minimum". It covers all four items and quotes 704.275(A) and 704.500(A) Steps 2 and 7. It also notes that this PR's allocation should exclude members inside the 100% window if that disregard becomes per member.

New findings

Critical: none.

Should address: none.

Suggestions: none.

Verified

  • Hand checks (all four new expectations, plus the changed header comment). Assumptions: the $200 work expense (704.270(A)), the 50% disregard, and the hours band from the SPM unit's summed weekly hours (40 + 40 = 80, so the 31+ row). pre_subsidy_childcare_expenses splits the SPM unit's care costs evenly over its children, and monthly_age < 2 selects younger.
    • "Two earners with two children below the cap".
      • Care is $4,200 / 12 = $350 a month, or $175 per child.
      • Child age 1: min($200, $175) = $175. Child age 5: min($175, $175) = $175. ma_tafdc_dependent_care_deduction = 350.
      • Earnings after the disregard: parent1 ($1,000 − 200) × 0.5 = 400; parent2 ($400 − 200) × 0.5 = 100; U = 500.
      • parent1 400 − 350 × 400/500 = 400 − 280 = 120; parent2 100 − 350 × 100/500 = 100 − 70 = 30; the children 0, 0. The sum is 150 = 500 − 350.
      • Main gives max(400 − 350, 0) = 50 and max(100 − 350, 0) = 0 (separate returns, so the full amount for each), so the case fails on main, as the body says.
    • "Two earners whose earnings after the disregard are below the deduction".
      • Care is $250 a month for a child age 1, so min($200, $250) = 200.
      • Each earner has ($300 − 200) × 0.5 = 50, so U = 100 < D = 200.
      • Each member gets max(50 − 200 × ½, 0) = max(−50, 0) = 0, giving [0, 0, 0].
      • Main gives max(50 − 200, 0) = 0 each, so the case passes on main. It pins the multi-earner floor.
    • The header comment now reads "Unless a case says otherwise, the child is age 1 ...". That is accurate, since the two-child case departs from the default.
    • The body's claims. "Eight cases are added" and "6 of the 8 new cases fail on main; the single-parent control and the two-$300-earner floor case pass on both" are both right. The other six fail on main: 300 vs 200; 50/50 vs 150/150; 200/0 vs 240/60; 50/0 vs 120/30; and the two annual cases. The body's table values match the YAML.
  • The formula is unchanged since round 1. It is vectorized, guards U = 0 with np.divide(..., where=unit > 0), and produces max(U − D, 0) as the unit total. The per-member allocation fills a gap: 704.500(A) Step 3 doesn't say how to split a unit's deduction between earners. It is not a conflict between sources. rulespec-us#1943 records the reading under "Interpretations and gaps".
  • Merged-tree guards. CI checked out Merge ff8655ea34 into c2785f63b1, which is current main.
  • NH Add New Hampshire state supplementation for 2026 #10156 pattern. No state-gated variable is used as a parameter or breakdown key.
  • The reference (106 CMR 704.500) loads and shows Steps 2-4 as quoted above.
  • Partner tests. No file under tests/policy/baseline/partners/** is touched, and Household API Partners passes.
  • Changelog. changelog.d/fix-9983-ma-tafdc-dependent-care-once.fixed.md is unchanged, top-level, and of type fixed.
  • 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 is still open and touches only the work-related expense variable, its test, integration.yaml and an EAEDC test. Its new formula is min(gross earnings, $200). Every earner in the two new cases earns at least $300, so the expectations hold after Count the MA TAFDC work-related expense deduction once per earner #9477 too.

Axiom line assessment

axiom: TheAxiomFoundation/rulespec-us#1943 queued is valid.

  • State: OPEN, labelled pe-parity, created 2026-10-27.
  • Dispatch-ready:
    • Module paths: us-ma/regulations/106-cmr/704/275/block-1.yaml and 704/500/block-1.yaml, each with its companion .test.yaml.
    • Corpus citations: us-ma/regulation/dta/106-cmr/704/704.275 and .../704.500.
    • Law: the verbatim text of 704.275(A) and 704.500(A) Steps 2-4.
    • Required outputs: the unit deduction (a sum of per-dependent minimums) and tafdc_filing_unit_countable_earned_income, together with the invariants.
    • Companion tests: eight cases hand-computed from 704.275(A) and 704.500(A), not taken from PolicyEngine output. They use the same facts as this PR's YAML cases.
    • Dispatch: a pasteable review_finding.
  • Blocker: each billed signed-encoder run needs separate approval. That is a valid reason to use queued.
  • Match with the head: the issue states the post-PR formula (each member gets max(0, e − D × e / U); the sum is max(U − D, 0)). Its companion cases 1-6 give the same unit totals as the head's YAML cases, including the two added in this commit (case 4 → 150 = 120 + 30; case 5 → 0).
  • The module defect is confirmed (see the prior-findings table). I checked it by reading the module, not by running it. Pavel's engine run used a local build, not the pinned one, and the issue says so.

CI status

The run at ff8655ea34 (gh pr checks 10257, last checked 2026-10-27 15:58 UTC) tested Merge ff8655ea34 into c2785f63b1, which is current main. At that check, 28 passed, 2 failed and 3 were pending.

  • Passed: all Baseline shards, including states-shard-1, where the MA batch ran this file's 11 cases and passed. Also Household API Partners, PR validation, Package and compatibility, Quick Feedback, Microsimulation, and Rest Python shards 1, 2, 4, 5 and 6.
  • Failed, main-caused (a CI note, not a finding): "Full Suite - Rest (Python shard 3)".
  • Still pending: Contrib states-shard-1, states-shard-2 and other-shard-1. They were in progress after about 20 minutes of waiting. This PR touches no contrib reform.

Branch status

The branch is 3 commits ahead of main and 70 behind. git merge-tree --write-tree PolicyEngine/main ff8655ea34 merges cleanly (tree da940af9fe).

Verdict: APPROVE

@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.

Approving round 2: 0 critical, 0 should. Full report in the comment above. CI note: the Rest shard 3 failure (test_mt_state_agi_invariants) comes from main and is fixed by #10496; re-run after it lands.

hua7450 commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

@PavelMakarchuk, could you link the Massachusetts rule or an authoritative worked example supporting allocation of the unit's dependent-care deduction across earners, including when the client paying for care has insufficient earnings left after the work-expense deduction and 50% disregard?

DTA's expense-entry guidance ties the deduction to the client incurring the expense. I could not establish from 106 CMR 704.275/704.500 whether an unused portion may reduce another earner's income.

For example, with post-work/50% earnings of $400 and $100 and an allowable $200 care expense paid by the lower earner, this PR produces $240 and $60. What source supports pooling the deduction in that case, or otherwise establishes that the proportional allocation gives the legally correct unit total? The current input records the unit's expense without identifying its payer.

The reported lost/duplicated-deduction cases are addressed; this source question is the remaining point I need clarified before approving.

PavelMakarchuk and others added 2 commits October 27, 2026 18:04
106 CMR 704.275(A) gives the deduction to the employed applicant or
client for the expenditure on care, and DTA's BEACON help applies it
"as a deduction for the client incurring the expense". No source lets
an unused part reduce another earner's earnings. So the unit's
deduction now comes off once, from the payer's earnings after the 50%
disregard, instead of being shared among earners by their earnings.

The care expense input does not record who pays, so a new input,
ma_tafdc_dependent_care_payer, names the payer. By default it is the
head or spouse with the highest gross earnings (the first one when
earnings are equal). If more than one member is set as a payer, they
share the deduction equally.

Tests: the reviewer's case ($400 and $100 after the disregard, $200
deduction paid by the lower earner) gives $400 and $0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PavelMakarchuk

Copy link
Copy Markdown
Collaborator Author

Thanks, @hua7450. I could not find a source that supports pooling. The sources give the deduction to the employed client who pays for the care. None of them lets an unused part reduce another earner's income. So I changed the PR: the deduction now comes off the payer's earnings only. New head: fc73aac393.

What the sources say

  1. 106 CMR 704.275(A) (same text in DTA's copy of 106 CMR 704, page 704.275). Each part of the rule is about one applicant or client:
    • "An employed applicant or client may receive a deduction from income equal to the expenditure for the care of a dependent child".
    • "If the applicant or client is eligible for a 50% TAFDC disregard ..., the dependent care deduction is made after the 50% disregard has been deducted."
    • The maximum depends on that person's own hours: "For an applicant or client who is employed full-time ..." and "An applicant or client who is employed less than full-time may receive a proportionate share of the maximum allowable deduction."
    • (B)(1)-(2) take the deduction away from a particular "applicant or client". (C)(1) verifies the cost by "a signed and dated statement from the employed individual".
  2. 106 CMR 704.280 and 704.281(B). 704.281(B) gives the 50% disregard to "a working client". 704.280 applies it to the applicant's "remaining gross earned income ... after work-related-expenses, but before dependent care deductions". So the deduction follows the 50% disregard in the same person's earnings.
  3. 106 CMR 704.500(A). Step 2 works on "the remaining gross earnings of each member". Step 3 subtracts "the appropriate dependent-care deduction". Step 4 totals "the countable earned income of all members". Step 3 comes before the total, so the deduction is taken from a member's earnings, not from the unit's total.
  4. DTA BEACON help.
  5. Background. The $175/$200 maximums and the part-time shares come from the AFDC rule, which took the disregard from each individual's earnings. 45 CFR 233.20(a)(11)(ii)(B) said: "Disregard from any other individual's earned income the amounts specified in paragraphs (a)(11)(i)(B) and (a)(11)(i)(D)". (D) is the dependent care disregard. This rule no longer applies, so I use it only as background.

I also read the BEACON pages on the dependent care deduction, the 50% disregard, the need and payment standards and the Interview Wrapup financial tab. I also checked the memos and Transitions items listed on the Employment policy page and the Mass Legal Services TAFDC training. None of them has a two-earner budget example, and none of them moves a deduction to another earner. I could not open the TANF State Plan on mass.gov (HTTP 403).

What the sources do not say

No sentence says what happens to the part of the deduction that is more than the payer's earnings. But the deduction is "from income" of the client who receives it, Step 3 comes before the Step 4 total, and no rule moves an unused part to another member. So I read the rule as: the payer's countable earned income stops at $0, and the rest of the deduction is not used.

What this means for the proportional split

The proportional split gives the correct total in two cases only. One is when the payer's earnings after the disregard cover the whole deduction, because then every split gives U - D. The other is when the earners paid shares in proportion to their earnings. In your example it gives $300, but the rule gives $400.

The change

  • The unit's deduction is subtracted once, from the earnings of the member who pays, after the 50% disregard: max(0, e_payer - D). Other members keep their earnings.
  • New input ma_tafdc_dependent_care_payer (Person, YEAR, bool) names the payer. spm_unit_pre_subsidy_childcare_expenses does not record the payer, so the default is an assumption. The default payer is the head or spouse with the highest gross earnings, or the first of them when earnings are equal. In a one-earner unit this is the earner. In a two-earner unit, it assumes the expense is reported under the earner who can use the most of it. If more than one member is set as a payer, they share the deduction equally.
  • Before, a two-earner unit lost nothing to the floor until U < D. Now it loses max(D - e_payer, 0).

Your example under the new code

$400 and $100 after the work expense and the 50% disregard, $200 deduction:

Payer parent1 parent2 Unit total
Not named (default: parent1, the higher earner) $400 - $200 = $200 $100 $300
parent2 (ma_tafdc_dependent_care_payer: true) $400 max($100 - $200, 0) = $0 $400 ($100 of the deduction not used)

For the full year (100% disregard for 6 months, then 6 months at these amounts), the parent2-pays case gives ma_tafdc_countable_earned_income of $2,400 and $0. ma_tafdc is ($901 - $2,400 / 12) x 12 + $500 = $8,912.

Test changes

Case Before this commit Now
One earner, joint return $200 / $0 $200 / $0 (no change)
Two equal earners, $250 each after the disregard $150 / $150 $50 / $250 (the first one pays)
Unequal earners, payer not named $240 / $60 $200 / $100
Unequal earners, parent2 pays (new, your example) — $400 / $0
Both set as payers (new) — $300 / $0
Two children, $350 deduction $120 / $30 $50 / $100
Two $50 earners, $200 deduction $0 / $0 $0 / $50
Annual, two equal earners $900 / $900, ma_tafdc $9,512 $300 / $1,500, ma_tafdc $9,512
Annual, parent2 pays (new) — $2,400 / $0, ma_tafdc $8,912

ma_tafdc_dependent_care_payer.yaml has four cases for the default: one earner, the higher earner listed second, equal earners, and a dependent teen with higher earnings (not the payer). ma/dta: 178 passed.

Not in this PR

🤖 Addressed by Claude Code

@hua7450 hua7450 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.

Thanks for replacing proportional pooling with a payer-specific deduction and adding explicit lower-earner-payer cases. The rewrite addresses my allocation-source question; the verified 18-case CI execution includes the final grant path. Approving within #9983's scope. The preexisting payer-specific financial-eligibility treatment is now explicitly tracked in section 5 of #10489.

@PavelMakarchuk
PavelMakarchuk merged commit 2faad8b into main Oct 27, 2026
33 checks passed
@PavelMakarchuk
PavelMakarchuk deleted the fix-9983-ma-tafdc-dependent-care-once branch October 27, 2026 23:38
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)

3 participants