Cap GA surplus tax rebate at Form 500 Line 16 and make it refundable#9097
Conversation
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 Report✅ All modified and coverable lines are covered by tests. 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
hua7450
left a comment
There was a problem hiding this comment.
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
- HB 162 (2023) enrolled act — O.C.G.A. §48-7-20.2 [PRIMARY, 3-page PDF; rebate amounts on file page 2]: https://www.legis.ga.gov/api/legislation/document/20232024/217823#page=2
- 2021 IT-511 Individual Income Tax Booklet (Form 500 instructions; Line 16 = tax before credits on physical page 18; filing-status letter D = "Head of Household or Qualifying Widow(er)" on physical page 12): https://dor.georgia.gov/document/booklet/2021-it-511-individual-income-tax-booklet/download#page=18
- 2021 Georgia Form 500 (Line 16 "Tax (Use Tax Table or Tax Rate Schedule)" before credits; Line 21 credits "cannot exceed Line 16" on physical page 3): https://apps.dor.ga.gov/FillableForms/webpdf/examples/2021GA500.pdf#page=3
- O.C.G.A. §48-7-20.2 (Justia, HTML — same statute text as HB 162): https://law.justia.com/codes/georgia/title-48/chapter-7/article-2/section-48-7-20-2/
- GA DOR HB 162 Surplus Tax Refund FAQs (corroborates $250/$375/$500 and "lesser of maximum or 2021 liability"; returns HTTP 403 to curl/WebFetch but works in a browser — valid, not a dead link): https://dor.georgia.gov/2022-hb-162-surplus-tax-refund-faqs
- Year: 2021 | Scope: PR changes only
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_SPOUSEto the HoH/Single value in the 2021 era — 2021 standard deductionSURVIVING_SPOUSE = 4_600(= HoH/Single; JOINT = 6_000) and personal exemptionSURVIVING_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_statusderivesSURVIVING_SPOUSEviasurviving_spouse_eligible(a widowed head with ≥1 child dependent, not remarried), so a GA tax unit draws the$500cap 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
- Document the unmodeled statutory eligibility conditions as "Not modeled" in the
ga_surplus_tax_rebatedocstring — 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.GAtreats 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. - Exact
tax == capboundary test — existing cases bracket it (below-max tax=200→200, above-max tax=1_000→375) but none sits at exactlytax == cap(HoH tax=375→375), where both arms ofmin_()are equal. Cheap boundary lock. - 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. - 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. - 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. - Parameter statute-title style —
amount.yaml:9uses2024 CODE OF GEORGIA, Title 48, …while sibling GA files useOfficial Code of Georgia Annotated | O.C.G.A. § 48-7-20.2(b)(1)(B). Cosmetic; the citation is correct. ga_refundable_credits.pyhas noreferenceattribute — acceptable for a general aggregator (matches other*_refundable_creditsfiles); the inline comment correctly cites §48-7-20.2(b),(d). Noting for completeness only.- Rationale comments slightly verbose —
ga_refundable_credits.py:11-14andga_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. - Downstream/integration assertions live in the variable's own test file (
ga_surplus_tax_rebate.yaml:55-80assert onga_income_tax,ga_refundable_credits, etc.). Code-organization convention puts multi-variable interaction tests inintegration.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>
Fixes applied (commit 99fead7)Thanks @hua7450 for the review. Addressed the findings: Critical
Should-address
Tests
Verification
|
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_rebatewas a flat amount placed last in the nonrefundable ordered stack, so it was effectively capped at the post-credit balance.ga_surplus_tax_rebatenow returnsmin(amount[filing_status], ga_income_tax_before_non_refundable_credits)— the statutory Line 16 cap.non_refundable.yaml; applied viaga_refundable_credits(adds) so it pays out past zero.surplus_tax_rebate/amount.yamlis 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):
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