Skip to content

Add Marin County, CA General Relief program#8583

Draft
hua7450 wants to merge 4 commits into
PolicyEngine:mainfrom
hua7450:ca-marin-gr
Draft

Add Marin County, CA General Relief program#8583
hua7450 wants to merge 4 commits into
PolicyEngine:mainfrom
hua7450:ca-marin-gr

Conversation

@hua7450
Copy link
Copy Markdown
Collaborator

@hua7450 hua7450 commented Jun 3, 2026

Summary

Implements California Marin County General Relief (GR) in PolicyEngine — a county-funded and county-administered cash-aid (loan) program of last resort, mandated statewide by CA Welfare & Institutions Code §17000 et seq. and operated by the Marin County Department of Health & Human Services under Board-approved Program Policies and Standards.

This models the post-July-1-2025 version of the program. The July 1, 2025 reform raised liquid-asset limits and eliminated Income-in-Kind reductions and work-requirement sanctions; all parameters are effective 2025-07-01 (single era).

The program is implemented as a local program at gov/local/ca/marin/general_relief and is intentionally left un-wired into household-level benefit aggregators, matching the existing LA County and Riverside County General Relief implementations (both of which exist as standalone SPMUnit variables and are not wired into any household aggregator).

Closes #8582

Regulatory Authority

Program Overview

  • Administration: County-administered (Marin County HHS, Division of Social Services)
  • Funding: County funds (legally a loan / Interim Assistance Reimbursement when the client later receives SSI or CAPI — the loan/repayment nature is not modeled)
  • Type: Cash aid of last resort for adults without dependent children

Eligibility Tests

Requirement Source How Modeled
Must reside in Marin County Standards §II.A; Live HHS page in_marin = county_str == "MARIN_COUNTY_CA"; all GR variables chain defined_for = "in_marin"
Head/applicant must be aged ≥ 18 Std §II.C, p.10; Live HHS page ("Adults aged 18 or older") age_head >= 18 (parameter eligibility/age_threshold.yaml). Married/emancipated-under-18 exception not modeled (rare).
Citizen / LPR / PRUCOL Std §II.E, p.10; Live HHS page Person-level immigration_status in a qualified-status list parameter; unit eligible if ≥ 1 applicant qualifies. PRUCOL approximated (see Not Modeled).
Liquid (cash & bank) assets ≤ $400 single / $800 couple News release; Live HHS page; Brochure (raised from $200 / $400) spm_unit_cash_assets <= where(married, $800, $400)
Personal property ≤ $600 single / $1,200 couple Std §II.G, p.11; Live HHS page add(spm_unit, period, ["personal_property"]) <= where(married, $1,200, $600)
Net countable income ≤ max grant (inclusive) Std §II.I, p.11; Brochure ("income not higher than $387/$636") Monthly net income <= monthly max grant. The brochure phrases the limit as "not higher than," so the at-or-below boundary is inclusive (<=).
SSI/SSP recipients ineligible Std §II.I, p.11 Unit ineligible if any member has ssi > 0

The top-level ca_marin_general_relief_eligible (SPMUnit, MONTH) ANDs all of the above sub-tests.

Income

  • Gross countable income (ca_marin_general_relief_gross_income, Person) sums an income_sources list parameter — earned income, self-employment income, unemployment compensation, state disability insurance, veterans' benefits, and Social Security. SSI is excluded from the list because SSI recipients are categorically ineligible (including it would be moot and could mask the categorical bar).
  • Net countable income (ca_marin_general_relief_net_income, SPMUnit) = max(gross income − mandatory withholdings, 0), using spm_unit_paycheck_withholdings (FICA = Social Security + Medicare, plus federal and state income tax). The Standards allow mandatory deductions only — there is no general earned-income disregard.
  • Documented limitation: spm_unit_paycheck_withholdings does not include the employee SDI/UI contributions, which the Standards also list as mandatory deductions. We don't subtract SDI/UI at the moment (matches the LA County GR proxy). The net-income floor at 0 and the monthly conversion (annual net income ÷ MONTHS_IN_YEAR) are applied before the income test and benefit subtraction.
  • Income-eligibility boundary: inclusive <= — a household with net income exactly equal to the grant is income-eligible (and receives a $0 partial grant).

Benefit Calculation

Category Monthly Max Grant Source
Single individual $387 Std §III.F, p.17; Live HHS page; Brochure
Married couple $636 Std §III.F, p.17; Live HHS page; Brochure
  • The married-couple amount is stored directly as $636 — it is NOT 2× the single rate ($636 ≠ $774).
  • The couple rate applies only when the unit is a married couple and both members are immigration-eligible; if one spouse is immigration-ineligible, the unit falls back to the single rate (mirrors LA County GR and avoids the defined_for half-benefit trap).
  • Benefit = max(max grant − monthly net countable income, 0), computed inside ca_marin_general_relief_base_amount (MONTH) and surfaced through the top-level ca_marin_general_relief (MONTH, add-only) so there is no MONTH/YEAR subtraction mismatch.

Requirements Coverage

REQ Description Parameter Variable Test
REQ-001 Marin residence in_marin in_marin.yaml
REQ-002 Top-level eligibility (ANDs all) ca_marin_general_relief_eligible eligibility/ca_marin_general_relief_eligible.yaml (7 cases)
REQ-003 Age ≥ 18 eligibility/age_threshold.yaml (18) ca_marin_general_relief_age_eligible eligibility/ca_marin_general_relief_age_eligible.yaml
REQ-004 Person qualified immigration status qualified_immigration_status.yaml ..._immigration_status_eligible_person ..._immigration_status_eligible_person.yaml (7 cases)
REQ-005 Unit-level ≥ 1 immigration-eligible ..._immigration_status_eligible ..._immigration_status_eligible.yaml (3 cases)
REQ-006/007 Liquid assets ≤ $400 / $800 eligibility/limit/liquid_assets/{single,married}.yaml ..._liquid_asset_limit, ..._liquid_asset_eligible ..._liquid_asset_limit.yaml, ..._liquid_asset_eligible.yaml
REQ-008 Personal property ≤ $600 / $1,200 eligibility/limit/personal_property/{single,married}.yaml ..._personal_property_limit, ..._personal_property_eligible ..._personal_property_limit.yaml, ..._personal_property_eligible.yaml
REQ-009 Gross income (SSI excluded) income_sources.yaml ..._gross_income covered via net income + integration
REQ-010 Net = max(gross − withholdings, 0) ..._net_income income/ca_marin_general_relief_net_income.yaml (4 cases incl. floor)
REQ-011 Income ≤ max grant (inclusive <=) ..._income_eligible eligibility/ca_marin_general_relief_income_eligible.yaml (6 cases incl. boundary)
REQ-012 SSI/SSP recipients barred (in ..._eligible: ~(ssi > 0)) ..._eligible.yaml + integration Case 6
REQ-013/013a Benefit = max(grant − net, 0) amount/{single,married}.yaml (387 / 636) ..._base_amount, ca_marin_general_relief, ..._max_grant ..._base_amount.yaml (4), ..._max_grant.yaml (3), integration.yaml (16 cases)
REQ-014 PRUCOL approximated via humanitarian list qualified_immigration_status.yaml ..._immigration_status_eligible_person ..._immigration_status_eligible_person.yaml
REQ-019 No dependent children in GR unit documented note (GR test households contain no children); no coded gate per scope

15 in-scope requirements (REQ-001..014 + REQ-019). Coverage is ~100% of in-scope requirements.

Not Modeled (by design)

What Source Why Excluded
6-month / 12-month employable cumulative time limit Std §I.G, p.8; News release PolicyEngine doesn't track cumulative months of receipt at the moment (known framework limitation)
Work-program participation; fleeing-felon; probation/parole & incarceration; CalWORKs-sanction; student financial-aid rules; responsible-relative & sponsor deeming; real-property look-back; SSN-application; must-apply-for-other-aid as a hard gate; IAR loan-repayment nature Standards §§II.B, II.D, II.F, II.J–II.N Out of household-model scope / not simulatable at the moment
Income-in-Kind reductions and work-requirement sanctions News release; Std §II.P (superseded) Eliminated by the July 1, 2025 reform — not active rules
No-dependents / <50%-custody demographic restriction Live HHS page; Brochure Documented limitation, not coded as a gate (matches LA County GR); GR test households contain no children
Exact PRUCOL status Std §II.E, p.10 No PRUCOL enum member exists; approximated via humanitarian immigration statuses (refugee, asylee, Cuban/Haitian entrant, deportation-withheld, conditional entrant, parolee), excluding undocumented/DACA/TPS
SDI/UI mandatory deductions Std §II.I, p.11 spm_unit_paycheck_withholdings covers FICA + income tax but not SDI/UI; we don't subtract SDI/UI at the moment (matches LA County GR)
Household-aggregator wiring Left un-wired, matching the existing LA County and Riverside County GR implementations

Files Added

policyengine_us/parameters/gov/local/ca/marin/general_relief/
├── amount/
│   ├── single.yaml                                 # $387/mo
│   └── married.yaml                                # $636/mo (stored directly, not 2×)
├── eligibility/
│   ├── age_threshold.yaml                          # 18
│   └── limit/
│       ├── liquid_assets/
│       │   ├── single.yaml                         # $400
│       │   └── married.yaml                        # $800
│       └── personal_property/
│           ├── single.yaml                         # $600
│           └── married.yaml                        # $1,200
├── income_sources.yaml                             # countable income list (excludes SSI)
└── qualified_immigration_status.yaml               # PRUCOL-approximation status list

policyengine_us/variables/gov/local/ca/marin/
├── in_marin.py
└── general_relief/
    ├── ca_marin_general_relief.py                  # top-level benefit (add-only)
    ├── ca_marin_general_relief_base_amount.py      # max(grant − monthly net income, 0)
    ├── ca_marin_general_relief_max_grant.py
    ├── eligibility/
    │   ├── ca_marin_general_relief_eligible.py
    │   ├── ca_marin_general_relief_age_eligible.py
    │   ├── ca_marin_general_relief_income_eligible.py
    │   ├── immigration/
    │   │   ├── ca_marin_general_relief_immigration_status_eligible_person.py
    │   │   └── ca_marin_general_relief_immigration_status_eligible.py
    │   ├── liquid_assets/
    │   │   ├── ca_marin_general_relief_liquid_asset_limit.py
    │   │   └── ca_marin_general_relief_liquid_asset_eligible.py
    │   └── personal_property/
    │       ├── ca_marin_general_relief_personal_property_limit.py
    │       └── ca_marin_general_relief_personal_property_eligible.py
    └── income/
        ├── ca_marin_general_relief_gross_income.py
        └── ca_marin_general_relief_net_income.py

policyengine_us/tests/policy/baseline/gov/local/ca/marin/
├── in_marin.yaml
└── general_relief/
    ├── ca_marin_general_relief_base_amount.yaml
    ├── ca_marin_general_relief_max_grant.yaml
    ├── integration.yaml                            # 16 cases
    ├── eligibility/
    │   ├── ca_marin_general_relief_eligible.yaml   # 7 cases
    │   ├── ca_marin_general_relief_age_eligible.yaml
    │   ├── ca_marin_general_relief_income_eligible.yaml  # 6 cases incl. boundary
    │   ├── immigration/
    │   │   ├── ca_marin_general_relief_immigration_status_eligible_person.yaml  # 7 cases
    │   │   └── ca_marin_general_relief_immigration_status_eligible.yaml          # 3 cases
    │   ├── liquid_assets/
    │   │   ├── ca_marin_general_relief_liquid_asset_limit.yaml
    │   │   └── ca_marin_general_relief_liquid_asset_eligible.yaml
    │   └── personal_property/
    │       ├── ca_marin_general_relief_personal_property_limit.yaml
    │       └── ca_marin_general_relief_personal_property_eligible.yaml
    └── income/
        └── ca_marin_general_relief_net_income.yaml  # 4 cases incl. floor

changelog.d/ca-marin-gr.added.md

9 parameters, 15 variables, 14 test files (69 YAML tests passing), plus the changelog fragment.

Test plan

  • 69 YAML tests pass (policyengine-core test policyengine_us/tests/policy/baseline/gov/local/ca/marin/ -c policyengine_us)
  • All 13 GR variables run through full-CPS Microsimulation() and a synthetic mixed population with no exceptions (verifies vectorized county-string comparison, immigration-list np.isin, and YEAR/MONTH period mixing)
  • make format clean
  • CI passes

hua7450 and others added 2 commits June 3, 2026 12:36
Scaffolds the branch for implementing Marin County, CA General Relief
(General Assistance) under California Welfare and Institutions Code 17000.

Closes PolicyEngine#8582

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Post-2025-07-01 version: flat two-tier grant ($387 single / $636 couple)
minus net countable income, with liquid-asset, personal-property, age,
immigration, and SSI-ineligibility eligibility tests. Local program under
gov/local/ca/marin/general_relief, un-wired (matches LA/Riverside).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (5c607f0) to head (76aa59e).
⚠️ Report is 8 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##              main     #8583    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files            4        15    +11     
  Lines           67       188   +121     
  Branches         1         0     -1     
==========================================
+ Hits            67       188   +121     
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 Sentry.
📢 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.

hua7450 and others added 2 commits June 3, 2026 13:56
- Add non-Marin $0 end-to-end test (exercises defined_for=in_marin), plus
  couple over-asset and personal-property-fail integration cases.
- Document couple-grant assumption (max_grant) and net-income applicant/
  recipient simplification (income_eligible). No logic changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Add Marin County, CA General Relief program

1 participant