Skip to content

[codex] Add Maine income tax surcharge#8012

Open
DTrim99 wants to merge 5 commits intoPolicyEngine:mainfrom
DTrim99:codex/me-millionaire-surcharge
Open

[codex] Add Maine income tax surcharge#8012
DTrim99 wants to merge 5 commits intoPolicyEngine:mainfrom
DTrim99:codex/me-millionaire-surcharge

Conversation

@DTrim99
Copy link
Copy Markdown
Collaborator

@DTrim99 DTrim99 commented Apr 16, 2026

Fixes #8011.

Summary

  • Add Maine income tax surcharge parameters for rate, threshold, and in-effect status.
  • Apply the 2% surcharge to Maine taxable income above the filing-status thresholds starting in 2026.
  • Add direct surcharge tests and a before-credits integration case.

Tests

  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/me_income_tax_surcharge.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/me_income_tax_before_credits.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income -c policyengine_us
  • ruff check policyengine_us/variables/gov/states/me/tax/income/me_income_tax_before_credits.py policyengine_us/variables/gov/states/me/tax/income/me_income_tax_surcharge.py

Copy link
Copy Markdown
Collaborator Author

DTrim99 commented Apr 16, 2026

Implementation note: this models Maine H.P. 1491 / L.D. 2212, Part DDDD by adding an in_effect flag for the surcharge, 2026-only starting values for the rate and thresholds, and a me_income_tax_surcharge variable that is included in Maine income tax before credits.

Validation run locally:

  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/me_income_tax_surcharge.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/me_income_tax_before_credits.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income -c policyengine_us
  • ruff check policyengine_us/variables/gov/states/me/tax/income/me_income_tax_before_credits.py policyengine_us/variables/gov/states/me/tax/income/me_income_tax_surcharge.py

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (46eaaf1) to head (528acb2).
⚠️ Report is 36 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main     #8012      +/-   ##
===========================================
+ Coverage   94.82%   100.00%   +5.17%     
===========================================
  Files           5         7       +2     
  Lines          58        98      +40     
  Branches        2         0       -2     
===========================================
+ Hits           55        98      +43     
+ Misses          1         0       -1     
+ Partials        2         0       -2     
Flag Coverage Δ
unittests 100.00% <100.00%> (+5.17%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@DTrim99 DTrim99 marked this pull request as ready for review April 16, 2026 14:38
@DTrim99 DTrim99 requested a review from PavelMakarchuk April 16, 2026 14:38
Copy link
Copy Markdown
Collaborator Author

DTrim99 commented Apr 16, 2026

Follow-up added to this PR:

  • Part CCCC: raises the under-65 Maine Property Tax Fairness Credit cap from $1,000 to $1,500 starting in tax year 2026, with 2025/2026 regression coverage.
  • Part T: adds Maine affordability payments as a one-time 2025 refundable payment of $300 per eligible head/spouse, with filing-status AGI thresholds and dependent-status eligibility checks.
  • Part T subtraction: adds a reported Maine AGI subtraction for affordability payments included in federal AGI for tax years 2026 and 2027.

Additional validation run locally:

  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_base_cap.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/me_affordability_payment.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/me_affordability_payment_eligible.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_affordability_payment_subtraction.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_agi_subtractions.yaml -c policyengine_us
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income -c policyengine_us
  • pytest policyengine_us/tests/code_health/variable_names.py -q
  • ruff check on the new/touched Maine affordability and AGI-subtraction Python files

Copy link
Copy Markdown
Collaborator Author

DTrim99 commented Apr 16, 2026

Follow-up update pushed in 98482d443f:

  • Removed the separate Maine affordability payment in_effect parameter.
  • Let the payment's tax-year effect be controlled by gov.states.me.tax.income.credits.refundable, where me_affordability_payment appears only for 2025.
  • Added me_refundable_credits tests covering inclusion in 2025 and exclusion after 2025.

Validation:

  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/me_affordability_payment_eligible.yaml policyengine_us/tests/policy/baseline/gov/states/me/tax/income/me_refundable_credits.yaml -c policyengine_us
  • ruff check policyengine_us/variables/gov/states/me/tax/income/credits/me_affordability_payment_eligible.py
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income -c policyengine_us
  • git diff --check

@DTrim99
Copy link
Copy Markdown
Collaborator Author

DTrim99 commented Apr 16, 2026

PR Review

🔴 Critical (Must Fix)

  1. Hard-coded year logic in policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_affordability_payment_subtraction.py:18:
    in_effect = (period.start.year >= 2026) & (period.start.year <= 2027)
    This directly violates the CLAUDE.md rule: "NEVER use period.start.year or other conditional checks to return hardcoded values". Create a parameter (e.g., gov.states.me.tax.income.adjusted_gross_income.affordability_payment_subtraction.in_effect) with 2026-01-01: true and 2028-01-01: false, then use it in the formula. The surcharge's in_effect.yaml pattern is a good model.

🟡 Should Address

  1. Redundant formula in me_affordability_payment_subtraction_reported.py:17-18:

    def formula(tax_unit, period, parameters):
        return 0

    With default_value = 0 already set, the formula is superfluous. Since this is a user-input variable, drop the formula — the default handles the zero case.

  2. Missing defined_for = StateCode.ME in me_affordability_payment_subtraction_reported.py. The variable is ME-specific but is currently defined for all tax units.

  3. Uprating source in parameters/gov/states/me/tax/income/surcharge/threshold.yaml: All thresholds are uprated by gov.irs.uprating (federal CPI-U). L.D. 2212 Sec. DDDD-5 specifies a COLA "beginning in 2027" but doesn't explicitly reference the federal CPI-U. Please verify this matches Maine's COLA basis; other ME parameters (e.g., property tax fairness) also use gov.irs.uprating, so consistency may be intentional — worth confirming in the reference.

  4. Scalar if in vectorized context in me_income_tax_surcharge.py:15-16:

    if not p.in_effect:
        return 0

    While parameters are scalar per period, prefer the vectorized pattern:

    return p.in_effect * max_(taxable_income - threshold, 0) * p.rate

    This is more consistent with other PolicyEngine formulas.

  5. Eligibility logic in me_affordability_payment_eligible.py:20-24: The "claimed as dependent" check uses head_or_spouse & dependent on persons — this is correct for cases where someone's record marks them as both head and dependent within the same tax unit, but the more common scenario is where a dependent filer creates a separate tax unit. Consider whether this covers all bill-required scenarios in L.D. 2212 Part T (e.g., filers claimed on another person's return).

🟢 Suggestions

  1. in_effect.yaml description reads awkwardly: "Maine applies its income tax surcharge if this is true." — consider "Whether Maine's income tax surcharge is in effect."

  2. Test coverage gap: No YAML test exercises the surcharge threshold uprating behavior in 2027+ years. Adding one would lock in the COLA behavior.

  3. programs.yaml: Consider whether the new Maine affordability payment and surcharge warrant entries/updates here — the file is described as the source of truth for program coverage.

  4. Refundable credits entries for 2025 and 2026 differ only by me_affordability_payment. This is clear as written but adds 14 lines of duplication; not blocking.


Validation Summary

Check Result
Regulatory Accuracy Thresholds ($1M/$750K/$1.5M/$1.5M/$1.5M) and 2% rate match L.D. 2212 Part DDDD; affordability payment amount and AGI limits match Part T
Reference Quality All new params have L.D. 2212 page-anchored references
Code Patterns 1 critical hard-coded year issue; 1 redundant formula; 1 missing `defined_for`
Test Coverage Surcharge and eligibility thresholds well-covered; COLA behavior untested
CI Status All checks passing

Next Steps

Address the critical hard-coded year issue before merge. The remaining items are quality improvements. To auto-fix: `/fix-pr 8012`.

Copy link
Copy Markdown
Collaborator Author

DTrim99 commented Apr 16, 2026

Addressed the CC review feedback in f787849b17:

  • Replaced the hard-coded period.start.year affordability-payment subtraction window with gov.states.me.tax.income.agi.subtractions.affordability_payment_subtraction.in_effect (2026-01-01: true, 2028-01-01: false).
  • Removed the redundant formula from me_affordability_payment_subtraction_reported and scoped it with defined_for = StateCode.ME.
  • Switched me_income_tax_surcharge to the vectorized p.in_effect * max_(...) * p.rate pattern.
  • Reworded the surcharge in_effect.yaml description.
  • Added a pre-2026 subtraction test.

On the surcharge uprating comment: I verified gov.irs.uprating is repo-defined from Chained CPI-U (parameters/uprating_extensions.py) and is the same uprating parameter used by other Maine income tax parameters tied to section 5403 annual adjustments. I did not add a 2027 surcharge uprating assertion because a simple current-parameter lookup still returns the 2026 threshold value for later years, so that would not currently be a meaningful regression test without broader parameter-uprating work.

Validation:

  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income/taxable_income/me_affordability_payment_subtraction.yaml policyengine_us/tests/policy/baseline/gov/states/me/tax/income/me_income_tax_surcharge.yaml -c policyengine_us
  • ruff check policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_affordability_payment_subtraction.py policyengine_us/variables/gov/states/me/tax/income/adjusted_gross_income/me_affordability_payment_subtraction_reported.py policyengine_us/variables/gov/states/me/tax/income/me_income_tax_surcharge.py
  • policyengine-core test policyengine_us/tests/policy/baseline/gov/states/me/tax/income -c policyengine_us
  • pytest policyengine_us/tests/code_health/variable_names.py -q
  • git diff --check

Replace the surcharge in_effect parameter with pre-2026 zero-rate and
infinite-threshold defaults so the formula can be fully vectorized and
evaluated in any year without the threshold breakdown lookup failing.

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

Program Review: PR #8012 -- Maine Income Tax Surcharge + Affordability Payments + Property Tax Credit

Source Documents

Critical (Must Fix)

  1. Dependent check is a logical no-op -- uses unreachable pattern instead of existing variables.

    • File: policyengine_us/variables/gov/states/me/tax/income/credits/me_affordability_payment_eligible.py
    • Law: Sec. T-1(1)(C)(3), PDF page 157: "May not be claimed as a dependent on another taxpayer's return for the tax year."
    • Problem: The code computes head_or_spouse & dependent where dependent = ~head & ~spouse. This is always false ((A | B) & (~A & ~B) = 0). The dependent exclusion never triggers in normal simulation. The test case "Head or spouse claimed as a dependent is ineligible" only passes because it manually overrides both is_tax_unit_head: true and is_tax_unit_dependent: true for the same person, which is impossible under normal derivation.
    • Fix: Use existing variables head_is_dependent_elsewhere and spouse_is_dependent_elsewhere (which rely on the input variable claimed_as_dependent_on_another_return). Update the test to set claimed_as_dependent_on_another_return: true instead of the contradictory override.
    • Sources: Regulatory review ISSUE 1
  2. All href URLs point to wrong bill version (item=2 instead of item=37).

    • Files: All 7 parameter files and all variable files with references
    • Problem: Every reference href uses item=2 (an earlier draft of the bill). The enacted chaptered law is item=37 (Public Law 2025, Chapter 650). The two documents have different pagination. Readers clicking these links will land on a different document version.
    • Fix: Replace item=2 with item=37 in all hrefs.
    • Sources: Reference review C1
  3. 8 of 12 Part T page references are off by +1 (wrong page numbers).

    • Files affected:
      • amount.yaml, income_limit.yaml, me_affordability_payment.py, me_affordability_payment_eligible.py, refundable.yaml: #page=158 should be #page=157 (the $300 amount, income limits, and eligible recipient definitions are on page 157)
      • in_effect.yaml, me_affordability_payment_subtraction.py, me_affordability_payment_subtraction_reported.py: #page=159 should be #page=158 (the subtraction modification is on page 158)
    • Correct pages: Part T content starts on page 157 (payment definition) and page 158 (subtraction provision). Part CCCC/DDDD on page 220 (4 references -- all correct).
    • Sources: Page verification report
  4. CPI uprating methodology mismatch -- will produce wrong surcharge thresholds for 2027+ (code-path CONFIRMED).

    • File: policyengine_us/parameters/gov/states/me/tax/income/surcharge/threshold.yaml
    • Law: Sec. DDDD-5, PDF page 221: "the Chained Consumer Price Index for the 12-month period ending June 30th of the preceding calendar year divided by the Chained Consumer Price Index for the 12-month period ending June 30, 2025."
    • Code: Uses gov.irs.uprating, which computes the Chained CPI-U average over a September-to-August window (the IRS method per IRC Sec. 1(f)(3)). This is a 2-month offset from the Maine-specified July-to-June window, with a different base year.
    • Impact: 2026 values are correct (explicitly defined). 2027+ thresholds will diverge. The error is cumulative.
    • Code-path verified: The parameter is actively used in me_income_tax_surcharge.py, which feeds into me_income_tax_before_credits -> me_income_tax_before_refundable_credits -> state_income_tax. Confirmed live and active.
    • Fix: Create a Maine-specific uprating parameter using a July-to-June Chained CPI-U window with a base period ending June 30, 2025.
    • Sources: PDF audit (surcharge) B.1, code-path verification, reference review W3
  5. amount.yaml missing end date -- affordability payment amount persists beyond its 2025-only statutory authorization.

    • File: policyengine_us/parameters/gov/states/me/tax/income/credits/affordability_payment/amount.yaml
    • Problem: The parameter has 2025-01-01: 300 with no subsequent entry. While refundable.yaml drops me_affordability_payment from 2026+, the variable itself will still compute $300 for eligible filers in 2026+ if queried directly. The law (Sec. T-1(1)(E)) explicitly limits the payment to "a tax year beginning on or after January 1, 2025 but not later than December 31, 2025."
    • Fix: Add 2026-01-01: 0 to terminate the parameter.
    • Sources: Code review W5, test review 2f/6b
  6. cap.yaml may have duplicate metadata keys overwriting correct values.

    • File: policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/cap.yaml
    • Problem: The PR diff shows duplicate period, label, and description metadata keys. YAML parsers silently take the last value for duplicate keys, which could result in incorrect label/description values. The label may be overwritten from "Maine property tax fairness credit cap" to "Maine property tax fairness credit age threshold."
    • Fix: Verify final merged file has no duplicate keys and preserves the correct description and label.
    • Sources: Reference review C2

Should Address

  1. documentation field used instead of reference in two variable files.

    • Files: me_affordability_payment_subtraction.py (line 9), me_affordability_payment_subtraction_reported.py (line 9)
    • Per PolicyEngine standards, explanatory text should go in reference, not documentation. The documentation field is a legacy pattern. Remove it from both files.
    • Sources: Regulatory review ISSUE 2, code review C1
  2. default_value = 0 is redundant.

    • File: me_affordability_payment_subtraction_reported.py (line 16)
    • float variables already default to 0 in PolicyEngine. Remove the line.
    • Sources: Regulatory review ISSUE 3, code review W7
  3. Missing test: SURVIVING_SPOUSE filing status for affordability payment eligibility.

    • The income_limit parameter defines SURVIVING_SPOUSE at $100,000, but no test exists for this filing status. All other filing statuses are covered.
    • Sources: Regulatory review, test review 2a
  4. Missing tests: at-threshold boundary tests for surcharge and affordability payment.

    • No test where surcharge taxable income equals the threshold exactly (should produce $0).
    • No at-threshold tests for affordability eligibility for HoH ($75K), Joint ($100K), Separate ($50K), or Surviving Spouse ($100K). Only SINGLE has an at-threshold test.
    • Sources: Test review 1a, 2b
  5. Missing test: surcharge below-threshold in 2026.

    • No test where income is below the surcharge threshold in 2026 (the existing below-threshold test uses 2025 period, testing only the temporal gate, not the max_(x, 0) logic).
    • Sources: Test review 1c
  6. Missing integration test for 2026 provisions.

    • No test verifies the full chain: surcharge + AGI subtraction + property tax cap all active simultaneously. An integration test would catch wiring errors between the new variables.
    • Sources: Test review section 5
  7. Parameter description format issues in 4 files.

    • in_effect.yaml: "Whether Maine's..." does not follow the "Maine uses this indicator..." pattern.
    • rate.yaml: Uses "applies" instead of approved verbs (limits, provides, sets, excludes, deducts, uses).
    • threshold.yaml: Uses "applies" and "its" instead of standard pattern.
    • amount.yaml: Mixes concept name into "this X" placeholder.
    • Sources: Code review W1-W4, reference review W5
  8. income_limit.yaml filing status entries not nested under values: key.

    • File: policyengine_us/parameters/gov/states/me/tax/income/credits/affordability_payment/income_limit.yaml
    • Other breakdown parameters in this PR (e.g., threshold.yaml) use the values: sub-key. Verify this syntax loads correctly and consider adding values: for consistency.
    • Sources: Code review W6, reference review W4
  9. Reference titles lack subsection-level citations.

    • All 7 parameter files cite only the Part/Section level (e.g., "Part T, Sec. T-1") without subsection detail (e.g., "subsection 1(A)," "subsection 1(C)(2)," "subsection 4"). Adding subsection references improves traceability.
    • Sources: Reference review W2
  10. Missing absolute_error_margin: 0.1 on new test files.

    • 7 new/modified test files omit absolute_error_margin. While integer and boolean outputs may pass without it, best practice per the testing patterns skill is to always include it.
    • Sources: Test review 7a

Suggestions

  1. Add YAML comment to refundable.yaml explaining modeling decision.

    • The affordability payment is a direct payment program per the statute (Sec. T-1(3)), not a tax credit. Modeling it as a refundable credit is a reasonable implementation choice, but a comment would document the rationale.
    • Sources: Reference review W6
  2. Add permanent MRSA statute citations when codified.

    • Surcharge: 36 MRSA section 5111(7)
    • Property tax credit cap: 36 MRSA section 5219-KK(2-D)
    • Affordability payment: uncodified session law (no permanent citation available yet)
    • Sources: Reference review W1
  3. Missing test: property tax credit cap unchanged at $2,000 for age 65+ in 2026.

    • A regression test confirming the cap increase only affects the under-65 bracket would be valuable.
    • Sources: Test review 4a
  4. Missing test: zero taxable income with surcharge.

    • Edge case: zero income should produce zero surcharge.
    • Sources: Test review 1d
  5. Document that estates and trusts are not covered.

    • Sec. DDDD-2 extends the surcharge to estates and trusts at the single filer rate. PolicyEngine does not model estates/trusts. Worth noting in code comments.
    • Sources: Regulatory review ISSUE 5, PDF audit (surcharge) C.1

PDF Audit Summary

Category Count
Confirmed correct 18 (8 surcharge/property tax + 10 affordability)
Mismatches (code-path confirmed) 1 (CPI uprating methodology for 2027+)
Mismatches rejected (code-path cleared) 0
Unmodeled items 6 (estates/trusts, dependent exemption phase-out CPI, full-year residency, filing deadline, unclaimed property, municipal assistance exclusion)

Validation Summary

Check Result
Regulatory Accuracy 1 critical (dependent check no-op), 1 informational (CPI proxy)
Reference Quality 2 critical (wrong bill version, cap.yaml duplicates), 6 warnings
Code Patterns 1 critical (documentation field), 6 warnings
Test Coverage 6 gaps (surviving spouse, at-threshold boundaries, below-threshold, integration, error margins)
PDF Value Audit 1 mismatch (CPI uprating) / 18 confirmed correct
Page References 8 wrong / 4 correct
CI Status All passing

Review Severity: REQUEST_CHANGES

Six critical issues must be fixed before merge:

  • The dependent check is logically unreachable and the test is misleading (correctness bug).
  • All href URLs point to the wrong bill version.
  • 8 of 12 Part T page references are off by +1.
  • CPI uprating will produce wrong thresholds for 2027+ (confirmed by code-path trace).
  • Affordability payment amount persists beyond its 2025-only statutory authorization.
  • Property tax cap.yaml may have duplicate metadata keys corrupting values.

Next Steps

To auto-fix issues: /fix-pr 8012

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 Maine millionaire income tax surcharge

2 participants