Repository navigation
Add North Carolina's claim of right repayment itemized deduction (G.S. 105-153.5(a)(2)d) - #10028
Conversation
G.S. 105-153.5(a)(2)d, added by S.L. 2016-5 for 2014 and later, lets North Carolina itemizers deduct repayments of income included in AGI in an earlier year under a claim of right (Form D-400 Schedule A line 8). Repayments above $3,000 are deductible in full; smaller ones are reduced by 2% of federal AGI less other miscellaneous itemized deductions, which the 2016 and 2025 NCDOR worksheets both reproduce. PE had no input for these repayments, so it adds claim_of_right_repayment (person level; only the head's and spouse's count) and moves North Carolina's uncapped itemized items into a parameter list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…C taxed Review r1 (subfleet 20261009-090558-nc-itemized-review): - S.L. 2026-31 section 1.8 rewrites G.S. 105-153.5(a)(2)d for taxable years beginning on or after January 1, 2026: the repaid amount must have been included in AGI "as modified in G.S. 105-153.5 and G.S. 105-153.6" in the earlier year. New person input nc_claim_of_right_repayment_excluded_from_income (the part NC deducted when received, such as repaid Social Security) and a dated parameter apply it. - Count only the head's and spouse's other miscellaneous expenses against the pre-2018 floor; a dependent's are on the dependent's return. - The property grid now varies property taxes (so the $20,000 cap binds) and adds a 2026 grid for the excluded part. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Context from the session that opened this PR, for the US + core hub, which now owns it. I will not push to this branch. Reviews (GPT-6.1 Sol via Subfleet). Files are in
Evidence is in
Known gaps, documented in the variable and the body:
Follow-ups:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #10028 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 4 3 -1
Lines 76 56 -20
Branches 2 2
=========================================
- Hits 76 56 -20
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:
|
|
US + core hub merge audit, us#10028 at
|
Summary
North Carolina itemizers may deduct repayments of income that they included in AGI in an earlier year under a claim of right (Form D-400 Schedule A line 8). PolicyEngine had no input for these repayments and left the deduction out. This PR adds:
claim_of_right_repayment, a person-level input: the amount repaid this year of income included in AGI in an earlier year because it appeared the person had an unrestricted right to it (26 U.S.C. 1341), excluding repayments deducted in arriving at AGI;nc_claim_of_right_repayment_excluded_from_income, a person-level input used from 2026: the part of that repayment North Carolina deducted from AGI when it was received, such as repaid Social Security benefits;nc_claim_of_right_deduction, North Carolina's deduction under G.S. 105-153.5(a)(2)d;gov.states.nc.tax.income.deductions.itemized.other_sources, a parameter list of the itemized items outside the $20,000 mortgage and property tax cap (charitable, medical, and now claim of right). It replaces a hard-coded list innc_itemized_deductions, preserving the existing charitable and medical sources and adding the default-zero repayment deduction. Historical microdata comparisons showed no change; impact at the final merged head remains pending for the hub.The law
N.C. Gen. Stat. § 105-153.5(a)(2)d, added by S.L. 2016-5 § 2.1.(a) for taxable years beginning on or after January 1, 2014 (§ 2.1.(d)):
S.L. 2026-31 § 1.8 (PDF pp. 5–6, approved July 2, 2026) rewrites the first sentence for taxable years beginning on or after January 1, 2026: "an amount included in adjusted gross
incomeincome, as modified in G.S. 105-153.5 and G.S. 105-153.6, in an earlier taxable year". The statute page on ncleg.gov did not yet show this on October 9, 2026.NCDOR's Repayment of Claim of Right Worksheet, 2025 Form D-401 instructions, PDF p. 20 (the same on PDF p. 20 for 2021 through 2024), for repayments of $3,000 or less: line 3 is 2% of federal AGI ("If negative, enter the number zero"), and line 4, the deduction, is line 1 minus line 3.
Term (ii) is read from the 2016 worksheet (PDF p. 13), the first year NCDOR printed one. Other miscellaneous itemized deductions absorb the 2% floor first: line 5 = 2% of AGI − the other federal miscellaneous deductions (not below zero), and line 6 = repayment − line 5 (not below zero). Section 67(g) disallows those other deductions from 2018. That is why the 2018-and-later worksheet subtracts the whole floor. The formula encodes the statute, so it reproduces both worksheets: it subtracts the head's and spouse's miscellaneous expenses only while
gov.irs.deductions.itemized.misc.appliesis true.Design notes
Historical household comparisons (2025, North Carolina, single)
The earlier
mainand claim-branch runs are saved in~/reviews/us-hub/nc-itemized-other/evidence/households_{main,claim}.json(scripthouseholds.pythere). These are prior-run examples, rather than measurements repeated at the final merged head.mainNC income taxTests
Current tested head:
81528e0207591db0a453552cfba4d8c1c12a43c6. The first three YAML files ran individually, and the remaining six ran in one permitted baseline batch; the repeated standalone standard-deduction run is counted once. Python test files ran individually, all in the foreground. The lightweight untracked wrapper completes each test module, session and fixture teardown, then skips interpreter finalization. The six-file YAML batch reported 23 passed; its outer/usr/bin/time -lexited 1 afterward because the sandbox deniedsysctl kern.clockrateduring timing-resource reporting.The incomplete
test_parameter_yaml_keys.pyattempts are preserved and excluded from pass counts: the initial pytest 9 attempt stopped with a Python segmentation fault (exit 139); a shared-startup retry was interrupted (exit 130); an isolated importlib retry was interrupted before assertions (exit 2); and a default-import-mode retry with a conftest cutoff stopped after partial progress (exit 2). None produced a complete test result. The fatal traceback references pytest capture and logging; the crash cause remains unconfirmed. The completed code-health runs used workspace-local pytest 8.4.2, matching the lock, with the existing shared policyengine-core 3.32.15 dependencies, defaultprependimport mode,--confcutdir=policyengine_us/tests/code_health, unbuffered and uncaptured output (-u -s), and no custom periodic traceback thread. These environment and invocation changes do not establish the crash cause. Version evidence is saved inhub-evidence/pytest-env-versions.log; the completed results are reported below.The
test_rest_python_groups.pyinvocation additionally setPYTEST_DISABLE_PLUGIN_AUTOLOAD=1, inherited by its child collectors; pytest built-in and module-local fixtures remain available. Its children only collect placeholders with--collect-only --noconftest: they neither import the collected test modules nor execute their cases. The guard checksmake -noutput and uses a stub pytest command with synthetic success, failure and kill outcomes to test group orchestration. Its workflow checks read YAML; it runs no Rest groups, SPM tests or microsimulations.nc_claim_of_right_deduction.yamlnc_itemized_deductions.yamlnc_standard_or_itemized_deductions.yamlnc_standard_deduction.yamlnc_income_tax.yamlnc_income_tax_before_refundable_credits.yamlwagering_losses_deduction.yamltaxable_income_deductions_if_itemizing.yamlar_gambling_loss_deduction.yamltest_nc_claim_of_right_properties.pytest_parameter_yaml_keys.pytest_reference_urls.pytest_no_concatenated_reference_urls.pytest_rest_python_groups.pyYAML total: 45 passed across nine unique files. The six-file batch accounts for 23 passing cases in 62.04 s of pytest time; the repeated standalone standard-deduction run adds no cases to this total.
Python total: 133 passed across five files (property 7, parameter keys 34, reference URLs 32, no-concatenated URLs 48, Rest groups 12). Together with 45 YAML cases across nine files, 178 current-head cases passed across all fourteen targeted files.
Partner contract tests were neither run nor edited. Static inspection of the 144 partner YAML files found neither new repayment input, and no partner movement attributable to this PR was identified.
Standalone
test_parameter_yaml_keys.py: 34 passed in 3,169.53 s of pytest time; 3,267.67 s from wrapper start through module completion; 285,949,952 bytes maximum RSS; module exit status 0. This is a local sandbox measurement. Evidence:hub-evidence/pytest_parameter_yaml_keys.pytest8.{log,metrics.json}.Standalone
test_reference_urls.py: 32 passed in 2,491.45 s of pytest time; 2,594.51 s from wrapper start through module completion; 753,172,480 bytes maximum RSS; module exit status 0. Evidence:hub-evidence/pytest_reference_urls.{log,metrics.json}.Standalone
test_no_concatenated_reference_urls.py: 48 passed in 1,149.98 s of pytest time; 1,181.61 s from wrapper start through module completion; 60,555,264 bytes maximum RSS; module exit status 0. Evidence:hub-evidence/pytest_no_concatenated_reference_urls.{log,metrics.json}.Standalone
test_rest_python_groups.py: 12 passed in 1,872.34 s of pytest time; 1,909.60 s from wrapper start through module completion; 40,943,616 bytes maximum RSS; module exit status 0. Evidence:hub-evidence/pytest_rest_python_groups.{log,metrics.json}.nc_claim_of_right_deduction.yaml, 17 cases from the worksheets and the statute:nc_income_taxintegration case.test_nc_claim_of_right_properties.py, intests/unit(the Rest job'sremainingPython group). It runs a 720-point grid (repayment × AGI × other miscellaneous expenses × charity × property tax), one vectorized simulation each for 2016 and 2025, and a 240-point 2026 grid. The Python file compares the model with independent line-by-line implementations of the 2016 and 2025 worksheets over these finite grids. It also checks bounds, monotonicity, additivity outside the cap, and tax direction across grid points, including the standard-deduction crossover. The worksheet comparisons follow the worksheets' line structure.Invariants checked over the finite grids
Current property-test cost
Standalone
test_nc_claim_of_right_properties.py: 7 passed in 9.14 s of pytest time; 298.33 s from wrapper start through module completion, including startup; 975,110,144 bytes maximum RSS, measured with Darwinresource.getrusage; module exit status 0. The long startup reflected slow sandbox filesystem access. This local run is not a CI cost estimate. Metrics are saved inhub-evidence/pytest_property.metrics.json, with the pytest summary inhub-evidence/pytest_property.log.Historical test and cost evidence
The following measurements predate this merge and are retained as context:
remaininggroup on main (run 37926760594) collected 2,151 tests, including 11 skipped: 1,315.161 s of test time, 24:05.67 wall clock, 12,816,372 kB maximum RSS on the 16 GB runner.test_ar_gambling_properties.pyaccounted for 32 cases and 4.636 s in that CI group.Prior locked runs (
~/reviews/us-hub/nc-itemized-other/evidence/):mainff479aa74a: the NC and gambling YAML files, 28 passed.3b57231636, YAML:nc_claim_of_right_deduction.yamlplus those files, 45 passed in 9.24 s.test_nc_claim_of_right_properties.pyplus four parameter, reference and Rest-group code-health files, 133 passed in 29.84 s; 49.11 s wall clock and 1,244,741,632-byte maximum RSS for the combined run. These are combined-run measurements.Hub microsimulation impact (current head)
A real microsimulation on the default dataset, main at the merge base
35f3c1f92aagainst this PR's head81528e0207, for 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.nc_itemized_deductionsnc_income_taxstate_income_taxincome_taxhousehold_net_incomehousehold_benefitsVariables this PR adds (
nc_claim_of_right_deduction) have no value on the base side, so the table leaves them out.Comparison files are in
fixes/10028-impact/on the hub host.Historical microsimulation evidence
The prior body and evidence logs attribute four real microsimulation runs on the default dataset (
hf://datasets/policyengine/populace-us/populace_us_2024.h5@populace-us-2024-spm-20260909, 79,729 tax units):mainff479aa74aand this branch3b57231636, for 2025 and 2026. They ran one at a time under the shared lock (~/reviews/pe-us-merge-backlog-2026-10-02/impact/lockrun.sh). Record-by-record comparisons are in~/reviews/us-hub/nc-itemized-other/evidence/impact-ncit-c-{2025,2026}.json. The saved run JSONs and run logs do not record commit SHAs; attribution toff479aa74aand3b57231636comes from the prior PR body, evidence summary, and r3 review. These results are historical evidence and do not replace the hub's impact run at the current head.mainstate_income_tax,nc_income_tax,nc_taxable_income,nc_itemized_deductions,nc_standard_or_itemized_deductions,household_net_income)Those historical comparisons show no change because the dataset has no claim-of-right repayments.
claim_of_right_repaymentandnc_claim_of_right_deductionare zero on every record. The change matters for households that report a repayment, as in the table above. The parameter-list refactor changed no record in those historical runs.Axiom
axiom: TheAxiomFoundation/rulespec-us#1656 queued
RuleSpec parity issue #1656 was filed by MaxGhenis on October 11, 2026 at 14:05:53 UTC with the
pe-paritylabel. It covers the claim-of-right repayment deduction in G.S. 105-153.5(a)(2)d and the wagering-loss deduction in (a)(2)e, including their dated amendments, prerequisites and companion cases. It was filed from the existing draft at~/reviews/us-hub/nc-itemized-other/axiom/nc-105-153.5-a2-d-e-issue.md. Encoding remains pending. The hub corrected the issue's status line to "queued" on 2026-10-11.The draft records the prior RuleSpec/corpus checks:
main207486d8b5,us-nc/statutes/105/105-153.5/a.yamlisstatus: deferred: it encodes the $3,000 threshold and leaves#deduction_amountdeferred.Follow-ups (not in this PR)
The PR remains a draft. The hub owns the confirmation review at the pushed head, marking ready, CI, landing, and re-stacking #10038 afterward.
nc-wagering-losses-deduction, stacked on this one. It awaits its federal prerequisites and hub review. It cannot land before Federal gross income omits gambling winnings but still deducts wagering losses; OBBBA 90% wagering loss limit (2026+) not modeled #9637 is fully fixed:Guards on that branch fail until all three are fixed.
🤖 Generated with Claude Code