Skip to content

Guard county-keyed lookups in VT renter credit, MN CCAP, WI Shares and MD CCS - #10116

Open
MaxGhenis wants to merge 7 commits into
mainfrom
fix-county-lookup-guards
Open

MaxGhenis wants to merge 7 commits into
mainfrom
fix-county-lookup-guards

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Problem

defined_for masks a formula's output, but policyengine-core 3.32.15 runs the formula over the whole population and skips it only when the mask is all false. A county key missing from a county-keyed parameter table therefore raises ParameterNotFoundError whenever the simulation also holds a household the table doesn't cover. This follows #10113 (the WA property tax exemption) and comes from the same 51-state probe.

Variable Crashes on main when
vt_renter_credit any non-VT household shares the simulation; a VT household has county UNKNOWN or a county belonging to another state; a tax unit has 9+ people (the tables cover sizes 1–8), even a lone VT household
mn_ccap_provider_rate an MN household has county UNKNOWN or a county belonging to another state
wi_shares_hourly_max_rate, wi_shares_monthly_max_rate a WI household has county UNKNOWN or a county belonging to another state
md_ccs_payment_rate an MD household has county UNKNOWN or a county belonging to another state

Changes

  • County guard. Each formula checks that the county belongs to its state with where(in_state & county_has_state_suffix(county, "<ST>"), county, "<FALLBACK>_COUNTY_<ST>"). This guards out-of-state rows, UNKNOWN counties and counties belonging to another state. The fallbacks remain Addison (VT), Hennepin (MN), Adams (WI) and Allegany (MD). VT switches from the county enum to county_str to match the other guards; the keys are the same.
  • The UNKNOWN and mismatched-county fallbacks are placeholders, not estimates. For an in-state household with county UNKNOWN or a county belonging to another state, VT, WI and MD use their first-listed county and MN uses Hennepin. The sources prescribe the actual county's rate and give no fallback, so these return an arbitrary in-state value instead of crashing. A household with no county input takes the variable's default county instead (for MN, Aitkin), which can differ: an MN infant in 45 hours a week of family care gets $888.33 a month with county omitted and $1,083.33 with UNKNOWN. No household in the default dataset has an unknown or mismatched county.
  • Size-cap citations. The department's calculators cap the income-limit household size at 8 in every year the parameter covers: TY2021 and TY2022, Calculator sheet, cells G10–G12, and the cited TY2023–2025 calculators, cells G11–G13. Both earlier workbooks were downloaded and their formulas verified directly; G10/G11 cap the income-limit lookup at 8 and G12 caps the credit-amount lookup at 4.
  • VT household size. A new parameter, gov.states.vt.tax.income.credits.renter.max_household_size = 8, caps the table lookup. Tax units of 9 or more use the 8-person income limits and fair market rent.

Why 8 for Vermont

  • The department caps at 8. Its Renter Credit Website Calculators for TY2021–2025 (cited in the parameter files) share these Calculator-sheet formulas:
    • G10 and G11 in TY2021–2022; G11 and G12 in TY2023–2025, the partial and full credit income limits: MATCH(TEXT(IF(Household_Size>8,8,Household_Size),0),...).
    • G12 in TY2021–2022; G13 in TY2023–2025, the credit amount: IF(Household_Size>4,4,Household_Size). PE's fair_market_rent table already repeats the 4-person value through size 8, so capping at 8 is exact.
    • G5, family size, is validated to 1–10.
  • The calculator reproduces the expectations. I recalculated the TY2025 calculator in LibreOffice for the test households. It gives 1,162 (Chittenden, size 2), 846 (Addison, size 2), 976 (Chittenden, size 7) and 1,250 (Chittenden, sizes 8, 9 and 10), exactly the expectations in the new tests.
  • The statute is silent on size. 32 V.S.A. § 6061(19)–(20) defines the limits as HUD's, and § 6066(b)(2) charges the Commissioner with calculating the credit. The TY2025 booklet (RCC-146, file pages 37–38) prints family sizes 1–8 only.
  • Alternative reading, not adopted. HUD does define larger households. Its FY 2024 income-limit methodology adds 8% of the 4-person limit per person over 8, and its FMR convention (68 Fed. Reg. 56705) adds 15% per bedroom over 4. A literal reading of § 6061 could import those values. The department caps instead, and PE's tables already transcribe its 4-bedroom cap, so this PR follows the department.

Response

UTF-8 review follow-up: all five guards use the shared county_has_state_suffix helper to compare text or byte suffixes without ASCII decoding, preserving county keys and fallbacks; five new !!binary YAML cases pair a covered household with UTF-8 DOÑA_ANA_COUNTY_NM and failed at 68051002b4 with UnicodeDecodeError. All five regressions now pass; the seven requested files pass 635 tests (VT YAML 38, MN 15, WI hourly 11, WI monthly 8, MD 11, VT amounts 12, VT income limits 540), one foreground process per file with the requested thread caps; Ruff 0.15.5 format/check, make format, and git diff --check pass.

Tests

New vectorized YAML cases put an in-state household, an in-state UNKNOWN-county household and (for the crash guards) an out-of-state household in one simulation, so the mask is not all false:

  • vt_renter_credit.yaml test 11: Chittenden, New Hampshire, and VT UNKNOWN (falls back to Addison).
  • vt_renter_credit.yaml test 12: VT tax units of 8, 9 and 12.
  • mn_ccap_provider_rate.yaml Case 13, wi_shares_hourly_max_rate.yaml Case 9, wi_shares_monthly_max_rate.yaml Case 6, and the new md_ccs_payment_rate.yaml informal-provider case.

Review follow-up cases. One additional case per variable pairs a normal in-state household with an in-state household whose county belongs to another state:

  • VT with GRAFTON_COUNTY_NH uses Addison: (60,390 - 44,145) × 1,692 / (60,390 - 27,900) = 846; the Chittenden control gives 1,162.
  • MN with MILWAUKEE_COUNTY_WI uses Hennepin: 250 × 52 / 12 = 1,083.33; the Becker control uses 205 × 52 / 12 = 888.33.
  • WI hourly with HENNEPIN_COUNTY_MN uses Adams' licensed-group table rate of 8.75/hour; the Milwaukee control is 9.72/hour.
  • WI monthly with HENNEPIN_COUNTY_MN uses Adams: ceil(30 × 4.348125) = 131 hours, 8.75 × 131 = 1,146.25; the Milwaukee control is 9.72 × 131 = 1,273.32.
  • MD with FAIRFAX_COUNTY_VA uses Allegany: informal REGULAR UNIT_1 83 / 3 = 27.67; the Montgomery control is 177 / 3 = 59.

Original guard validation (before the main merge). With the five formulas restored from upstream/main and the new tests kept, the six new cases fail with ParameterNotFoundError (keys …thirty_percent.9, the out-of-state VT key, …weekly.CHILD_CARE_CENTER.UNKNOWN, …licensed_group.hourly.UNKNOWN ×2, …informal.rates.UNKNOWN). The 44 existing cases in those files pass. With the fix, all 50 pass.

Broader runs. All VT, MN, WI and MD baseline YAML tests plus household/state_property_tax_credits pass (1,920). code_health/test_parameter_yaml_keys.py, code_health/test_reference_urls.py and test_md_ccs_service_unit_enum_default.py pass (69).

51-state probe (2026). Five multi-household simulations: 51 states with real counties; the same plus UNKNOWN in every state; plus VT tax units of 9 and 12; a lone VT unit of 9; and every county of VT (14), MN (87), WI (72) and MD (24) plus UNKNOWN and out-of-state. Every scenario raised for at least one variable on main; all five variables compute in every scenario here. Script and outputs: ~/reviews/county-lookup-guards-2026-10/evidence/.

After the main merge. Main (35a94c3b02) was merged in at a23810c84e. Main now carries #10130, which rounds the VT credit amount to whole dollars before the phase-out, and the merge resolved the overlap. The PR still touches the same 12 files and the guard and size-cap code is unchanged. In vt_renter_credit.yaml, the worked-arithmetic comments for tests 11 and 12 now show #10130's rounding step; the expected values (1,162, 846, 1,250) are the same. The nine affected test files were rerun one process per file on that exact tree, and all pass: vt_renter_credit.yaml (36), vt_renter_credit_countable_tax_exempt_ss.yaml (2), vt_renter_credit_integration.yaml (2), mn_ccap_provider_rate.yaml (13), wi_shares_hourly_max_rate.yaml (9), wi_shares_monthly_max_rate.yaml (6) and md_ccs_payment_rate.yaml (9), plus main's test_vt_renter_credit_amounts.py (12) and test_vt_renter_credit_income_limits.py (540).

Review follow-up validation (HEAD 68051002b4c2d12f6fd6c22e04836b34830af474): All 700 tests passed in the eleven requested files. Each file ran in its own foreground process, sequentially, with OMP_NUM_THREADS=4 OPENBLAS_NUM_THREADS=4 MKL_NUM_THREADS=4 VECLIB_MAXIMUM_THREADS=4 NUMEXPR_NUM_THREADS=4 OMP_WAIT_POLICY=PASSIVE. No new microsimulation was run.

File Passed
vt_renter_credit.yaml 37
mn_ccap_provider_rate.yaml 14
wi_shares_hourly_max_rate.yaml 10
wi_shares_monthly_max_rate.yaml 7
md_ccs_payment_rate.yaml 10
vt_renter_credit_countable_tax_exempt_ss.yaml 2
vt_renter_credit_integration.yaml 2
test_vt_renter_credit_amounts.py 12
test_vt_renter_credit_income_limits.py 540
test_parameter_yaml_keys.py 34
test_reference_urls.py 32

Ruff 0.15.5: uvx ruff@0.15.5 format . left all 6,919 Python files unchanged; uvx ruff@0.15.5 check . passed. git diff --check passed.

Invariants

The probe runs every county of the four states and checks that each variable computes. It does not itself assert main/head equality, size-cap equality, out-of-state zeros or calculator agreement; the YAML cases assert representative values for those:

  • No crash. Each variable computes for any mix of households with a matching county, UNKNOWN county or county belonging to another state. An in-state household with UNKNOWN or a mismatched county uses the existing fallback county; the new paired-household YAML cases assert its value alongside a normal in-state control.
  • No change where main computed. In-state households with a real county use the same table key as before; VT sizes 1–8 use the same size key.
  • Size cap. The VT credit for any size n ≥ 8 equals the size-8 credit.
  • Out of state is zero. Out-of-state output is 0 (defined_for).
  • Differential. The VT credit equals the department calculator for sizes 2, 7, 8, 9 and 10.

No Python test is added, per the repo's YAML-first rule; the YAML cases cover each path.

Hub microsimulation impact (current head)

A real microsimulation on the default dataset, main at the merge base 35a94c3b02 against this PR's head 7089303db3, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.

Output 2025 change 2026 change 2025 records changed (weighted) 2026 records changed (weighted)
state_income_tax +0 +0 0 (0) 0 (0)
income_tax +0 +0 0 (0) 0 (0)
household_net_income +0 +0 0 (0) 0 (0)
household_benefits +0 +0 0 (0) 0 (0)

Run on the standard outputs only. On main, requesting vt_renter_credit across the whole population crashes on its out-of-state households (the crash this PR fixes), so a base run that names it cannot complete. No record changes in either year, as at the earlier heads 68051002b4, a23810c84e and 8fde198e14. A zero is expected: every default-dataset VT, MN, WI and MD household has a county in its own state, so no record reaches a fallback, and vt_renter_credit feeds the TAXSIM property-credit aggregate, not these four outputs.

Comparison files are in fixes/10116-impact/ on the hub host.

Hub microsimulation impact (head 6805100)

A real microsimulation on the default dataset, main at the merge base 35a94c3b02 against this PR's head 68051002b4, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.

Output 2025 change 2026 change 2025 records changed (weighted) 2026 records changed (weighted)
state_income_tax +0 +0 0 (0) 0 (0)
income_tax +0 +0 0 (0) 0 (0)
household_net_income +0 +0 0 (0) 0 (0)
household_benefits +0 +0 0 (0) 0 (0)

Run on the standard outputs only. On main, requesting vt_renter_credit across the whole population crashes on its out-of-state households (the crash this PR fixes), so a base run that names it cannot complete. No record changes in either year, as at the earlier heads a23810c84e and 8fde198e14. A zero is expected: every default-dataset VT, MN, WI and MD household has a county in its own state, so no record reaches a fallback, and vt_renter_credit feeds the TAXSIM property-credit aggregate, not these four outputs.

Comparison files are in fixes/10116-impact/ on the hub host.

Hub microsimulation impact (merged head a23810c)

A real microsimulation on the default dataset, main at the merge base 35a94c3b02 against this PR's head a23810c84e, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.

Output 2025 change 2026 change 2025 records changed (weighted) 2026 records changed (weighted)
state_income_tax +0 +0 0 (0) 0 (0)
income_tax +0 +0 0 (0) 0 (0)
household_net_income +0 +0 0 (0) 0 (0)
household_benefits +0 +0 0 (0) 0 (0)

Run on the standard outputs only. On main, requesting vt_renter_credit across the whole population crashes on its out-of-state households (the crash this PR fixes), so a base run that names it cannot complete. Main already guards out-of-state counties in the MN, WI and MD child-care rate formulas, and every default-dataset household has a real county matching its state, so those three can't reach the UNKNOWN path on this dataset. No record changes in either year, as at the previous head 8fde198e14. A zero is expected: no county key changes on this dataset, and vt_renter_credit feeds the TAXSIM property-credit aggregate, not these four outputs. The independent review found 654 VT tax units in the pinned dataset, the largest with seven people, so the size cap doesn't bind either.

Comparison files are in fixes/10116-impact/ on the hub host.

Impact

Only cases that crashed on main get new values. In the default dataset every household has a real county matching its state. vt_renter_credit's only consumer is taxsim_state_property_tax_credit, through gov.states.household.state_property_tax_credits.

axiom: us-vt/statute/32/6066 TheAxiomFoundation/rulespec-us#1678 queued (corpus ingest TheAxiomFoundation/axiom-corpus#816; the rulespec-us corpus pin predates the VT § 6061/§ 6066 rows). The county guards are n/a: pure crash guards.

Follow-up

The TY2025 booklet's Washington County 7-person partial-credit limit ($88,880) differed from the calculator's $88,990. #10125, now on main and in this branch, set it to $88,990, along with seven other VT income-limit corrections.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits October 11, 2026 15:38
…D CCS

defined_for masks a formula's output, but policyengine-core runs the formula
over the whole population, so county keys missing from a county-keyed
parameter table raise ParameterNotFoundError in multi-household simulations.

- vt_renter_credit: mask non-VT and UNKNOWN counties to Addison, and cap the
  table lookup at household size 8 (new max_household_size parameter), as the
  Department of Taxes renter credit calculator does for 9+ person households.
- mn_ccap_provider_rate, wi_shares_{hourly,monthly}_max_rate,
  md_ccs_payment_rate: also mask an in-state UNKNOWN county.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each case puts an in-state household, an in-state UNKNOWN-county household
and (for the crash guards) an out-of-state household in one simulation, so
the defined_for mask is not all false and the formula runs over every
county. VT test 12 covers tax units of 8, 9 and 12. All six cases raise
ParameterNotFoundError on upstream/main and pass with the fix.

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

Copy link
Copy Markdown
Contributor Author

The CI run on this pull request was cancelled at 23:27Z on 2026-10-11 to free the organization's shared GitHub runners for an urgent fix in another repository. The US + core hub will re-run it automatically (cancelled jobs only; jobs that had passed are kept). Nothing in this pull request changed. Please don't push or reopen just to restart CI.

@DTrim99

DTrim99 commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Guard county-keyed lookups in VT renter credit, MN CCAP, WI Shares and MD CCS

PR #10116 (author: MaxGhenis, head 8fde198e14, merge-base 065d0e9560). 12 files (+380/−15), 3 commits. Axiom: TheAxiomFoundation/rulespec-us#1678 queued for the Vermont size cap; the county guards are marked n/a.

Summary

The PR stops five county-keyed parameter lookups from raising ParameterNotFoundError. Each crash happened when a simulation held both a household the lookup covers and one it doesn't:

  • vt_renter_credit:
    • It masks out-of-state and UNKNOWN counties to Addison.
    • It switches from the county enum to county_str. The keys are the same.
    • It caps the table lookup at household size 8 with a new parameter, max_household_size.
  • mn_ccap_provider_rate, wi_shares_hourly_max_rate, wi_shares_monthly_max_rate, md_ccs_payment_rate: these already masked out-of-state counties. They now also mask an in-state UNKNOWN county, to Hennepin, Adams, Adams and Allegany.
  • Tests: six new YAML cases. Each puts an in-state household, an in-state UNKNOWN household and an out-of-state household in one simulation, or (VT test 12) tax units of 8, 9 and 12.

The fixes are right:

  • The guards work across a whole population. I checked how policyengine-core applies defined_for, checked the table keys (every county of each state is a key), and traced the fallbacks. No household that computed on main changes value.
  • The cap of 8 is the department's rule for every year the PR applies it. The 2021, 2022, 2024 and 2025 Renter Credit Website Calculators all look up IF(Household_Size>8,8,Household_Size).
  • Tests. Every expectation in the six new cases reproduces by hand, and the VT ones match the department's 2025 calculator.
  • Rounding on main. The VT expectations still hold under the whole-dollar rounding main gained in Match Vermont renter credit base amounts for Franklin and Grand Isle to the department's tables #10130.
  • CI is green.

One should-fix. The new parameter starts in 2021 but cites only the 2023–2025 calculators. The 2021 and 2022 calculators show the same cap and should be cited.

Branch. The branch conflicts with main in the two VT files, because of #10130 and #10125. It needs a merge from main before it can land; Branch status gives the resolution.

Three suggestions follow.

Critical (must fix)

None.

Should address

1. max_household_size starts in 2021, but no cited source covers 2021–2022.

  • Where: parameters/gov/states/vt/tax/income/credits/renter/max_household_size.yaml.
    • Line 9 sets 2021-01-01: 8.
    • The references (lines 15–20) are the 2023, 2024 and 2025 calculators only.
    • The comment (lines 2–7) names cells G11–G13, which is the 2023–2025 layout.
  • The PR body agrees. It says: "The calculators document the size-8 income-limit cap for TY2023–2025. This PR applies the same cap to 2021–2022; no contrary rule was found for those years."
  • The 2021 and 2022 calculators have the same rule. I opened both, at the URLs main already cites in fair_market_rent.yaml since Match Vermont renter credit base amounts for Franklin and Grand Isle to the department's tables #10130. On their Calculator sheets, one row above the 2023–2025 layout:
    • G10 (very low-income limit): =IFERROR(INDEX(VLIL2021[],MATCH(County,VLIL2021[County],0),MATCH(TEXT(IF(Household_Size>8,8,Household_Size),0),VLIL2021[#Headers],0)),"")
    • G11 (extremely low-income limit): the same lookup on ELIL2021.
    • G12 (credit amount): =VLOOKUP(County,TRebateAmounts[],MATCH(TEXT(IF(Household_Size>4,4,Household_Size),0),TRebateAmounts[#Headers],0),FALSE)
    • G5 (family size): validated as a whole number from 1 to 10.
    • The 2024 and 2025 workbooks have the same formulas in G11, G12 and G13.
  • Fix:
    • Add two references:
      • 2022 Renter Credit Website Calculator (Calculator sheet, cells G10-G12), at https://tax.vermont.gov/sites/tax/files/documents/2022%20Renter%20Credit%20Website%20Calculator_1.xlsx
      • 2021 Renter Credit Website Calculator (Calculator sheet, cells G10-G12), at https://tax.vermont.gov/sites/tax/files/documents/2021%20Renter%20Credit%20Website%20Calculator_8.xlsx
    • Say in the comment that the cells are G10–G12 in 2021–2022.
    • Replace the PR body's "Size cap before 2023" bullet with the citation.
    • Add both workbooks to the size-convention section of rulespec-us#1678, which lists only TY2023–2025.

Suggestions

1. Make an UNKNOWN county give the same result as an omitted county.

  • Omitted county. A household with no county input gets first_county_in_state (county.py:65-66): Addison, Adams, Allegany and Aitkin.
  • VT and WI agree. Their UNKNOWN fallbacks are the same counties, so UNKNOWN and omitted give one answer.
  • MN does not. mn_ccap_provider_rate.py:36 sends UNKNOWN to Hennepin. The PR body discloses the result: an infant in 45 hours a week of family care gets $888.33 a month with county omitted (Aitkin, $205 a week) and $1,083.33 with UNKNOWN (Hennepin, $250 a week).
  • MD is split within one household.
    • md_ccs_payment_rate.py:37 sends an UNKNOWN county to Allegany, which is Region Z, for informal rates.
    • md_ccs_region.py:21,56 defaults an unmatched county to Region W, for center and family rates.
    • So an MD household with an UNKNOWN county is priced in Region W for licensed care and in Allegany for informal care (informal REGULAR: $83 a week, against $135 in every Region W county).
    • COMAR 13A.14.06.11.B(2) (text): "The rate paid to the provider is based on the region in which the: (a) Child care is given if the provider is a: (i) Family child care provider; or (ii) Center child care provider; or (b) Child resides, if the provider is an informal child care provider."
  • The law gives no fallback. None of the four sources gives a rate for an unknown county:
    • Minn. Stat. 142E.17 subd. 1(b) (text): "the maximum rate paid for child care assistance in a county or county price cluster"
    • Wis. Stat. § 49.155(6)(a) (text) leaves the maximum rates to the department, which publishes them by county. § 49.155(4)(c)1, which covers out-of-state providers, keys the rate to "the maximum rate applicable in the county in which the eligible individual resides".
    • 32 V.S.A. § 6061(7)(C) (text): "the monthly fair market rent for the area in which the claimant resides as determined by the U.S. Department of Housing and Urban Development".
    • So any fallback is a modeling choice, and the PR body rightly calls these placeholders.
  • Fix (optional):
    • Use AITKIN_COUNTY_MN as MN's in-state UNKNOWN fallback. Hennepin can stay for out-of-state rows, which defined_for zeroes anyway.
    • Either use a Region W county for MD's informal fallback, or map UNKNOWN to Allegany's region in md_ccs_region.
    • Or keep the current choices and note the difference in the code comments.

2. A household whose county belongs to another state still raises.

  • Where: vt_renter_credit.py:31, mn_ccap_provider_rate.py:36, wi_shares_hourly_max_rate.py:29, wi_shares_monthly_max_rate.py:32 and md_ccs_payment_rate.py:37.
  • The gap. in_state & (county != "UNKNOWN") lets an in-state household with another state's county (for example VT with GRAFTON_COUNTY_NH) reach the table. The PR body's invariants say so.
  • The fix. A suffix test such as np.char.endswith(county.astype(str), "_VT") excludes both UNKNOWN and mismatched counties.
  • Optional. The != "UNKNOWN" form matches md_flat_rate_county_tax.py:24 and in_county_tax.py:20. A mismatched state and county is an input error, and every VT, MN, WI and MD household in the default data has a matching county (Verified correct).

3. Reword the changelog and one PR-body sentence about what crashed on main.

  • The changelog (changelog.d/fix-county-lookup-guards.fixed.md) says all four programs crashed "on simulations that include households outside the state". On main, the MN, WI and MD formulas already masked out-of-state counties: the diff's context lines show where(in_mn, county, "HENNEPIN_COUNTY_MN") and the matching WI and MD lines. Only VT crashed on out-of-state households. The PR body's own table has this right.
  • The PR body's microsimulation section says that on main, "requesting vt_renter_credit or the MN/WI/MD child-care rate variables across the whole population crashes".
    • Only vt_renter_credit can crash on the default population. Every enum county of MN (87), WI (72) and MD (24) is a key in every rate table, so the old MN/WI/MD formulas fail only on an in-state UNKNOWN county.
    • The default data has none. Every MN (1,166), WI (1,232) and MD (1,091) household in the Populace 2024 release has an in-state county_fips that maps to an enum county.
    • MD is on the net-income path. md_child_care_subsidies is in household_state_benefits, so a main run of household_net_income reaches md_ccs_payment_rate for the whole population whenever any MD child is eligible. The PR's main run of the standard outputs completed.
  • Fix: say "the Vermont renter credit from crashing on out-of-state households and on tax units over eight people, and all four from crashing on an in-state household whose county is UNKNOWN". In the PR body, limit the microsimulation crash sentence to vt_renter_credit.

Verified correct

  • How policyengine-core applies defined_for. I checked this in the local core 3.26, simulations/simulation.py. The PR cites 3.32.15, which behaves the same way.

    • Lines 766–774: the formula is skipped only when the mask is all false (if np.all(~mask): array = holder.default_array()).
    • Lines 836–837: otherwise the formula runs over every entity and is masked afterwards (array = np.where(mask, array, variable.default_value)).
    • So a county key missing from the table raises whenever one in-state row shares the simulation, as the PR describes.
  • The guards are vectorized and complete.

    • Table keys. Every county in the County enum for each state is a key in every table the formulas index:
      • VT: 14 of 14, in thirty_percent, fifty_percent and fair_market_rent
      • MN: 87 of 87, in weekly, full_day, hourly and lnl_hourly
      • WI: 72 of 72, in both hourly tables and both full_time_monthly tables
      • MD: 24 of 24, in informal/rates
    • No table has an UNKNOWN key. So once out-of-state and UNKNOWN counties are masked, every household whose county matches its state computes.
    • The UNKNOWN test works. county_str is county.decode_to_str(), so County.UNKNOWN arrives as "UNKNOWN" and county != "UNKNOWN" catches it.
    • In-state values don't change. A real in-state county passes through where(...) unchanged.
    • VT's switch is safe. county (enum) and county_str index the tables with the same names.
  • The VT size cap.

    • The code. size = min_(tax_unit_size, p.max_household_size).astype(int) (vt_renter_credit.py:24) follows mo_mhf_parent_income_limit.py:21. Sizes 1–8 use the same key as before, and .astype(int) keeps the key an integer if the parameter loads as a float.
    • The calculators. I opened the department's calculators for 2021, 2022, 2024 and 2025:
      • All four cap the income-limit lookup at 8 and the credit-amount lookup at 4.
      • All four validate family size to 1–10.
      • The cells are listed under Should 1.
      • PE's fair_market_rent table already repeats the 4-person amount through size 8, so one cap of 8 reproduces both lookups.
    • The 2023 workbook. I couldn't re-open it, because the Wayback Machine returned HTTP 429. But the Wayback availability API resolves the cited link to a 200 capture of the .xlsx (2025-06-09), and the CDX index lists four captures with one digest.
    • The statute. 32 V.S.A. § 6066(b)(2) (text): "The Commissioner shall calculate the credit under subdivision (1) of this subsection (b) using the fair market rent corresponding to a number of bedrooms equal to the number of personal exemptions allowed under subdivision 5811(21)(C) of this title for the taxable year". The statute sets no size limit, and the PR body records HUD's extrapolation as an alternative reading. Following the department, which administers the credit, is reasonable.
    • The 2025 calculator's tables match PE's 2025 cells:
      • Chittenden: full limits 31,200 (size 2), 48,650 (size 7) and 54,150 (size 8); partial limits 67,540, 104,650 and 111,410; credit amounts 2,323 (size 2) and 2,500 (size 4+).
      • Addison, size 2: 27,900, 60,390 and 1,692.
  • Hand checks. Every expectation in the six new cases reproduces. The VT figures use the head's formula; the post-merge check is below.

    Case Calculation Expected
    VT test 11, Chittenden, size 2, $49,370 (67,540 − 49,370) / (67,540 − 31,200) = 0.5; 0.5 × 1,936 × 12 × 0.1 = 1,161.6 1,162
    VT test 11, NH household defined_for 0
    VT test 11, VT UNKNOWN → Addison, size 2, $44,145 16,245 / 32,490 = 0.5; 0.5 × 1,692 846
    VT test 12, Chittenden, sizes 8, 9 and 12, $82,780 28,630 / 57,260 = 0.5; 0.5 × 2,083 × 1.2 = 1,249.8 1,250 ×3
    VT comment: size 7 1 − 34,130 / 56,000 = 0.3905; × 2,499.6 = 976.2 976
    VT comment: UNKNOWN priced at Chittenden 23,395 / 36,340 × 2,323.2 = 1,495.6 1,496
    MN case 13, Becker, family infant, 45 h/week (weekly rate, >35 h) 205 × 52 / 12 888.33
    MN case 13, UNKNOWN → Hennepin 250 × 52 / 12 1,083.33
    WI hourly case 9, Milwaukee and UNKNOWN → Adams, licensed group, ages 2–3 table values 9.72, 8.75
    WI monthly case 6, 15 h/week (part time) ceil(30 × 4.348125) = 131 h; 9.72 × 131; 8.75 × 131 1,273.32, 1,146.25
    MD informal case, Montgomery and UNKNOWN → Allegany, age 3 (REGULAR, ≥ 24 months), 2 h/day (UNIT_1) 177 / 3; 83 / 3 59, 27.67
  • The tests fail on main. By the code on main, each new case reaches a missing key:

    • VT test 11: the NH county and the VT UNKNOWN county
    • VT test 12: size key 9
    • MN, WI ×2 and MD: UNKNOWN
    • The in-state controls pin the unchanged path. Each case puts at least one in-state row in the simulation, so the mask is never all false.
  • No change to default microsimulation records. In the Populace 2024 release, every VT (496), MN (1,166), WI (1,232) and MD (1,091) household has an in-state county_fips that maps to an enum county. So no default record reaches a fallback. That matches the PR's zero-change run.

  • Callers.

    • vt_renter_credit feeds only the state_property_tax_credits lists, the TAXSIM-parity aggregate, not net income.
    • The rate variables feed md_ccs, mn_ccap_max_rate and wi_shares_child_subsidy.
    • Values change only for rows that raised before.
  • Parameter metadata.

    • The description follows the house pattern, and the label is clear.
    • unit: person is used in 140 other parameter files, and period: year is right.
    • The cell locators in the reference titles stand in for page anchors, which a workbook doesn't have. That fits the reference convention.
  • Changelog. changelog.d/fix-county-lookup-guards.fixed.md is top-level and typed fixed. Suggestion 3 covers its wording.

  • Local run. policyengine-core 3.26 can't import the head tree (_uprating_index_value is missing; CI uses a newer core). I relied on CI, the hand checks and the independent key and calculator checks.

Axiom line assessment

Valid: queued for the size cap and n/a for the guards.

  • The line: axiom: us-vt/statute/32/6066 TheAxiomFoundation/rulespec-us#1678 queued (corpus ingest TheAxiomFoundation/axiom-corpus#816; ...). The county guards are n/a: pure crash guards.
  • The issue is OPEN and labelled pe-parity. It was created on 2026-10-11 from this PR, and it has:
    • module paths: us-vt/statutes/32/6066/b.yaml, plus us-vt/policies/tax/renter-credit/table-household-size.yaml for the department's size convention
    • corpus citations: the axiom-corpus 2026-10-06-w6-income-tax-statute-vt rows
    • blockers, as main's CLAUDE.md now requires for queued: the corpus pin must advance, and the billed encoder run needs approval
    • verbatim law: § 6066(b), and § 6061(7)(C), (19) and (20)
    • required outputs: min(exemptions, 8) and min(exemptions, 4)
    • companion tests from the department's 2025 calculator: 1,162, 846, 976 and 1,250 at sizes 8, 9 and 10, which match YAML tests 11–12
  • It matches the head's behavior. The Correct eight Vermont renter credit income limits to HUD's limits #10125 and Match Vermont renter credit base amounts for Franklin and Grand Isle to the department's tables #10130 comments on the issue add the rounding and Franklin/Grand Isle data points that main now has.
  • n/a for the guards is right. They are placeholder keys with no legal content, and no source gives a rate for an unknown county (Suggestion 1).
  • Gaps to fix in the issue:

CI status

All 26 checks pass (gh pr checks 10116, run 38171059356, attempt 2, on head 8fde198e14).

  • Skipped jobs. Three aggregate jobs from the earlier cancelled run (38170610280) show as skipping. The maintainer's comment says that run was cancelled to free runners and re-run without changes.
  • The changed YAML files ran:
    • states-shard-1: mn_ccap_provider_rate.yaml (13 cases) and vt_renter_credit.yaml (13)
    • states-shard-2: md_ccs_payment_rate.yaml (9)
    • states-shard-3: wi_shares_hourly_max_rate.yaml (9) and wi_shares_monthly_max_rate.yaml (6)
    • All passed.
  • Partner tests. The PR touches none, and the Household API Partners job passes.

Branch status

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 guards are right: every county of each state is a table key, in-state results are unchanged, and every new expectation reproduces by hand (the VT values match the department's 2025 calculator). One should item (see the comment above): max_household_size.yaml starts in 2021 but cites only the 2023-2025 calculators. The 2021 and 2022 calculators have the same cap at Calculator!G10-G12, so cite both and fix the cell numbers in the comment, the PR body and rulespec-us#1678. Also, the branch now conflicts with main in vt_renter_credit.py/.yaml (#10130 rounding, #10125 cases). Keep main's whole-dollar base and half-up rounding with this PR's [size][safe_county], and keep all YAML cases.

@MaxGhenis MaxGhenis closed this Oct 14, 2026
@MaxGhenis MaxGhenis reopened this Oct 14, 2026
@MaxGhenis MaxGhenis closed this Oct 14, 2026
@MaxGhenis MaxGhenis reopened this Oct 14, 2026
@DTrim99

DTrim99 commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

PR Review (round 2): Guard county-keyed lookups in VT renter credit, MN CCAP, WI Shares and MD CCS

PR #10116 (author: MaxGhenis). Head 7089303db3; we last reviewed 8fde198e14. Since then there are three author commits and one merge of main (a23810c84e, which merged 35a94c3b02). The merge-base diff is 13 files, +794/−21. Axiom: TheAxiomFoundation/rulespec-us#1678 queued for the Vermont § 6066 size cap; the guards are n/a.

Summary

Every round-1 item is resolved, and nothing new needs fixing in this PR.

  • The should-fix is fixed. max_household_size.yaml now cites the TY2021 and TY2022 calculators (cells G10–G12), and its comment gives the cell layout for each year.
  • The mismatched-state gap is closed. This was round-1 Suggestion 2. All five formulas now gate on in_state & county_has_state_suffix(county, "<ST>"), a new shared helper.
    • An in-state household whose county is UNKNOWN, belongs to another state or is missing falls back to the placeholder county instead of crashing.
    • Out-of-state rows fall back the same way and are then zeroed by defined_for.
    • In-state rows with a real county keep their key.
  • The UTF-8 fix is right. The helper compares bytes values with a bytes suffix and text values with a text suffix. It never ASCII-decodes, so a UTF-8 county such as DOÑA_ANA_COUNTY_NM supplied as bytes can't raise UnicodeDecodeError before the mask applies.
  • The wording fixes are in. The changelog and the PR body's microsimulation sentence now say what actually crashed on main (round-1 Suggestion 3).
  • The merge of main is correct. Both hand-resolved blocks keep every case and line from both sides.
  • The branch merges cleanly with today's main, which is 120 commits ahead. None of those commits touches these programs, their rate tables or the core pin. The source-conflict ratchet (Tie source-conflict markers to the register shared with Axiom #10287) passes on the merged tree.
  • Tests. Ten new YAML cases, 20 expectations. Each reproduces by hand from the head's tables.
  • CI is 27/27 green on the head.

Two suggestions:

  • The same crash pattern remains in lookups this PR doesn't cover. Main hasn't added any new ones since the merge-base.
  • Some Axiom issue housekeeping.

Prior findings

Finding Status Evidence
Should 1: max_household_size starts in 2021 but cited only the 2023–2025 calculators Fixed 4d47b5f22a adds the 2022 and 2021 Renter Credit Website Calculators (Calculator sheet, cells G10-G12) at lines 22–25. Both URLs are the ones main already cites in fair_market_rent.yaml. The comment (lines 2–8) now reads "G10-G12 in 2021-2022 and G11-G13 in 2023-2025". The PR body's "Size cap before 2023" bullet is replaced by the citation. rulespec-us#1678 got a 2026-10-14 comment adding both workbooks, with the same cells and formulas.
Suggestion 1: make UNKNOWN give the same result as an omitted county (MN Hennepin vs Aitkin; MD informal Allegany vs Region W) Declined, with a reason (optional) The fallbacks stay as labelled placeholders. The PR body now discloses the MN difference ($888.33 with county omitted, $1,083.33 with UNKNOWN). The code comments don't, and the MD split (Region W for licensed rates, Allegany/Region Z for informal) is still not mentioned. That split now also applies to an MD household with another state's county. The law gives no fallback, so this stays a modelling choice; no action needed.
Suggestion 2: an in-state household with another state's county still raised Fixed 68051002b4 replaces county != "UNKNOWN" with a state-suffix test in all five formulas, and 7089303db3 moves that test into county_has_state_suffix (tools/geography/county_helpers.py:17). There are five new paired cases: VT+GRAFTON_COUNTY_NH, MN+MILWAUKEE_COUNTY_WI, WI+HENNEPIN_COUNTY_MN (hourly and monthly) and MD+FAIRFAX_COUNTY_VA. Each reaches a missing key on main and at 8fde198e14.
Suggestion 3: changelog and PR-body wording about what crashed on main Fixed The changelog now reads "Stop the Vermont renter credit from crashing on out-of-state households and on tax units over eight people, and all four programs ... from crashing on an in-state household whose county is UNKNOWN or belongs to another state, including counties supplied as UTF-8 bytes". The microsimulation note now limits the crash to vt_renter_credit.
Branch: conflicts with main in the two VT files (#10130, #10125) Fixed Merged at a23810c84e; both resolution blocks are checked under Verified.
Axiom gap (a): add the TY2021–2022 calculators to #1678 Fixed, in a comment The 2026-10-14 comment on #1678 adds them. The body's size-convention section still lists TY2023–2025 only (Suggestion 2).
Axiom gap (b): #1678 output 7 says "TY2027" for Act 169 (claim year 2027) Open, not blocking Unchanged. It matches main's max_credit/fmr_rate dating (2027-01-01), which this PR doesn't touch.

New findings

Critical (must fix)

None.

Should address

None.

Suggestions

1. Other county-keyed lookups still have the crash this PR fixes. None of them is new on main.

  • Main added none since the merge-base. I checked all 120 newer commits on main. The new county readers (OH HEAP Add Ohio HEAP regular heating assistance #9975, SD LIEAP Add South Dakota LIEAP regular heating assistance #9974, RI LIHEAP Add Rhode Island LIHEAP regular heating assistance #9972, VA Auxiliary Grant Add Virginia state supplementation for 2026 #10172, NY SSP Add New York state supplementation for 2026 #10158) all use np.isin(county, ...) or equality checks, which can't raise.
  • Older lookups on main that are still exposed:
    • nc_scca_market_rate.py:17-19, with no guard:
      • The formula is return p.childcare_market_rates[county][age_group], and the table has the 100 NC counties only.
      • Any simulation that holds an eligible NC child together with a non-NC household (or an NC household whose county is UNKNOWN) reaches a missing key. That is the VT mechanism this PR fixes.
      • nc_child_care_subsidies is in gov.hhs.ccdf.child_care_subsidy_programs.
      • I traced this by code; I did not run it.
    • MD local income tax, with the old guard: md_applicable_local_tax_rate.py:26, md_flat_rate_county_tax.py:24 and md_withheld_income_tax.py:30 keep in_md & (county != "UNKNOWN"). So an MD household with a non-MD county still indexes gov.local.md.flat_rate with a missing key.
    • IN county tax, with the old guard: in_county_tax.py:20-24 has the same gap. rates[safe_county[in_valid_county]] is reached by an IN household with an Ohio county.
    • WA property tax exemption: the open sibling PR Fix WA property tax exemption crash for households outside Washington #10113 guards wa_pte_tier/wa_pte_income_eligible with the old != "UNKNOWN" form (ADAMS_COUNTY_WA fallback). That form would leave the mismatched-state gap.
  • Fix (optional, follow-up): open an issue or follow-up PR that reuses county_has_state_suffix for the MD, IN and WA formulas and adds an in_nc & county_has_state_suffix(county, "NC") guard to NC SCCA, each with a paired mixed-state YAML case. This PR's title and body name only its four programs, so this isn't a gap in its scope.

2. Put the TY2021–2022 sources into the queued Axiom work itself.

Verified

  • The guards, for each program. I read the head's formulas (vt_renter_credit.py:31-37, mn_ccap_provider_rate.py:34-40, wi_shares_hourly_max_rate.py:29-34, wi_shares_monthly_max_rate.py:32-37, md_ccs_payment_rate.py:35-41).

    • Out-of-state household: in_state is false, so it gets the fallback key and defined_for zeroes it.
    • In-state with another state's county, or UNKNOWN: the suffix test fails, so it gets the fallback key.
    • In-state with an in-state county: the same key as on main. VT's switch from the county enum to county_str keeps the same names.
  • The helper, probed with numpy only (policyengine_us was not imported). I ran the helper and the where(...) that follows it on three kinds of array:

    • an object array mixing text, ASCII bytes, UTF-8 bytes (DOÑA_ANA_COUNTY_NM), UNKNOWN, None and ""
    • a text (<U) array
    • a fixed-width bytes (|S) array

    In-state text and ASCII-bytes values keep their key. Everything else becomes the fallback, and the resulting key array casts to text without error. Core's table lookup does that cast, and CI's !!binary cases confirm it works end to end.

  • Edge cases.

    • Non-ASCII names: the County enum has 18 non-ASCII names (1 NM, 17 PR) and none in VT, MN, WI or MD. A non-ASCII county can therefore only be out-of-state or mismatched, and it is always replaced by the ASCII fallback before any lookup.
    • Default county: an omitted county gets first_county_in_state (Addison, Aitkin, Adams, Allegany), which passes the suffix test. A county that resolves to UNKNOWN (the enum default) falls back.
    • Names shared across states: WASHINGTON_COUNTY_* exists in all four states. Each state keeps its own, and another state's Washington County falls back.
    • Not handled: a county string that ends in _VT but isn't a real county still raises. That is an input error outside the enum and unchanged from main.
  • NH Add New Hampshire state supplementation for 2026 #10156 pattern. Every key variable the formulas index with has a valid default:

    • MN: mn_ccap_age_group, default SCHOOL_AGE
    • WI: wi_shares_age_group, default AGE_6_AND_OLDER
    • MD: md_ccs_age_group REGULAR, md_ccs_service_unit UNIT_3, md_ccs_region REGION_W. Each is defined_for its state, and each default is a member present in its table.
    • VT: the size key is min_(tax_unit_size, 8), and tax_unit_size is at least 1.
  • Hand checks of every new or changed expectation. All match the head's parameters: VT 2025; MN 2026-01; WI 2027-01 (part-time conversion 30, 4.348125 weeks per month); MD 2026-01.

    Case Calculation Expected
    VT, NH county (line 634): Chittenden, size 2, $49,370 base floor(1,936 × 12 × 0.1 + 0.5) = 2,323; 18,170 × 2,323 / 36,340 = 1,161.5, which rounds to 1,162 1,162
    VT, NH county: VT household with GRAFTON_COUNTY_NH → Addison, size 2, $44,145 base 1,692; 16,245 × 1,692 / 32,490 = 846.0 846
    VT, UTF-8 (line 679): Chittenden as bytes; NM household as above; defined_for 1,162, 0
    MN Case 14 (line 286): Becker, family infant, 45 h/week (weekly) 205 × 52 / 12 888.33
    MN Case 14: MN household with MILWAUKEE_COUNTY_WI → Hennepin 250 × 52 / 12 1,083.33
    MN, UTF-8 (line 314): Becker as bytes; NM 205 × 52 / 12; defined_for 888.33, 0
    WI hourly Case 10 (line 190): Milwaukee, licensed group, ages 2–3; HENNEPIN_COUNTY_MN → Adams table values 9.72, 8.75
    WI hourly, UTF-8 (line 218): Milwaukee as bytes; NM table; defined_for 9.72, 0
    WI monthly Case 7 (line 143): 15 h/week, part time ceil(30 × 4.348125) = 131 h; 9.72 × 131; 8.75 × 131 1,273.32, 1,146.25
    WI monthly, UTF-8 (line 172) 9.72 × 131; defined_for 1,273.32, 0
    MD, Virginia county (line 325): parents; Montgomery informal REGULAR UNIT_1; MD household with FAIRFAX_COUNTY_VA → Allegany 0; 177 / 3; 0; 83 / 3 0, 59, 0, 27.67
    MD, UTF-8 (line 378): Montgomery as bytes; NM child 177 / 3; defined_for 0, 59, 0, 0
    VT tests 11–12, comments rewritten in the merge (values unchanged) 0.5 × 2,323 = 1,161.5 → 1,162; 0.5 × 1,692 = 846; 0.5 × 2,500 = 1,250; "Chittenden would give 1,496": 23,395 × 2,323 / 36,340 = 1,495.5 → 1,496; "7-person gives 976": 21,870 × 2,500 / 56,000 = 976.3 → 976 1,162 / 0 / 846, 1,250 ×3
  • What the tests discriminate.

    • Each mismatched-state case reaches a missing key under main's != "UNKNOWN" form (and VT's enum lookup).
    • The UTF-8 cases would fail on the ASCII cast at 68051002b4, as the author reports.
    • Each case keeps an in-state control row, so the defined_for mask is never all false.
  • Merge resolutions (a23810c84e).

    • Block 1, vt_renter_credit.yaml: compared with main at the merge-base, the head removes 0 lines. It has no conflict markers, and its 38 cases are main's 34 plus this PR's 4. Main's Franklin/Grand Isle and corrected-limit cases are intact.
    • Block 2, vt_renter_credit.py: keeps this PR's [size][safe_county] lookups and main's Match Vermont renter credit base amounts for Franklin and Grand Isle to the department's tables #10130 rounding. That is floor(fmr × 12 × rate + 0.5) for the base, multiply-before-divide in the phase-out, and floor(unrounded + 0.5) at the end. Main's duplicate [tax_unit_size][county] lines are dropped, which is the resolution round 1 proposed.
  • Interaction with main's 120 newer commits.

    • None touches the 13 files, these programs' variables, the VT renter parameters, the MN/WI/MD rate tables, the geography variables or the core pin (policyengine-core 3.32.27 on both).
    • The only related changes are one-line income-source list edits for MD CCS, MN CCAP and WI Shares. No new test has unemployment inputs, so the expectations hold on the merged tree.
  • Source-conflict ratchet (Tie source-conflict markers to the register shared with Axiom #10287), checked statically on the merged tree.

    • I applied the test's CONFLICT_COMMENT_RE to the comments of the six scanned files this PR changes (the five formulas and max_household_size.yaml). It finds 0 matches on main and 0 on the merged tree.
    • None of the six files is in KNOWN_UNMARKED.
    • The helper (tools/) and the YAML tests (tests/) are outside the scanned folders.
    • "calculators use" does not trigger the calculator\s+(uses|use) pattern.
  • Other code-health guards on main. The new hrefs don't match any tax.vermont.gov prefix in known_dead_reference_urls. The PR doesn't touch income-source lists, so test_unemployment_compensation_readers.py doesn't apply.

  • Changelog. changelog.d/fix-county-lookup-guards.fixed.md is top-level and typed fixed. The UTF-8 clause is accurate: on main, an MN, WI or MD household with another state's UTF-8 county reaches the core lookup's ASCII cast.

  • Partner tests. None touched.

  • Local run. Not possible: the head imports _uprating_index_value from policyengine-core, which the local 3.26 lacks. I relied on CI, the hand checks and the numpy-only helper probe. No microsimulation was run.

Axiom line assessment

Valid: queued for the § 6066 size cap and n/a for the guards.

  • The line: axiom: us-vt/statute/32/6066 TheAxiomFoundation/rulespec-us#1678 queued (corpus ingest TheAxiomFoundation/axiom-corpus#816; the rulespec-us corpus pin predates the VT § 6061/§ 6066 rows). The county guards are n/a: pure crash guards.
  • rulespec-us#1678 is OPEN and labelled pe-parity (created 2026-10-11, updated 2026-10-14). It is dispatch-ready:
    • module paths: us-vt/statutes/32/6066/b.yaml and us-vt/policies/tax/renter-credit/table-household-size.yaml
    • corpus citations: the 2026-10-06-w6-income-tax-statute-vt rows
    • blockers: the corpus pin must advance, and the billed encoder run needs approval
    • verbatim law: § 6066(b) and § 6061(7)(C), (19) and (20)
    • required outputs: min(exemptions, 8) and min(exemptions, 4)
    • companion tests from the department's TY2025 calculator: 1,162, 846, 976 and 1,250 at sizes 8, 9 and 10. These are the PR's YAML values.
  • It matches the head. The size-cap and credit computation are unchanged since round 1. The new commits add only guard logic, which has no legal content, and no source gives a rate for an unknown or mismatched county. So n/a for the guards stands.
  • The blocker, axiom-corpus#816, is OPEN.
  • Non-blocking gaps:
    • The TY2021–2022 sources are only in a comment, and Error with person-level childcare expenses #816 is still scoped to TY2023–2025 (Suggestion 2).
    • Output 7 still says "TY2027" for Act 169. Round 1 noted that claim year 2027 is TY2026. That text mirrors main's parameter dating, which is outside this PR.

CI status

All 27 checks pass (gh pr checks 10116, re-checked at the end of this review). This is run 38674936177 on head 7089303db3, from 2026-10-15 03:11 to 05:11 UTC.

  • The run is older than two main-side changes:
  • The jobs that run the changed files all pass: the baseline state shards 1–4, Microsimulation, Household API Partners, PR validation and Quick Feedback with coverage.
  • Merge state: GitHub reports the PR as mergeable, and BLOCKED only by the outstanding changes-requested review.

Branch status

  • Position: 7 commits ahead of PolicyEngine/main (328d1721e2) and 120 behind. The merge-base is 35a94c3b02.
  • Merge: git merge-tree --write-tree PolicyEngine/main 7089303db3 is clean (tree 3c8f25f09d). No conflicts.
  • Sibling: Fix WA property tax exemption crash for households outside Washington #10113 (WA, open) touches only WA files, so it doesn't conflict with this PR (see Suggestion 1 on its guard form).
  • CI age: CI last ran 120 commits ago. A merge from main and a re-run before landing would refresh it, but the static checks show no interaction.

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: Should 1 (TY2021-22 calculator citations) is fixed, and the new county_has_state_suffix guard handles mismatched-state counties in all five formulas, with paired tests. Out-of-state, UNKNOWN, mismatched and missing counties all fall back, and in-state keys are unchanged. Both hand-resolved merge blocks are correct, and all 20 new expectations hand-check. Two suggestions, including the other lookups still on the old guard (NC SCCA, MD local tax, IN county tax, WA). Full report in the comment above.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants