Skip to content

Add Marin County, CA General Relief program#8583

Open
hua7450 wants to merge 11 commits into
PolicyEngine:mainfrom
hua7450:ca-marin-gr
Open

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

Conversation

@hua7450

@hua7450 hua7450 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

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 (qualified-status list parameter) checked only for the tax-unit head or spouse (the applicant); the unit is eligible if ≥ 1 such 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); the limit is evaluated monthly so the 2025-07-01 increase applies mid-year
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
No dependent children (adults only) Live HHS page; Std §II.C, p.10 Unit ineligible if it contains a dependent child (is_tax_unit_dependent & is_child). Tax-dependency approximates ≥50% custody; the married/emancipated-under-18 exception is not modeled.

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.
  • CalWORKs is not counted as income: an earlier version added CalWORKs cash (ca_tanf) to net income to exclude families with children, but that only caught families on CalWORKs and missed dependent households CalWORKs-ineligible for non-income reasons (e.g. an over-limit vehicle leaves ca_tanf = 0). Families with children are now excluded directly by the no-dependent-children eligibility gate (see Eligibility), so CalWORKs is not added to income.
  • No double-dipping with SSI/CAPI/CalWORKs: SSI/SSP recipients are categorically barred (ssi > 0); CalWORKs recipients have dependent children and are excluded by the no-dependents gate; CAPI (California's SSI-equivalent for immigrants) needs no separate check — CAPI recipients are non-qualified noncitizens who fail the GR citizenship requirement, so the immigration test already prevents any GR+CAPI overlap.
  • 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 is applied inside ca_marin_general_relief_net_income; the income test and benefit subtraction read net income at the monthly period, so PolicyEngine auto-divides the annual figure by 12 (no explicit ÷ 12 in the formula).
  • 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 directly in the top-level ca_marin_general_relief (MONTH).

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 (8 cases)
REQ-005 Unit-level ≥ 1 immigration-eligible inlined any() in ..._eligible integration cases 7, 16, 21
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 (5 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) ca_marin_general_relief, ..._max_grant ..._max_grant.yaml (3), integration.yaml (22 cases)
REQ-014 PRUCOL approximated via humanitarian list qualified_immigration_status.yaml ..._immigration_status_eligible_person ..._immigration_status_eligible_person.yaml
REQ-019 Adults without dependent children dependent-child gate (is_tax_unit_dependent & is_child) in ..._eligible ..._eligible.yaml (dependent-child case) + integration Case 22

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
Exact <50%-custody determination; married/emancipated-under-18 exception; §II.L sanction / 48-month-clock specifics Std §II.C; Std §II.L; Live HHS page The no-dependent-children rule is now gated (a unit with a dependent child is ineligible). <50% custody is approximated via tax-dependency; the married/emancipated-under-18 exception and the §II.L sanction / 48-month-clock details are not separately modeled.
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
    ├── 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
    │   ├── 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_max_grant.yaml
    ├── integration.yaml                            # 22 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  # 8 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  # 5 cases incl. floor

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

9 parameters, 13 variables, 12 test files (74 YAML tests passing), plus the changelog fragment.

Test plan

  • 74 YAML tests pass (policyengine-core test policyengine_us/tests/policy/baseline/gov/local/ca/marin/ -c policyengine_us)
  • All 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)
  • Integration tests compute SSI and CalWORKs (ca_tanf) from the model and assert them as outputs (no stubbed benefit inputs)
  • 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

codecov Bot commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

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

Additional details and impacted files
@@             Coverage Diff              @@
##             main     #8583       +/-   ##
============================================
+ Coverage   77.77%   100.00%   +22.22%     
============================================
  Files           1        13       +12     
  Lines           9       169      +160     
============================================
+ Hits            7       169      +162     
+ Misses          2         0        -2     
Flag Coverage Δ
unittests 100.00% <100.00%> (+22.22%) ⬆️

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.

hua7450 and others added 8 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>
- Apply the July 1, 2025 liquid-asset limit increase by month: the limit and
  eligibility variables are now month-defined, so $400/$800 takes effect from
  that month instead of being masked by the January value of a year-defined
  parameter lookup (the $200/$400 -> $400/$800 transition).
- Restrict the immigration-status check to the applicant (tax-unit head or
  spouse) per Standards Section II.E, so a dependent's qualifying status no
  longer makes the unit eligible.
- Use spm_unit_is_married for couple detection in the grant and resource
  limits.
- Cite Standards of Aid Section II.H for the liquid-asset parameters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-income conversion

- personal_property_limit/_eligible: definition_period YEAR -> MONTH, reading the
  year-defined is_married flag and personal_property stock via period.this_year
  (consistent with the liquid-asset pair and the rest of the eligibility chain);
  dedicated tests moved to period 2026-01.
- base_amount/income_eligible: read net_income at the monthly period so the engine
  auto-divides the annual figure, instead of period.this_year / MONTHS_IN_YEAR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Families with minor children are served by CalWORKs, not General Relief. The
Standards exclude them not via a demographic gate but through the program-of-
last-resort mechanism: applicants must pursue all potentially available income
(Sec II.B / II.Q), and CalWORKs recipients with children on the cash allowance
are barred (Sec II.L). Model this by counting CalWORKs (ca_tanf) as unit-level
unearned income in ca_marin_general_relief_net_income, so a family receiving
CalWORKs above the grant is income-ineligible. A family not receiving CalWORKs
cash can still qualify, matching Sec II.L (no hard no-dependents gate).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Collapse the base_amount pass-through into ca_marin_general_relief and the
  immigration any() wrapper into ca_marin_general_relief_eligible (inlined),
  removing two single-purpose variables and their tests.
- Document the single-rate assumption for mixed-status couples in max_grant
  (Standards are silent; eligible spouse aided at the single rate, ineligible
  spouse's income still counted) and note that GR+CAPI overlap is already
  prevented by the immigration eligibility check.
- Rewrite integration tests so SSI and CalWORKs (ca_tanf) are computed by the
  model and asserted as outputs (a real aged SSI recipient; a real CalWORKs
  family) rather than stubbed as inputs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hua7450 hua7450 marked this pull request as ready for review June 7, 2026 02:14
The CalWORKs-as-income approach only excluded families on CalWORKs, missing
dependent households that are CalWORKs-ineligible for non-income reasons (e.g.
a vehicle over the CalWORKs limit, which leaves ca_tanf = 0 yet still pays GR).
Replace it with an explicit no-dependents gate: a unit containing a dependent
child (a tax-unit dependent under 18) is ineligible, per Marin HHS's
adults-without-dependent-children rule. Tax-dependency approximates the >=50%
custody rule. Remove the now-redundant ca_tanf term from net income (any
CalWORKs recipient has a dependent child and is caught by the gate).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hua7450 hua7450 requested a review from PavelMakarchuk June 7, 2026 21:17
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