Skip to content

Apply North Carolina Work First's $3,000 resource limit - #10686

Open
PavelMakarchuk wants to merge 3 commits into
mainfrom
nc-tanf-resource-test
Open

PavelMakarchuk wants to merge 3 commits into
mainfrom
nc-tanf-resource-test

Conversation

@PavelMakarchuk

@PavelMakarchuk PavelMakarchuk commented Nov 6, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

nc_tanf_eligible tested only income and demographics. North Carolina Work First Family Assistance also has a resource limit:

  • 10A NCAC 71W .0407 (Reserve): the assistance unit may reserve resources up to $3,000 and is ineligible above that.
  • Work First Manual, section 115 I.A: "A family receiving Work First Family Assistance is allowed $3,000 in resources." The chart in section II (p. 2-4) counts cash, checking and savings accounts, stocks, bonds and mutual fund shares, and does not count motor vehicles, real property, retirement accounts or household goods.

Changes:

  • New parameter gov.states.nc.ncdhhs.tanf.resources.limit ($3,000; 10A NCAC 71W .0407(a), Work First Manual 115 I.A, State Plan FFY 2026-2028 Financial Rules 1-2). The earliest source found is the 2009 manual section; the value is backdated to 1997, as the other North Carolina TANF parameters are.
  • New nc_tanf_countable_resources: spm_unit_cash_assets (bank, stock and bond assets) less the same assets held by SSI recipients. 10A NCAC 71W .0407(b) counts a parent's resources only if the parent does not receive SSI, and a child's only if the child is in the payment. The SSI test matches nc_tanf_household_size and the NC income variables, and the subtracted components are read from spm_unit_cash_assets.adds. Vehicles, real property and retirement funds are not counted (.0407(e)).
  • New nc_tanf_resources_eligible: countable resources ≤ the limit (the unit is ineligible only when it exceeds $3,000).
  • nc_tanf_eligible now requires nc_tanf_resources_eligible.
  • Known simplifications, noted in the formula: the full checking balance counts (.0407(d)(3)/(e)(5) exclude the month's deposited income), and non-parent adults' resources count, as their income does.

Tests

  • nc_tanf_resources_eligible.yaml: $3,000 is eligible, $3,001 is not.
  • nc_tanf_countable_resources.yaml: $1,000 bank + $1,500 stock + $700 bond = $3,200 and a $20,000 vehicle is excluded; an SSI parent's $4,000 and an SSI child's $4,000 give 0; an SSI parent's $6,000 is removed from a $9,500 total, leaving $3,500.
  • nc_tanf_eligible.yaml: demographically and income eligible but resources above the limit gives false.
  • integration.yaml: a parent and a 17-year-old with no income get 0.5 × 472 × 12 = $2,832 with $3,000 in the bank, and $0 with $5,000 in stocks; an SSI parent with $4,000 and a child aged 10 get 0.5 × 362 × 12 = $2,172; a parent, an SSI child aged 8 with $4,000 and a child aged 5 get 0.5 × 472 × 12 = $2,832.

Locally, the NC TANF tests pass (72) after the SSI exclusion; before it, gov/states/nc passed (411), and the NC partner fixtures and gov/hhs/tanf passed (124). No partner fixture changes.

Found by the PE-vs-PRD comparison (PolicyEngine/prd-comparison): 8 units in the 2025 CPS with more than $3,000 of liquid assets got PE Work First ($23.6k), and PRD, which applies the $3,000 test, paid nothing.

Fixes #10685

axiom: rulespec-us#2081 queued

🤖 Generated with Claude Code

10A NCAC 71W .0407 and the Work First Manual (section 115) make a unit
ineligible when its countable reserve exceeds $3,000. Cash, bank accounts,
stocks, bonds and mutual funds count; vehicles, real property and
retirement accounts do not. nc_tanf_eligible now requires
nc_tanf_resources_eligible.

Fixes #10685

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

codecov Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (aae7f98) to head (db0ee98).
⚠️ Report is 62 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main    #10686   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         3    +2     
  Lines           37        42    +5     
=========================================
+ Hits            37        42    +5     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

DTrim99 commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Apply North Carolina Work First's $3,000 resource limit

Summary

The PR adds the missing Work First reserve test. It creates the parameter gov.states.nc.ncdhhs.tanf.resources.limit ($3,000), nc_tanf_countable_resources (= spm_unit_cash_assets), and nc_tanf_resources_eligible (countable ≤ limit). It also wires the test into nc_tanf_eligible. The $3,000 value, the "ineligible only above $3,000" boundary, and the choice of counted items (bank, stocks, bonds and mutual funds; vehicles, real property and retirement funds excluded) all match 10A NCAC 71W .0407(a), (d) and (e), State Plan Financial Rules 1-2, and Work First Manual section 115. The existing asset variables are reused, and nothing is reinvented.

There is one gap against the binding rule. .0407(b) counts only the resources of parents who do not receive SSI and of children included in the payment. The new variable counts every SPM-unit member's assets, SSI recipients included. The rest of the NC model already excludes SSI recipients from household size and income. As a result, a family with an SSI-recipient parent or child holding more than $3,000 is wrongly denied. A probe at the head confirms this: such a family gets $0 instead of $2,172 a year.

There are also two smaller items. The PR body has no axiom line, and one reference does not follow the CLAUDE.md multi-page rule.

Critical (must fix)

1. SSI recipients' resources are counted, contrary to 10A NCAC 71W .0407(b)

  • Where: policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.py:17-21.

  • What the code does: it returns spm_unit("spm_unit_cash_assets", period.this_year). That adds bank_account_assets, stock_assets and bond_assets for every SPM-unit member.

  • What the rule says: 10A NCAC 71W .0407(b), readopted effective October 1, 2021 (OAH Subchapter 71W, PDF page 6):

    (b) Resources owned by the following budget unit members shall be counted for purposes of eligibility of Work First assistance: (1) Parent, adoptive parent, or stepparent unless the individual receives SSI; (2) If the child is included in the payment, the child's resources shall be counted; …

  • The manual agrees. Work First Manual 115 I.C counts only "individuals who are receiving Work First Family Assistance and those applying to be included in the case". I.D.3 (page 2) says not to count a checking or savings account held jointly with an SSI recipient.

  • The NC model already treats SSI recipients as outside the case:

    • nc_tanf_household_size drops anyone with ssi > 0 or receives_ssi.
    • nc_tanf_countable_earned_income and nc_tanf_countable_gross_unearned_income exclude their income (State Plan Financial Rules 3-4).
    • Only the new resource test pulls them back in.
  • Reproduced at the head with a small YAML probe (3 cases, all passed as written, so the expectations below are the head's actual outputs):

    Household (NC, 2025) Head result Under .0407(b)
    Parent 35 on SSI ($11,000) with $4,000 in the bank; child 10 nc_tanf_household_size 1, unearned income 0, nc_tanf_countable_resources 4,000, nc_tanf_resources_eligible false, nc_tanf 0 countable 0, nc_tanf = 362 × 0.5 × 12 = 2,172
    Same family with no assets nc_tanf 2,172 2,172
    Parent 35 (no income); child 8 on SSI with $4,000 in the bank; child 5 household size 2, countable 4,000, nc_tanf 0 countable 0, nc_tanf = 472 × 0.5 × 12 = 2,832
  • Fix: follow the existing Missouri and South Carolina pattern (mo_tanf_countable_resources, sc_tanf_countable_resources). Subtract the SSI recipients' person-level share from the aggregate, using the same SSI test the NC income variables use:

    def formula(spm_unit, period, parameters):
        # 10A NCAC 71W .0407(b)(1)-(2): a parent's resources count unless the
        # parent receives SSI; a child's count only if the child is in the
        # payment, and SSI recipients are not.
        total = spm_unit("spm_unit_cash_assets", period)
        person = spm_unit.members
        is_ssi_recipient = (person("ssi", period) > 0) | person("receives_ssi", period)
        # This list must mirror spm_unit_cash_assets.adds.
        person_assets = add(
            person, period, ["bank_account_assets", "stock_assets", "bond_assets"]
        )
        excluded = spm_unit.sum(person_assets * is_ssi_recipient)
        return max_(total - excluded, 0)
  • Add tests in nc_tanf_countable_resources.yaml (and an integration case) for the two SSI households above, so the new exclusion is pinned. Add the .0407(b) cite to the variable's reference.

Should address

1. No axiom line in the PR body

  • This is a staff policy change: it adds an eligibility test to a benefit. CLAUDE.md "Axiom Parity" therefore requires a line of the form axiom: … encoded-correct | … encoded | … queued.
  • I found no rulespec-us module or issue for 10A NCAC 71W .0407. Code searches for "71W" and "Work First" in us-nc/ returned nothing for Work First rules.
  • The open pe-parity issue rulespec-us#1947 covers only Work First countable income and payment (State Plan Financial Rules 3, 4, 6 and 8), not the reserve.
  • Fix: file a dispatch-ready pe-parity rulespec-us issue, then add axiom: rulespec-us#<n> queued. The issue should include:
    • the module path and corpus citation for 10A NCAC 71W .0407 (a), (b)(1)-(2), (d) and (e);
    • the verbatim rule text and the required outputs;
    • companion tests taken from the rule, not from PolicyEngine output: $3,000 eligible, $3,001 ineligible, a vehicle excluded, and an SSI parent's resources excluded.

2. A multi-page variable reference lacks the CLAUDE.md page comment, and the binding lists aren't cited

  • Where: policyengine_us/variables/gov/states/nc/ncdhhs/tanf/nc_tanf_countable_resources.py:11-14, 18-20.
  • The comment cites "Work First Manual, section 115, II", but the href opens only wf115.pdf#page=2. That chart runs across file pages 2-4:
    • Page 2 has only burial items, cash and checking.
    • The motor vehicle, real property and retirement exclusions the comment relies on are on page 3.
    • Stocks, bonds and mutual fund shares are on page 4.
  • CLAUDE.md: "Variable reference tuples have no title: put a # PDF pages 61-62, 67 comment above a multi-page href."
  • Fix: add # PDF pages 2-4 above the manual href. Better still, also cite the binding lists in 10A NCAC 71W .0407(d)-(e). The OAH Subchapter 71W PDF has them on file pages 6-7 (comment # PDF pages 6-7). That file is the one the NC income variables already cite.

Suggestions

  1. Non-parent adults and child-only cases. .0407(b) lists only parents and stepparents (non-SSI) and children in the payment, so other adults' resources don't count. Examples are a grandparent caretaker in a child-only case, an adult sibling, or an unmarried partner. The new variable counts every non-SSI SPM-unit member. That matches how the existing NC income variables treat the unit, so it isn't a new inconsistency. Still, please name the limitation in the formula comment, or open a follow-up issue to model case membership for both income and resources.
  2. Checking-account balance. .0407(d)(3) and (e)(5) count only "that portion of a checking account other than the monthly income deposited to meet the family's needs". bank_account_assets has no such split, so the whole balance counts. That's a reasonable data simplification, but the comment at lines 18-20 ("Work First counts cash, checking and savings accounts") reads as if the full balance is the rule. Suggest one line noting the simplification.
  3. References on the parameter.
    • Consider adding the current Work First State Plan, Financial Rules 1-2. It states the $3,000 limit and "All vehicles are excluded", and it is the same plan the other NC TANF variables cite.
    • The Justia link sits behind a Cloudflare challenge for automated fetches. The OAH PDF above holds the same rule text.
    • The manual's document page now links WF-115_ADA.pdf. Its content is the same 2009 Change # 03-09, so the existing link is fine.
  4. Backdating. The value is backdated to 1997 on the strength of a 2009 manual section. The State Plan's "Increase resource limits … pursuant to the change from AFDC to Work First" supports a limit dating from Work First's start. If an early state plan (for example the 2009 or 1997 TANF State Plan) states $3,000, citing it would document 1997-2008 rather than leaving those years to the backdating comment.

Verified correct

  • Law research.
    • 10A NCAC 71W .0407(a): "allowed to reserve resources at a maximum of three thousand dollars ($3,000). The assistance unit is ineligible if the reserve level exceeds this maximum." That supports $3,000 and the <= test.
    • (d) counts cash on hand, savings, the non-living-expense part of checking, and "stocks, bonds, mutual fund shares".
    • (e) excludes motor vehicles, real property, retirement funds, life and burial insurance, household goods, and trust funds.
    • State Plan Financial Rules 1-2 (file page 18) give the $3,000 limit, the readily-convertible test, and "All vehicles are excluded".
    • Manual 115 I.A (page 1) and the II chart (pages 2-4) agree.
    • The limit applies at application and review (manual II.B), and it applies per case. Modelling it on the annual SPM unit matches the rest of the NC model.
  • No source conflict to record for the modelled items. The rule, the plan and the manual agree on every item the code counts or excludes. They disagree on remaining lump-sum balances: excluded by .0407(e)(13), counted by State Plan Financial Rule 9 and the manual chart. No asset variable for lump sums exists, so the PR doesn't touch that conflict. The PR adds no conflict-sounding comments, so the Tie source-conflict markers to the register shared with Axiom #10287 ratchet is unaffected.
  • Variable reuse.
    • spm_unit_cash_assets adds bank_account_assets (checking, savings and money market), stock_assets (stocks and mutual funds, SIPP TVAL_STMF, which excludes retirement accounts) and bond_assets.
    • Vehicles (household_vehicles_value), home equity and real estate are not read, as (e)(8)-(9) require.
    • The same pattern is used by about 40 other state TANF resource tests (DC, NM, KY and others).
  • Entity, period and vectorization. Everything is SPMUnit and YEAR, matching every other NC TANF variable. defined_for = StateCode.NC. The formulas are vectorized. No new state-gated int or enum key, so the NH Add New Hampshire state supplementation for 2026 #10156 pattern doesn't apply. quantity_type = STOCK is set on the countable amount.
  • Mutation coverage.
    • The <= boundary is pinned both ways (3,000 true, 3,001 false).
    • The new & is_resources_eligible term in nc_tanf_eligible is pinned by the new nc_tanf_eligible.yaml case and by the $5,000 integration case.
    • Each cash-asset component affects the 3,200 sum.
    • The vehicle case pins the exclusion against a switch to a vehicle-inclusive measure.
  • Callers. nc_tanf (defined_for = "nc_tanf_eligible") is the only downstream reader. The existing nc_tanf_eligible.yaml cases still hold, because default assets of 0 are ≤ 3,000.
  • Hand checks (10).
    1. Integration, $3,000 in the bank, parent and 17-year-old (2024):
      • The age limit is 18, so the 17-year-old is a child.
      • Size 2 gives a need standard of $472 a month (State Plan p. 18-19). Income is 0.
      • Payment = 0.5 × 472 × 12 = 2,832, which is ≥ the $25 × 12 = 300 minimum.
      • Countable resources 3,000 ≤ 3,000, so eligible: 2,832 ✓
    2. Integration, $5,000 in stocks: 5,000 > 3,000 → ineligible → 0 ✓
    3. nc_tanf_countable_resources: 1,000 + 1,500 + 700 = 3,200, and the $20,000 vehicle is not read ✓
    4. Same case: 3,200 > 3,000 → nc_tanf_resources_eligible false ✓
    5. 3,000 ≤ 3,000 → true ✓
    6. 3,001 > 3,000 → false ✓
    7. nc_tanf_eligible: true & true & false → false ✓
    8. Existing nc_tanf_eligible case 1: true & true & (0 ≤ 3,000) → true, still passes ✓
    9. Probe, SSI parent with $4,000 and child 10:
      • Size 1, need standard $362. Payment = 0.5 × 362 × 12 = 2,172.
      • The head gives 0 because it counts the SSI parent's $4,000 (Critical 1).
    10. Probe, SSI child with $4,000, plus parent and sibling:
      • Size 2. Payment = 0.5 × 472 × 12 = 2,832.
      • The head gives 0 (Critical 1).
  • Changelog. changelog.d/fix-10685-nc-work-first-resources.fixed.md is top-level, with type fixed. ✓
  • Tests are in variable-named files (plus the program's existing integration.yaml), and periods are plain. No Python tests were added. No partner files were touched.
  • Parameter. The description follows the house template, and the label and units are correct. Both references show $3,000 on the anchored page (the .0407(a) text, and wf115.pdf#page=1).

Axiom line assessment

Missing (Should address 1). The PR body has no axiom: line, and none appears in comments. No rulespec-us module or issue exists for 10A NCAC 71W .0407. rulespec-us#1947 (open, pe-parity) covers NC Work First income and payment rules only. A dispatch-ready pe-parity issue for the reserve rule is needed, including the .0407(b) SSI exclusion once Critical 1 is fixed, plus a matching axiom: rulespec-us#<n> queued line (or an encoded module).

CI status

All 38 checks pass at head bf595a7 (re-checked with gh pr checks 10686 at review time). Nothing is pending.

Branch status

  • 2 commits ahead and 10 behind main.
  • git merge-tree --write-tree PolicyEngine/main bf595a768c merges cleanly (tree d3ad403a).
  • Main has not changed any NC TANF variable, parameter or test file since the merge base, and none of the 10 newer main commits touch these code paths.

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.

Requesting changes per the review above: 1 critical (countable resources include SSI recipients' assets, which 10A NCAC 71W .0407(b) leaves out), 2 should (no axiom line; multi-page reference missing its page list), 4 suggestions.

10A NCAC 71W .0407(b) counts a parent's resources only if the parent does
not receive SSI, and a child's only if the child is in the payment. Subtract
SSI recipients' person-level cash assets from spm_unit_cash_assets, reading
the components from that variable's adds, as MO and SC TANF do.

Cite .0407(b), (d) and (e) from the OAH Subchapter 71W PDF (pages 6-7), add
the PDF page comment for the Work First Manual 115 chart (pages 2-4), add
the FFY 2026-2028 State Plan Financial Rules 1-2 reference to the limit, and
name the checking-balance and non-parent-adult simplifications. Add
variable-level and integration tests for SSI-recipient parent and child
households.

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

Copy link
Copy Markdown
Collaborator Author

Thanks for the careful review. All items are addressed in db0ee98:

The NC TANF tests pass locally (72). Could you take another look when you have a moment?

@DTrim99

DTrim99 commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator

PR Review (round 2): Apply North Carolina Work First's $3,000 resource limit

Summary

One author commit (db0ee98) addresses every round-1 finding. Round 1 was at bf595a7 on 2026-11-07, with 1 critical, 2 should and 4 suggestions.

  • Critical 1 is fixed. nc_tanf_countable_resources now subtracts SSI recipients' bank, stock and bond assets from spm_unit_cash_assets, as 10A NCAC 71W .0407(b)(1)-(2) requires. It identifies SSI recipients with the same ssi > 0 | receives_ssi test the NC household-size and income variables use. Both round-1 probe households are now pinned at their correct values: $2,172 for the SSI parent and $2,832 for the SSI child, with countable resources of 0 in each. Those tests would fail at the round-1 head, which gave $0 and $4,000.
  • Both should items are fixed. rulespec-us#2081 is open, labelled pe-parity, dispatch-ready and matches the head, and the PR body has axiom: rulespec-us#2081 queued. The multi-page references now carry # PDF pages comments and cite .0407(b), (d) and (e).
  • Suggestions. Three are fixed. The fourth (backdating) was declined with a reason I accept.

I found no new critical or should items. Two optional suggestions follow. CI is 38/38 green, and the branch merges cleanly with current main.

Prior findings

Finding Status Evidence
C1. SSI recipients' resources counted, contrary to .0407(b) Fixed See "C1 in detail" below the table.
S1. No axiom line / no rulespec-us issue Fixed The PR body has axiom: rulespec-us#2081 queued. rulespec-us#2081 is OPEN and labelled pe-parity, and it has a module path, corpus status, verbatim law, required outputs and 7 companion cases computed from the rule. It describes the head's SSI exclusion (see Axiom).
S2. Manual 115 II reference spans PDF pages 2-4 without a page comment; binding lists not cited Fixed nc_tanf_countable_resources.py:13-16: # PDF pages 6-7 above the OAH Subchapter 71W PDF (#page=6, which holds .0407(a)-(e)), and # PDF pages 2-4 above wf115.pdf#page=2. This is the CLAUDE.md form for variable reference tuples.
Sugg. 1. Non-parent adults and child-only cases Fixed (documented) nc_tanf_countable_resources.py:35-38 names the limitation (grandparent caretaker, adult sibling, unmarried partner) and its consistency with the NC income variables. rulespec-us#2081 lists it under "Interpretations and gaps".
Sugg. 2. Checking-account balance Fixed (documented) nc_tanf_countable_resources.py:24-27 notes that .0407(d)(3)/(e)(5) exclude the month's deposited income and that the full bank_account_assets balance counts.
Sugg. 3. References on the parameter Fixed resources/limit.yaml adds "North Carolina TANF State Plan FFY 2026-2028, Financial Rules 1-2" (efs-wf-06-2025a2/open#page=18). That page shows the $3,000 limit and "All vehicles are excluded", and the title has no page text. The OAH PDF is now on the variable. The Justia link (Cloudflare-blocked for automated fetches) is still listed beside it and is the parameter's only copy of the rule text. That's optional to change.
Sugg. 4. Backdating 1997-2008 Declined with reason (accepted) The author found no plan stating $3,000 earlier than the 2016-2019 plan, which rulespec-us#2081 places at file page 34. The parameter comment documents the backdating to 1997, as the other NC TANF parameters do.

C1 in detail

  • The fix. nc_tanf_countable_resources.py:28-48 computes max_(spm_unit_cash_assets − Σ SSI-recipient (bank + stock + bond), 0), with is_ssi_recipient = (ssi > 0) | receives_ssi (line 40).
  • Mutation: the round-1 head fails the new expectations.
    • The new integration cases expect nc_tanf 2,172 and 2,832. The round-1 probe gave 0 for both.
    • nc_tanf_countable_resources 0 in both new variable-level cases. The round-1 probe gave 4,000.
  • Each arm of the SSI test is pinned separately.
    • The ssi > 0 arm: the ssi: 11_000 cases fail without it, giving 4,000 instead of 0, because receives_ssi has no formula and defaults to false.
    • The receives_ssi arm: the partial case (receives_ssi: true, modeled ssi = 0) fails without it, giving 9,500 instead of 3,500.

New findings

Critical

None.

Should address

None.

Suggestions

  1. The max_(…, 0) floor is not pinned.
    • Where: nc_tanf_countable_resources.py:48.
    • Deleting the floor fails no test. It is reachable only when the inputs disagree, for example when spm_unit_cash_assets is supplied directly below the person-level holdings of an SSI recipient, or when that variable is neutralized.
    • Even then it cannot change nc_tanf_resources_eligible or nc_tanf, because a negative count is still ≤ $3,000. It mirrors MO and SC TANF and the fix suggested in round 1, so it is not a should.
    • Optional pin: spm_unit_cash_assets: 1_000 on the unit, plus an SSI parent with bank_account_assets: 4_000, should give countable 0.
  2. rulespec-us#2081's cross-reference sentence overstates the overlap.
    • It says "Cases 1-5 and 7 match PE-US tests in the PR (case 1 and 2 at the variable level and in the integration file…)".
    • Case 2 ($3,001) appears only at the variable level, as a direct nc_tanf_countable_resources input, not in the integration file.
    • Case 3 ($1,000 of savings plus a $20,000 vehicle gives 1,000) has no PR counterpart. The PR's vehicle case is the $3,200 case.
    • The companion expectations are derived from the rule, so dispatch-readiness is unaffected. A one-line correction would keep the mapping accurate.

Verified

  • Hand checks of every new or changed expectation. The need standard is $362 for one person and $472 for two, and the payment is 0.5 × (need − income) (WF-114 p. 5).
    1. nc_tanf_countable_resources.yaml, SSI parent ($4,000 bank) and child 10: 4,000 − 4,000 = 0. 0 ≤ 3,000 → eligible true ✓
    2. Same file, parent; SSI child 8 ($4,000); child 5: 4,000 − 4,000 = 0, so true ✓
    3. Same file, partial case: parent receives_ssi holds 4,000 bank + 2,000 stock, and the child holds 3,500 bank.
      • Total 9,500, less 6,000 = 3,500.
      • 3,500 > 3,000 → false ✓
    4. integration.yaml, SSI parent with $4,000 and child 10:
      • Household size 2 − 1 = 1. Unearned income 0 (SSI excluded). Countable 0, eligible true.
      • nc_tanf = 0.5 × (362 − 0) × 12 = 181 × 12 = 2,172 ✓ This matches the round-1 expected value.
    5. integration.yaml, parent; SSI child 8 with $4,000; child 5:
      • Size 3 − 1 = 2. Countable 0, eligible true.
      • nc_tanf = 0.5 × 472 × 12 = 236 × 12 = 2,832 ✓ This matches the round-1 expected value.
    6. The unchanged round-1 expectations still hold, because the fix does not touch households without SSI recipients: 3,200 / false, 3,000 / true, 3,001 / false, 2,832 at $3,000, and 0 at $5,000.
  • Probe at the head (a small household simulation with three cases):
    • (a) The partial case reproduces 3,500 / false.
    • (b) A parent with both ssi > 0 and receives_ssi: true, holding $1,000, plus a child holding $5,000, gives countable 5,000 and ineligible, as .0407(b) requires.
      • receives_ssi is a monthly bool, and read over the year it returns a bool array, not a count of months.
      • So (ssi > 0) | receives_ssi stays 0/1 and the subtraction is never multiplied.
    • (c) With only the SPM-unit aggregate supplied ($4,000) and an SSI parent, countable stays 4,000. This is the aggregate fallback the comment at lines 32-34 documents, identical to MO and SC. In microdata the person-level asset variables are populated, so the exclusion applies there.
  • SSI identification and reuse.
    • No reusable person-level "NC SSI recipient" variable exists. is_ssi_recipient_for_medicaid is gated by Medicaid state classification and isn't appropriate.
    • The inline test is character-for-character the one in nc_tanf_countable_earned_income, nc_tanf_countable_gross_unearned_income and nc_sa_eligible. It is equivalent to nc_tanf_household_size's (ssi <= 0) & ~receives_ssi, so the three NC TANF measures (size, income, resources) now exclude the same people.
    • No new dependency cycle: nc_tanf_household_size already reads ssi.
  • Components read from spm_unit_cash_assets.adds.
    • That attribute is a plain list (bank_account_assets, stock_assets, bond_assets), so the subtraction can't drift from the aggregate.
    • No reform in the repo redefines spm_unit_cash_assets.
    • This is the only runtime .adds read in the repo. It's acceptable here and more drift-proof than the MO/SC hard-coded list.
  • Entity, period and vectorization. Person values are summed to the SPM unit with spm_unit.sum. ssi (monthly) and receives_ssi (monthly) are read over the year, spm_unit_cash_assets and the asset components are yearly, and there is no scalar branching. period.this_year was changed to period on a YEAR variable, which is equivalent. There is no new state-gated int or enum key, so the NH Add New Hampshire state supplementation for 2026 #10156 pattern doesn't apply.
  • References (CLAUDE.md rules).
    • Multi-page hrefs open the first page and carry the # PDF pages comment; no page list appears in any href.
    • The parameter's new State Plan entry is a single page with no page text in its title.
    • The OAH PDF and Justia are distinct documents (the same rule from two publishers), not one source split by #page=.
  • Source-conflict ratchet (Tie source-conflict markers to the register shared with Axiom #10287). No added comment in the PR's files matches main's CONFLICT_COMMENT_RE. The new wording ("Simplification", "Limitation", "does not list") is not flagged, and none of the PR's files are in KNOWN_UNMARKED. The lump-sum disagreement (.0407(e)(13) vs State Plan Financial Rule 9) remains untouched by the code. rulespec-us#2081 notes it for the module.
  • PR body. It matches the head: the SSI exclusion, the .adds source, the test list and the stated simplifications. The changelog fragment is unchanged and top-level (fix-10685-nc-work-first-resources.fixed.md). No partner files are touched, and no Python tests are added.

Axiom

axiom: rulespec-us#2081 queued: valid.

  • Encode North Carolina Work First reserve limit (10A NCAC 71W .0407; State Plan Financial Rules 1-2) (PE parity, policyengine-us#10686) TheAxiomFoundation/rulespec-us#2081, "Encode North Carolina Work First reserve limit (10A NCAC 71W .0407; State Plan Financial Rules 1-2)", is OPEN and labelled pe-parity. It was created 2026-11-08 and has no later edits.
  • Dispatch-ready.
    • Proposed module us-nc/regulations/10a-ncac/71w/0407.yaml, plus an extension of the Add Kansas state income tax #1947 State Plan module.
    • Corpus status per source: 71W is not ingested (ingest step and sha256 given), and the State Plan is locked as us-nc/policy/2026-09-13-tanf-state-plan.
    • Verbatim text of .0407(a), (b)(1)-(2), (d) and (e) and of Financial Rules 1-2. Required outputs and invariants.
    • Seven companion cases hand-computed from the rule text, including the SSI-parent (0), SSI-child (0) and partial (3,500) cases.
    • The blocker is recorded: 71W is not ingested, and no encoder run is approved.
  • Matches the head. It describes spm_unit_cash_assets less the components held by members with ssi > 0 or receives_ssi, floored at 0. The gaps it lists (non-parent adults, checking split, joint ownership, lump sums) are the head's simplifications. The one inaccuracy is the cross-reference sentence (Suggestion 2).

CI

  • 38/38 checks pass at head db0ee98, re-checked at the end of this review; nothing is pending.
  • Run 42500611999 (pull_request, 2026-11-08 16:34 UTC) includes Baseline and Contrib states-shards 1-4. The new NC TANF YAML cases are therefore exercised against the merge with main as of that run.

Branch

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.

Round 2: the SSI-asset critical, the axiom line and the reference page list are all fixed and pinned; CI is green. Two optional suggestions remain.

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

Reviewed at db0ee98 against the primary sources. The limit and the counting rules are right.

  • Limit: 10A NCAC 71W .0407(a) (OAH Subchapter W rules PDF, pages 6-7): "shall be allowed to reserve resources at a maximum of three thousand dollars ($3,000). The assistance unit is ineligible if the reserve level exceeds this maximum." countable_resources <= p.limit matches, and the 3,000 / 3,001 cases pin the operator. State Plan FFY 2026-2028 Financial Rules 1 (page 18) and Work First Manual 115 I.A (page 1) say the same.
  • Applicants: Manual 115 I.C.1 counts the resources of those receiving and "those applying to be included in the case", so one test for both, with no is_tanf_enrolled split, is correct.
  • What counts: .0407(d) counts cash, savings, checking and stocks, bonds and mutual fund shares, and .0407(e) excludes vehicles, real property and retirement funds. spm_unit_cash_assets (bank, stock, bond) matches. The test excludes the $20,000 vehicle.
  • SSI exclusion: .0407(b)(1)-(2) cover a parent "unless the individual receives SSI" and a child only "if the child is included in the payment". (ssi > 0) | receives_ssi matches nc_tanf_household_size and the NC income variables. Subtracting from the aggregate keeps SPM-level spm_unit_cash_assets inputs working, the same approach as mo_tanf_countable_resources. Reading the components from spm_unit_cash_assets.adds avoids the hand-copied list MO has to keep in sync.
  • Test arithmetic: 0.5 × 472 × 12 = 2,832 and 0.5 × 362 × 12 = 2,172 both check out.

Non-blocking, for a follow-up: the documented non-parent-adult limitation is a real gap. .0407(b) lists only parents, stepparents and children in the payment, so a grandparent's savings in a multigenerational SPM unit shouldn't count, but here they can make the family ineligible. NC's household size and income already treat every non-SSI SPM member as in the unit, though, so fixing only resources would be inconsistent. It belongs in an NC assistance-unit composition fix across size, income and resources, as Missouri does with mo_tanf_non_parent_caretaker_budget_member. Fine to leave out of this PR.

Approving.

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.

North Carolina Work First has no resource test

3 participants