Skip to content

Cap GA surplus tax rebate at Form 500 Line 16 and make it refundable#9097

Merged
hua7450 merged 2 commits into
PolicyEngine:mainfrom
DTrim99:fix/ga-surplus-rebate-line16
Jul 20, 2026
Merged

Cap GA surplus tax rebate at Form 500 Line 16 and make it refundable#9097
hua7450 merged 2 commits into
PolicyEngine:mainfrom
DTrim99:fix/ga-surplus-rebate-line16

Conversation

@DTrim99

@DTrim99 DTrim99 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Fixes #9096

Surfaced by PolicyEngine/policyengine-taxsim#1103 (GA 2021 HoH, $23,504.17 wages, one child, $1,914.21 childcare).

Changes

O.C.G.A. §48-7-20.2(b)(1) (HB 162, 2023) sets the one-time refund of 2021 taxes at the lesser of (A) the 2021 liability "as properly reported on Line 16 of the 2021 Georgia Form 500" — the tax before credits — or (B) $250 single/separate, $375 HoH, $500 joint/surviving spouse. Subsection (b)(3) repeats that Line 16 is the only cap, and (d) pays the refund out by check even when credits wipe the balance due.

Previously ga_surplus_tax_rebate was a flat amount placed last in the nonrefundable ordered stack, so it was effectively capped at the post-credit balance.

  • ga_surplus_tax_rebate now returns min(amount[filing_status], ga_income_tax_before_non_refundable_credits) — the statutory Line 16 cap.
  • Removed from non_refundable.yaml; applied via ga_refundable_credits (adds) so it pays out past zero.
  • surplus_tax_rebate/amount.yaml is zeroed outside tax year 2021 (the HB 162 refund is keyed to 2021 liability only), keeping the refundable wiring inert in other years. Filing-status unit tests moved from period 2022 to 2021 accordingly.

Validation

Against the #1103 record (Form 500: Line 16 tax = 525, GA CDCC = 287, balance 238; TAXSIM books the rebate at 375):

Before After Statute
ga_surplus_tax_rebate (effective) 237.11 375.00 min(524.24, 375) = 375
ga_income_tax 0.00 −137.89 237.11 − 375

New tests: Line 16 cap below the maximum (200 → 200), other credits not reducing the rebate (the #1103 record), and the 2022 zero case. All 9 tests in the touched GA files pass locally, including the existing nonrefundable-ordering test.

🤖 Generated with Claude Code

O.C.G.A. 48-7-20.2(b)(1) sets the HB 162 one-time refund at the lesser of
the 2021 liability as reported on Line 16 of Form 500 (tax before credits)
or $250/$375/$500 by filing status, and pays it out past a zero balance
due. Modeling it as a nonrefundable credit stacked after the other Georgia
credits wrongly capped it at the post-credit balance.

Zero the amount parameter outside tax year 2021 so the refundable wiring
stays inert in other years.

Fixes PolicyEngine#9096

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (6a8a897) to head (99fead7).
⚠️ Report is 40 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9097   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            1         2    +1     
  Lines           16        24    +8     
=========================================
+ Hits            16        24    +8     
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.

@DTrim99
DTrim99 marked this pull request as ready for review July 20, 2026 17:44

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

Program Review — PR #9097

Title: Cap GA surplus tax rebate at Form 500 Line 16 and make it refundable
State/Program: Georgia — surplus tax rebate income-tax credit (O.C.G.A. §48-7-20.2 / HB 162, 2023)
Tax year: 2021 (rebate active; zeroed 2022+) | PR type: bug fix (TAXSIM #1103 / PE-US #9096)

Source Documents

Branch Status

  • ⚠ PR branch is 12 commit(s) behind main. Consider rebasing before merging. Review was scoped to the PR's actual changes — staleness did not affect findings. (informational, NOT a finding)

Critical (Must Fix)

1. SURVIVING_SPOUSE = $500 should be $375 — verified $125/unit overpayment for GA surviving-spouse households (TY2021)

File: policyengine_us/parameters/gov/states/ga/tax/income/credits/surplus_tax_rebate/amount.yaml:24-27
Statute: O.C.G.A. §48-7-20.2(b)(1)(B) — HB 162 #page=2

This is the review's one blocking finding. It was flagged independently by four agents (reference-checker, statute audit, regulatory reviewer, and both dedicated verifiers) and passed both verification stages — code-path reachability and a 600 DPI visual re-render of the source pages. The evidence chain is airtight:

  • Statute wording. HB 162 §48-7-20.2(b)(1)(B) enumerates exactly three filing-status buckets: (i) single or married-filing-separate → $250; (ii) head of household → $375; (iii) "a married couple filing a joint return" → $500. Surviving spouse / qualifying widow(er) is never named, and the $500 tier is textually restricted to a married couple filing jointly — which a surviving spouse (deceased spouse) is not. The $500 value is an inference, not statutory text.
  • Georgia's own return routes QSS to Head of Household. The 2021 IT-511 Line 5 instructions (#page=12) offer only filing letters A–D and direct a qualifying widow(er) to status D = "Head of Household or Qualifying Widow(er)." HB 162 keys the amount to "such taxpayer's filing status for the 2021 taxable year," and a status-D filer receives the head-of-household amount, $375. Corroborated on Form 500 #page=3 (Line 14a: $2,700 exemption "for filing status A or D," grouping QSS with Single, not with married-joint B) and by the IT-511 standard-deduction table (Single/HoH/Qualifying Widow(er) share the $4,600 amount; married-joint is $6,000).
  • The repo's own GA convention already encodes QSS = HoH for 2021. Every other GA filing-status-keyed parameter maps SURVIVING_SPOUSE to the HoH/Single value in the 2021 era — 2021 standard deduction SURVIVING_SPOUSE = 4_600 (= HoH/Single; JOINT = 6_000) and personal exemption SURVIVING_SPOUSE = 2_700 (= HoH/Single; JOINT = 7_400). The standard-deduction file even documents deliberately that QSS maps to JOINT only going forward (2026+), with pre-2024 QSS entries preserved at the HoH value. The surplus rebate is the sole 2021-era outlier grouping QSS with JOINT.
  • Reachable, not theoretical. filing_status derives SURVIVING_SPOUSE via surviving_spouse_eligible (a widowed head with ≥1 child dependent, not remarried), so a GA tax unit draws the $500 cap in microsimulation, not only in scalar unit tests.

Materiality: $500 − $375 = $125 per affected unit, for GA surviving-spouse filers with 2021 Line-16 tax high enough for the cap to bind (GA's ~5.75% 2021 rate reaches $375 of tax at a few thousand dollars of taxable income, so most working widowed parents hit the full $125). Narrow population, one-time TY2021 — low fiscal materiality, but a definitively incorrect value.

Classification nuance: Per the value-mismatch rule this is CRITICAL — a verified value mismatch on a line this PR actively edits (the PR re-touches every filing-status row in this file), producing a real overpayment for a reachable population. The regulatory reviewer graded it SHOULD ADDRESS on the grounds that the affected population is narrow and the $500 is technically pre-existing (the PR does not introduce it). Presented with that nuance; the fix is trivial either way.

One-line fix: set SURVIVING_SPOUSE: 2021-01-01 from 500 to 375 in amount.yaml, and update the surviving-spouse test case (ga_surplus_tax_rebate.yaml:28-35) to expect 375.


Should Address

1. Missing edge-case test: zero 2021 liability → rebate 0 (the property that distinguishes this from an ordinary refundable credit)

File: policyengine_us/tests/policy/baseline/gov/states/ga/tax/income/credits/ga_surplus_tax_rebate.yaml
No case sets ga_income_tax_before_non_refundable_credits: 0 in 2021. min(cap, 0) = 0, so a filer with no 2021 liability gets nothing even though the rebate now flows through ga_refundable_credits. This is the single most valuable missing boundary: without it, a future regression that paid the full statutory amount regardless of liability (the natural "refundable credit" mistake) would pass CI. Add a 2021 case (e.g. HoH, ga_income_tax_before_non_refundable_credits: 0) asserting ga_surplus_tax_rebate: 0, ga_refundable_credits: 0, ga_income_tax: 0.

2. Missing edge-case test: pre-2021 year is inert (2020 → 0), locking in the 0000-01-01: 0 guard

File: ga_surplus_tax_rebate.yaml
The PR added 0000-01-01: 0 to amount.yaml specifically to stop backward extrapolation of the 2021 amount into earlier years, but no test locks it in (only 2021-active and 2022-zeroed are tested). This is the exact failure mode in the GA SSP lessons: "when a parameter's first entry is a positive value, periods before that date return that value via backward extrapolation." Add a 2020 case asserting ga_surplus_tax_rebate: 0 (and ga_refundable_credits: 0).

3. Refundable-credits aggregation deviates from the codebase convention

File: policyengine_us/variables/gov/states/ga/tax/income/ga_refundable_credits.py:15
Uses inline adds = ["ga_surplus_tax_rebate"]. The dominant *_refundable_credits pattern (~40 states) is a parameter-list path, e.g. adds = "gov.states.ga.tax.income.credits.refundable". GA already maintains the symmetric non_refundable.yaml list, so the consistent fix is a credits/refundable.yaml containing - ga_surplus_tax_rebate. Functionally correct as written (IN/NJ/MT use the inline form) — convention, not a bug, but low-effort and matches the nonrefundable side.

4. Parameter description uses "based on …" phrasing the style checklist disallows

File: policyengine_us/parameters/gov/states/ga/tax/income/credits/surplus_tax_rebate/amount.yaml:1
description: Georgia provides a surplus tax rebate of up to this amount, based on filing status, for the 2021 tax year. The parameter-patterns checklist disallows "based on …" (the filing-status dimension is already documented by breakdown: [filing_status], the year by the values). The PR already edits this line, so trimming is cheap: Georgia provides a surplus tax rebate of up to this amount. (Keep the "up to" — it reflects the new Line-16 cap.)

5. HB 162 PDF reference is missing the #page= anchor (3-page PDF)

Files: surplus_tax_rebate/amount.yaml:11-12 and ga_surplus_tax_rebate.py:10
Both cite https://www.legis.ga.gov/api/legislation/document/20232024/217823 with no page anchor. Per project convention (global instruction #4, multi-page PDFs get #page=XX), and the filing-status amounts (b)(1)(B) are on file page 2. Add #page=2. (Low risk that the legis.ga.gov API endpoint honors the fragment, but the anchor documents the location regardless.)

6. Variable reference is session-law-only; should cite the codified statute

File: policyengine_us/variables/gov/states/ga/tax/income/credits/ga_surplus_tax_rebate.py:10
reference = "https://www.legis.ga.gov/api/legislation/document/20232024/217823" points only at the HB 162 session-law PDF. The Line-16-cap and refundable logic rely on §48-7-20.2(b)(1)(A), (b)(3), and (d) — all in the codified statute — so the reference should primarily cite O.C.G.A. §48-7-20.2 (the Justia URL the parameter already uses), with HB 162 as secondary:

reference = (
    "https://law.justia.com/codes/georgia/title-48/chapter-7/article-2/section-48-7-20-2/",
    "https://www.legis.ga.gov/api/legislation/document/20232024/217823#page=2",
)

Suggestions

  1. Document the unmodeled statutory eligibility conditions as "Not modeled" in the ga_surplus_tax_rebate docstring — filed-both-2021-and-2022-returns ((a),(b)(1)), nonresident-alien exclusion ((a)(1)(A)), dependent exclusion with the earned-income carve-back ((a)(1)(B),(a)(2)), estate/trust exclusion ((a)(1)(C)), and part-year/nonresident Schedule-3-Line-9 proration ((b)(2)). Each is low-materiality for a single-year household microsim (dependents fold into the filer's tax unit and generally don't independently receive the rebate; defined_for=StateCode.GA treats residents as full-year), so this is a disclosure improvement. Note: the regulatory reviewer graded this SHOULD ADDRESS; it is classified SUGGESTION here under the documentation-improvement rule since none of the conditions produces a value mismatch in-model.
  2. Exact tax == cap boundary test — existing cases bracket it (below-max tax=200→200, above-max tax=1_000→375) but none sits at exactly tax == cap (HoH tax=375→375), where both arms of min_() are equal. Cheap boundary lock.
  3. Cap-binds case that also asserts the downstream flow — a companion to the existing cap-bound case (tax=200→rebate 200) that carries it to the top level (ga_refundable_credits: 200, ga_income_tax: 0), confirming refundability drives liability to exactly zero (never negative) when the cap binds with no other credits.
  4. Explicit nonrefundable-exclusion guard — the rebate's removal from the 2021 nonrefundable stack is proven only implicitly by the integration case's ga_non_refundable_credits: 287.13 (CDCC only). An explicit 2021 assertion would make the intent obvious. Not required.
  5. Case-naming convention — cases use descriptive names ("Single filer", …) rather than the skill's Case N, description. form. Consistent with the file's pre-existing style; do not renumber existing cases if touched.
  6. Parameter statute-title styleamount.yaml:9 uses 2024 CODE OF GEORGIA, Title 48, … while sibling GA files use Official Code of Georgia Annotated | O.C.G.A. § 48-7-20.2(b)(1)(B). Cosmetic; the citation is correct.
  7. ga_refundable_credits.py has no reference attribute — acceptable for a general aggregator (matches other *_refundable_credits files); the inline comment correctly cites §48-7-20.2(b),(d). Noting for completeness only.
  8. Rationale comments slightly verbosega_refundable_credits.py:11-14 and ga_surplus_tax_rebate.py:17-20 (4 lines each) vs the minimal-comment style. They explain genuine regulatory rationale and align with the "document regulatory logic in comments" guidance; optional tightening only.
  9. Downstream/integration assertions live in the variable's own test file (ga_surplus_tax_rebate.yaml:55-80 assert on ga_income_tax, ga_refundable_credits, etc.). Code-organization convention puts multi-variable interaction tests in integration.yaml; keeping them here is common and fine.

PDF Audit Summary

Category Items
Confirmed correct SINGLE=$250; SEPARATE=$250; HEAD_OF_HOUSEHOLD=$375; JOINT=$500 (all → §48-7-20.2(b)(1)(B)(i)-(iii), #page=2); lesser-of Line-16 cap logic (min_(cap, line_16_tax)) → (b)(1)(A)+(b)(3); Line 16 → ga_income_tax_before_non_refundable_credits mapping (tax before credits, "cannot exceed Line 16" per Form 500 #page=3 / IT-511 #page=18); refundable/pays-past-zero treatment → (d); one-time TY2021 window + 0000-01-01/2021/2022 zeroing; rebate not taxable → (c)
Mismatches — verified SURVIVING_SPOUSE = $500 should be $375 (CONFIRMED by code-path + 600 DPI; statute silent, GA Form 500 routes QSS to status D = HoH)
Mismatches — rejected Tax-Table-vs-Rate-Schedule rounding (≤ few dollars at cap, standard PE treatment); current-period vs pinned-2021 liability (inherent to single-year model of a backward-looking rebate, by design); GA NOL / Line 15b not modeled (standard PE omission, immaterial). None survived as a real defect in the mapping.
Unmodeled statutory items (by design) filed-both-years, nonresident-alien exclusion, dependent exclusion (+earned-income add-back), estate/trust exclusion, part-year proration; plus administrative (d)-delivery/(f)-setoff/(e)-no-interest/(g)-rulemaking provisions. Low materiality; recommend documenting (Suggestion 1).

Validation Summary

Lane Result
Regulatory Accuracy Core mechanics faithful (Line-16 cap = (b)(1)+(b)(3); refundable = (d); one-time TY2021). One value defect: SURVIVING_SPOUSE.
Reference Quality All amounts trace to statute except SURVIVING_SPOUSE (no authoritative source; contradicted by GA Form 500 status D). Missing #page=2 anchor; variable ref is session-law-only.
Code Patterns 0 critical. Convention deviations: inline adds=[...], "based on …" description phrasing. Period usage, entity types, zeroing structure, changelog all correct.
Test Coverage 8 cases — all 5 filing statuses, cap boundary, #1103 refundability path (negative ga_income_tax), 2022 zero. Integration arithmetic verified end-to-end. 2 missing edge cases (zero-liability, pre-2021). No absolute_error_margin: 1.
PDF Value Audit 3 enumerated amounts + Line-16 mapping + refundability confirmed against HB 162, IT-511, Form 500. 1 verified mismatch (SURVIVING_SPOUSE). All caveats cleared.
CI Status Passing — all 31 checks.

Review Severity: REQUEST_CHANGES

One CRITICAL finding: a verified value mismatch (SURVIVING_SPOUSE = $500 → should be $375) on a line the PR actively edits, producing a $125/unit overpayment for a real, reachable GA population. It passed both code-path and 600 DPI verification and has a one-line fix. Everything else is sound — the two headline changes (Line-16 cap and refundability) are faithful to the statute, CI is green, and test coverage of the core scenarios is real.

Nuance for the merge decision: the regulatory reviewer graded the SURVIVING_SPOUSE issue SHOULD ADDRESS because the population is narrow and the $500 is technically pre-existing (the PR re-touches the row but did not introduce the value). If you weigh the narrow/pre-existing aspect as decisive, this downgrades to COMMENT; under the value-mismatch rule it is CRITICAL → REQUEST_CHANGES. Either way the fix is trivial and should ship with this PR since it is editing the exact file.

Next Steps

To auto-fix issues: /fix-pr 9097

…aram list, references, and edge-case tests

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

DTrim99 commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

Fixes applied (commit 99fead7)

Thanks @hua7450 for the review. Addressed the findings:

Critical

  • Surviving spouse cap 500 → 375: confirmed against O.C.G.A. §48-7-20.2(b)(1)(B) — the statute names only single/MFS ($250), head of household ($375), and MFJ ($500); it never defines a QSS tier. GA Form 500 routes a qualifying surviving spouse to filing status D (head of household), so the applicable cap is $375. Updated amount.yaml and the surviving-spouse test.

Should-address

  • Converted ga_refundable_credits from an inline adds=[...] to the param-list convention: new credits/refundable.yaml list (mirrors the nonrefundable side); behavior preserved (still pays past zero).
  • Reworded the amount.yaml description to drop the disallowed "based on ..." phrasing.
  • Added #page=2 anchors to the HB 162 reference in the parameter and variable.
  • Added the codified O.C.G.A. §48-7-20.2 (Justia) reference as primary, keeping the HB 162 session-law cite.
  • Documented the unmodeled statutory conditions in the variable docstring.

Tests

  • Surviving-spouse expected value → 375.
  • Added: zero 2021 liability → 0; pre-2021 year inert (2020) → 0; exact tax == cap boundary; and cap-binds-downstream (rebate drives ga_income_tax to exactly 0).

Verification

  • GA credit + income-tax suites pass locally (rebate 12/12; GA income tax 127/127).
  • Pattern validator: CLEAN (0 new issues).
  • make format: done.

@hua7450
hua7450 self-requested a review July 20, 2026 20:41
@hua7450
hua7450 merged commit b7a9a12 into PolicyEngine:main Jul 20, 2026
35 checks passed
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.

GA surplus tax rebate (HB 162) wrongly capped at post-credit balance; statute caps it only at Form 500 Line 16

2 participants