Separate the dependent portion of 11 states' personal exemptions#8696
Separate the dependent portion of 11 states' personal exemptions#8696DTrim99 wants to merge 3 commits into
Conversation
Adds Child Poverty Impact Dashboard contrib reforms that split the dependent
portion of each state's per-person personal exemption (or credit) into its own
variable + parameters, mirroring the existing RI/DE/OR/VA reforms. Each defaults
to a no-op (in_effect=false; default amount reproduces current law) and lets the
per-dependent amount be adjusted or zeroed independently of the head/spouse
exemption.
States and how they separate:
- Bundled per-person exemption split into head/spouse + dependent: HI (preserves
the aged add-on), IN (base; the additional per-child exemption is untouched),
MI, NE, OK, VT, WI, WV.
- AGI-stepped per-person amount (MD, OH): the dependent amount defaults to the
baseline income-stepped schedule via a negative-amount sentinel, with an
optional flat override and income phase-out group.
- AR: redirects the existing person-level dependent slice of the personal credit
to a contributed amount (its base is otherwise shared with head/spouse). No
age limit, since it is summed via `adds`.
Each reform exposes in_effect + amount (+ age_limit for the exemption states;
+ phaseout for MD/OH). Indiana's module dir is the Python keyword `in`, so it is
imported dynamically in reforms.py and uses getattr for parameter access.
Parameters under gov.contrib.states.{st}.dependent_exemption (AR:
dependent_credit). Registered in reforms.py. Each state has YAML tests covering
the default no-op, amount reduction/elimination, childless-filer no-op, and
age-limit fallback; all pass. System smoke-imports cleanly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…coverage - Remove accidentally committed SEP_MSG.tmp scratch file from repo root - HI dependent-exemption reform: use `reference` field instead of `documentation` - Add MD/OH flat-amount and phaseout test cases (previously untested paths) - Add joint-filing test cases (MD, OH, MI, AR, HI, IN) covering the head/spouse-vs-dependent count split in 2-adult units - Strengthen MD/OH no-op case documentation Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Program Review — Separate the dependent portion of 11 states' personal exemptions
Scope: Child Poverty Impact Dashboard contrib reforms, 11 states (AR, HI, IN, MD, MI, NE, OH, OK, VT, WI, WV) · three separation patterns (bundled split; AGI-stepped sentinel + phaseout; shared credit-base redirect)
A large but disciplined PR. All four review dimensions cleared the implementation: every state defaults to a verified no-op, cross-state isolation holds (no copy-paste/wrong-state references — the main risk in a multi-state PR), variable overrides match their baselines exactly, and all 55 YAML cases pass. Requesting changes to tighten the test suite before merge — the gaps are in what the tests prove, not in the code.
Requested changes
-
Add an end-to-end tax/net-income assertion (systemic — affects all 11 states). Every test currently asserts the reform's own exemption/credit-total variable (e.g.
md_total_personal_exemptions,hi_regular_exemptions,ar_personal_credits) — one level above the per-dependent variable, which does prove the head/spouse split arithmetic. But no test asserts state taxable income, state tax, or net income, so the exemption→tax wiring is unproven end-to-end. AR is most exposed (it asserts only a credit total, never a resulting AR tax/net-income figure). Please add at least one downstream-outcome case — ideally for AR plus one bundled-split state and MD/OH. -
Add the joint 2-adult case to NE, OK, VT, WI, WV. These five states have 4 cases and omit the joint two-adult + dependents case that HI/IN/MI/MD/OH/AR include. That case is precisely what catches off-by-one / sign-flip errors in the
personal_count = size − dependents + over-age dependentsformula — the risk the PR description itself flags. Add a joint 2-adult + 2-dependent case to each, mirroring HI/IN/MI.
Suggestions (non-blocking)
- Re-run the canceled "Quick Feedback (Selective Tests + Coverage)" job — it was canceled by an infra runner-shutdown, not a real failure (the
Full Suite - Contrib (states-shard-*)jobs that run these tests all passed). - Several count variables are typed
float/unit = USD(should be int/count); unusedinstantimport in ~7 reform files. - Most contrib params omit
reference— consistent with the merged DE/RI/VA/OR siblings, so optional; a one-line provenance comment on eachamount.yamlnoting it mirrors the state baseline would make the derivation explicit. - Minor consistency: inconsistent state-level
__init__.pypresence (works via namespace packages); WI/WV test values lack numeric underscores; effective-date style varies (0000-01-01vs2025-01-01) for inert defaults.
Validation Summary
| Check | Result |
|---|---|
| Regulatory Accuracy | ✅ No-op fidelity verified for all 11; bundled-split arithmetic, MD/OH sentinel, and state-specific preservations (HI aged add-on, IN per-child exemption, AR credit base, MI stillborn, OK extras, WV size==0) all correct; isolation confirmed |
| Reference Quality | ✅ All 11 default amounts trace to state baselines; metadata complete & consistent with siblings |
| Code Patterns | ✅ All update_variable overrides match baseline name/entity/period/value_type; non-negative fallback counts; IN dynamic import correct; 5-year gating loop references each state's own parameter — no cross-state leakage |
| Test Coverage | |
| CI Status |
Review Severity: REQUEST_CHANGES (approve-leaning — gaps are test-completeness only)
To auto-fix: /fix-pr 8696
🤖 Generated with Claude Code
Resolves PavelMakarchuk review on PR PolicyEngine#8696: - Add downstream-tax/net-income assertions (AR, MI, MD, OH) so tests no longer stop at intermediate exemption/credit variables - Add married-filing-joint 2-adult cases for NE, OK, VT, WI, WV - Add age-17 (eligible) / age-18 (excluded) boundary cases for all 10 age-limit states - Enrich AR dependent credit reference (AR1000F Line 7A + statute subsections); fix WI/WV test literal underscores - Remove unused `instant` imports (7 reform modules); add ne/wi re-export __init__.py; type dependent-count helpers as int (drop USD) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fixes Applied (full scope)Addresses PavelMakarchuk's review. CI: the prior "Full Suite - Rest" failure was a runner cancellation, not a test failure. Blocking review items
Suggestions
Verification
|
What this does
Adds Child Poverty Impact Dashboard contrib reforms that separate the dependent portion of each state's per-person personal exemption (or credit) into its own variable + parameters, for 11 states: AR, HI, IN, MD, MI, NE, OH, OK, VT, WI, WV. This mirrors the existing RI/DE/OR/VA reforms and lets the per-dependent amount be adjusted or eliminated independently of the head/spouse exemption (which most of these states bundle together).
Each reform:
in_effect=false, and when on, the default amount reproduces current law.gov.contrib.states.{st}.dependent_exemption.{in_effect, amount, age_limit/*}(AR usesdependent_credit; MD/OH also get aphaseoutgroup).How each separates
{st}_dependent_exemption. HI preserves its aged add-on; IN leaves the existing per-child additional exemption untouched.baseis otherwise shared with head/spouse). No age limit — it's summed viaadds, which only reflects uniform per-dependent amounts.Indiana's module directory is the Python keyword
in, so it is imported dynamically inreforms.pyand usesgetattrfor parameter access.Tests
Each state has YAML tests (
tests/policy/contrib/states/{st}/) covering: default no-op for a family with children, amount reduction / elimination (amount: 0), childless-filer no-op, and (exemption states) age-limit fallback. All pass. The system smoke-imports cleanly with all 11 registered increate_structural_reforms_from_parameters.Follow-up
Once released, the dashboard flips these states to amount-editable (separate PR). Companion: #8691 (SC dependent-exemption parameter).
🤖 Generated with Claude Code