Repository navigation
Conversation
N.Y. Tax Law 615(a) computes New York itemized deductions as they existed before P.L. 115-97, but ny_itemized_deductions_max added the federal interest_deduction, so post-2017 loans got the federal $750,000 limit and no home equity debt. A new ny_mortgage_interest_deduction applies the preserved $1,000,000 / $100,000 limits (halved for separate returns) with per-home fair market value room, and ny_interest_deduction substitutes it for the federal mortgage component. New inputs default to values that add no home equity debt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6J5LH2sLC5oX6pUHnC
Building ny_interest_deduction from its components dropped an interest total supplied as deductible_interest_expense, which ny_itemized_deductions_max.yaml uses. Start from interest_deduction and swap only the federal mortgage component for New York's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LwQq6J5LH2sLC5oX6pUHnC
|
Ready for hub review Head: Ownership check
Reproduced on main2025, single, $36,000 interest, $900,000 loan from 2020: What the item asked, and where
Hand computationsAll are in the YAML comments.
Tests (local, one file per process)
MutantsEach ran in its own process in a separate worktree, with the code restored after. All 7 are killed:
CIThe PR is a draft, so the Pull request run at 4b893cf shows Judgment calls
Extra files beyond the spec's list
Proposed follow-ups
Generated by Claude Code |
|
Ready for hub review Independent review, round 1, of head Sources. No source was reachable from this VM. govinfo.gov, uscode.house.gov, ecfr.gov, irs.gov, nysenate.gov, legislation.nysenate.gov and tax.ny.gov all returned FindingsP2-1. A fair market value of 0 (the default) disallows interest the law allows, and can take New York below both main and federal
An unknown home value is read as a home worth $0. Any debt counted as home equity debt then gets no room, so its interest is disallowed. On top of that, because a non-acquisition balance is added to line 9's total debt, the share can fall below federal, and the floor is turned off when non-acquisition debt is reported ( Witnesses, run at this head (
On main both W1 and W2 give New York the federal 20,000. The input's own documentation tells users to "Include the interest on this debt in the home mortgage interest inputs". A user who does that and leaves FMV blank, which the documentation also invites ("Leave at 0 if unknown"), loses interest that New York allows on any home with positive equity. On survey data the same default denies home equity treatment to every acquisition balance above $1,000,000. The data carries no home value, and these new inputs are 0 for every record. Mortgaged homes with positive equity are the norm, so Hawaii's merged rule (treat every home as worth at least its mortgages) fits survey data better. The hand-off's reason for 0, that it "keeps main's (zero) home equity result", keeps a part of main's bug rather than main's behaviour. Main's result is the federal amount, which the 1M limit already changes. Suggested replacement for line 49, so that 0 means unknown, as # 0 means unknown: treat the home as worth at least the debt on it,
# as the Hawaii calculation does.
equity_room = where(
fair_market_value > 0, max_(fair_market_value - treated, 0), np.inf
)Then update the input documentation ( P2-2. The new input tells users to make the federal deduction wrong
The hand-off's follow-up claim is confirmed. The federal calculation sees only the two acquisition balances, so interest on home equity debt that is folded into That gap exists on main. But this PR adds an input whose documentation directs every NY user with home equity debt to put its interest in or the hub should file the federal follow-up the hand-off proposes (move the non-acquisition balance to a shared input that the federal calculation reads and disallows under 163(h)(3)(F)) before this lands. I couldn't read 163(h)(3)(F) to quote it. P3-1. Floor at federal versus the worksheet: a source conflict for the hub to rule on (METHODOLOGY_CHOICE)
§ 615(a), as quoted in the spec, adopts the pre-TCJA deduction. That deduction allows interest on qualified indebtedness and prescribes no three-place rounding. The merged Hawaii code cites Treas. Reg. 1.163-10T for that point; I couldn't read it. Under the project's rule, the 2017 worksheet fills that gap, and the worksheet gives 49,980. The floor follows neither source: it is a PE safeguard copied from the merged Hawaii calculation. The exact statutory ratio gives 50,000 here, so the floor and the unrounded statute agree on this witness. The current mix is asymmetric. Rounding up above the exact amount is kept (the no-FMV case allows 26,680 where the exact amount is 26,666.67). Rounding down below the exact NY amount is kept whenever NY exceeds federal (29,320 against the exact 29,333.33). Rounding down is undone only when it would cross the federal amount. Both the worksheet and the exact ratio are defensible, and the floor is consistent with Hawaii, so this is for the hub to rule on. If the hub keeps it, record it in the register. If not, either drop the rounding (use the exact ratio; the floor is then redundant when no non-acquisition debt is reported) or drop the floor (the worksheet governs, 49,980). P3-2. Body and hand-off claims that are now false or loose
P3-3. The grandfathering date is still a year proxy (spec deviation)The spec says the implementation "must obtain that fact rather than infer it from the year". The PR keeps the 1987-or-earlier convention (judgment call 1). Only one witness depends on it, "Grandfathered debt reduces the acquisition-debt limit" (origination 1986), and it is unaffected by the October 13 boundary. No test sits at 1987. The proxy is wrong only for a loan taken out between October 14 and December 31, 1987 that is still outstanding, which is negligible today. I agree with keeping one shared convention rather than a NY-only date. The hand-off's follow-up (one exact-date flag read by the federal, HI and NY calculations) is the right fix. Checked and sound
I ran YAML summaries only, so I name the killing case by which case asserts the changed output rather than from a failure listing. M1 is killed by "New York keeps the $1,000,000 acquisition-debt limit" ( M10 survives because it is equivalent, not because a test is missing. When
What I couldn't check
Generated by Claude Code |
|
Picking this up for the US hub. I'll post a hand-off comment here when it's ready. Generated by Claude Code |
Bring the branch up to date before the round 1 fixes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er allocation share Round 1 review of the New York pre-TCJA mortgage interest calculation: - A fair market value of 0 now means unknown, as the Hawaii calculation and the origination-year inputs treat it, so home equity debt on a home without a value is capped only by the $100,000 ($50,000 separate) limit instead of losing its interest. - The deductible share is the larger of the 2017 Publication 936 worksheet's three-place share and the unrounded ratio of Treas. Reg. 1.163-10T(d); CCA 201201017 allows any reasonable method. The federal floor, which followed no source, goes. The pass-through stays so a directly supplied deduction is not limited twice. - The non-acquisition debt inputs now say that PE's federal calculation does not disallow that interest after 2017. - YAML expectations, two new cases and the Hypothesis properties follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Ready for hub review Head: Ownership and merge
Findings
YAML cases (
|
| Case | Old NY | New NY | Federal (unchanged) |
|---|---|---|---|
| New York keeps the $1,000,000 acquisition-debt limit | 36,000 | 36,000 | 30,000 |
| Acquisition debt above the limit counts as home equity debt | 29,320 | 29,333.33 | 20,000 |
| Separate returns halve both limits | 18,340 | 18,340 | 12,500 |
| Without a fair market value, only the dollar limit caps home equity debt (renamed) | 26,680 | 29,333.33 | 20,000 |
| Fair market value limits home equity debt | 27,720 | 27,733.33 | — |
| Non-acquisition debt counts as home equity debt up to the limit | 29,995 | 30,000 | 35,000 |
| Grandfathered debt reduces the acquisition-debt limit | 45,850 | 45,850 | 31,250 |
| Each home's equity room limits its own excess debt | 43,980 | 44,000 | — |
| A directly supplied deduction passes through when nothing is disallowed | 12,000 | 12,000 | — |
| New D: A directly supplied deduction passes through even with balances | — | 12,000 | — |
| New W2: Without a fair market value, home equity debt keeps its interest | (17,140 at old head) | 20,000 | 20,000 |
| Before 2018 New York uses the federal amount | 26,666.67 | 26,666.67 | 26,666.67 |
| When the worksheet rounds down, New York uses the unrounded share (reworked: FMV $1M added) | 50,000 | 50,000 | 50,000 |
| Mortgage interest outside New York is zero | 0 | 0 | — |
The file's header comment now describes line 7's per-home room (0 = no limit) and line 11 as the larger of the two shares. Hand checks match the hub's table. Case D: I read mortgage_interest_structure.py. non_deductible_mortgage_interest_tax_unit = max(0, home_mortgage_interest_tax_unit + points − deductible_mortgage_interest_tax_unit), and with no home_mortgage_interest both are 0. The person-level non_deductible_mortgage_interest is that times the share. So the supplied 12,000 passes through, and mutant (d) confirms 8,800 without the pass-through.
Tests at 7538a504f8 (one file per process)
ny_mortgage_interest_deduction.yaml: 14 passed.test_ny_mortgage_debt_limit_invariants.py: 4 passed (afteruv sync --extra dev).- Readers:
ny_itemized_deductions_max5,ny_itemized_deductions_phase_out7,ny_pre_tcja_deductions6,ny_itemizes3,ny_deductions1,ny_taxable_income1,ny_income_tax3, NYtax/income/integration.yaml11,hi_mortgage_interest_deduction22,deductible_mortgage_interest16,deductible_mortgage_interest_tax_unit18. All passed. test_source_conflicts.py: 103 passed.make format: no changes.ruff check: clean.- No full suite and no microsimulation.
Mutants (each in its own process, git status clean after each)
| Mutant | YAML (14) | Hypothesis (4) |
|---|---|---|
| (a) worksheet share only | 6 failed: acquisition above the limit (29,320), no-FMV dollar limit (29,320), FMV limits (27,720), non-acquisition (29,995), each home's room (43,980), worksheet rounds down (49,980) | 2 failed: ..._allowed_interest_without_non_acquisition_debt, ..._deductible_share_is_the_larger_method |
| (b) unrounded ratio only | 2 failed: separate returns (18,333.33), grandfathered (45,833.33) | 1 failed: ..._deductible_share_is_the_larger_method |
| (c) FMV 0 treated as $0 | 2 failed: no-FMV dollar limit (26,680), W2 (17,142.86) | 1 failed: ..._qualified_loan_limit_properties |
| (d) no pass-through | 1 failed: D (8,800) | 4 passed. This is equivalent in the helper property, because with no non-acquisition debt and nothing disallowed the federal and NY shares are both 1 |
| (e) acquisition limit 750,000 / 375,000 | 8 failed | 3 failed: ..._statutory_amounts, ..._qualified_loan_limit_properties, ..._allowed_interest_without_non_acquisition_debt |
(f) ny_interest_deduction keeps the federal mortgage part |
1 failed: first case, ny_interest_deduction 66,000 vs 36,000 |
4 passed (helpers untouched) |
CI
The Pull request run at 7538a504f8 (run 41526937728, https://github.com/PolicyEngine/policyengine-us/actions/runs/41526937728) completed with conclusion success: 34 jobs, all success, none cancelled or skipped.
Judgment calls
- Went ahead despite the under-6-hours commit, because it is the named head (see above).
- Share test: draws
debt ≥ 1and clampslimit ≤ debt. Its rounding reference is exact (Fraction). That is safe because integer inputs below 3M sit at least about 1.6e-7 away from a tie after ×1000, far above double-precision error. - W2 comment: it records the old head's 17,140 as history. Mutant (c) gives 17,142.86, because the old head rounded .857 and the mutant, with the larger share, uses the unrounded 6/7.
- I didn't re-run the extra phase-out sub-files (
_reduction,_incremental_reduction, ...) that round 1 ran. The item didn't name them, and CI covers them.
Proposed follow-ups
- Federal: disallow home equity interest after 2017 via a shared non-acquisition balance input. The federal calculation reads only acquisition balances, so home equity interest in
home_mortgage_intereststays deductible. Move the non-acquisition balance to a shared input that federal disallows under 163(h)(3)(F) and NY/HI treat as home equity debt. - Exact grandfathering date for mortgage debt limits. Replace the 1987-year proxy with one exact-date (on or before October 13, 1987) input that the federal, Hawaii and New York calculations all read, so that one loan cannot have two vintages.
Generated by Claude Code
|
Picking this up for the US hub. I'll post a hand-off comment here when it's ready. Generated by Claude Code |
…text An exact tie such as 1,001,000 / 2,000,000 = .5005 comes to 500.49999999999994 after x 1,000 in binary, so the floor rounded it down to .500 and New York used the unrounded .5005 instead of the worksheet's .501. Twelve ratios from .5005 to .5115 did this. Rounding the scaled ratio to nine places before the floor makes the tie round up, as the docstring says. A YAML case and a Hypothesis example now pin the tie. Also from the round 2 review: - A YAML case for non-acquisition debt on the second home, which no test read before. - Property 3 now asserts that the Hawaii helper gives the same default limit, which the input documentation cites. - The input documentation credits the unknown-value rule to PolicyEngine, and says the federal calculation applies its share to home equity interest when the balances exceed the federal limit. - Active voice, a clearer subject and corrected Publication 936 pages in the docstrings and comments. - The Hawaii docstring and the rounding candidate in the source-conflict backlog now account for New York's home value input and its larger-share rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The property 3 docstring's "which is also what the Hawaii helper gives" could attach to the home equity debt limit rather than the whole default limit, so it is now a sentence of its own. The rounding candidate's note said "using it for both" after listing three conventions; it now says Hawaii, whose floor the sentence is about. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Picking this up for the US hub, continuing an earlier session's work on this fix round ( Generated by Claude Code |
1 similar comment
|
Picking this up for the US hub, continuing an earlier session's work on this fix round ( Generated by Claude Code |
|
Ready for hub review Head: Ownership and the earlier session's commits
Findings
The register entry keeps the file's order. Its edits stay inside the entry. On main the same entry, unchanged, now starts at line 11173 after newer entries. The trial merge keeps it between Tests (one file per process, at
|
| Mutant | YAML (16) | Hypothesis (4) |
|---|---|---|
(g) np.round removed from line 82, the brief's mutant |
1 failed: the exact tie, 40,040 vs 40,080 | 1 failed: the share test at @example(limit=1_001.0, debt=2_000.0), assert 0.5005 >= (0.501 - 1e-12) |
(h) the formula ignores ny_second_home_non_acquisition_debt (0 * on line 157) |
1 failed: the second-home case, 30,000 vs 25,000. No test named this input at 7538a504f8 |
not run: it changes only formula_2018, which the file never calls |
| (i) Hawaii's line 6 = min(limit, total debt), ignoring grandfathered debt above the limit | not run | 1 failed: loan-limit properties at the Hawaii assertion (:227); a $1,100,001 grandfathered loan gives 1,100,001 vs 1,100,000 |
CI
The Pull request run at 53f8806db4 is 41588428535: completed, conclusion success, 35 jobs, all success, first attempt. GitHub reports the PR mergeable, with merge state blocked (review required).
Judgment calls
- I kept two edits from the earlier session that go beyond the review's wording:
- Property 3's docstring adds "The Hawaii helper gives the same limit." (test file
:27-28), to match the P3-9 assertion. - The register note says "using it for Hawaii too" where it said "using it for both" (
candidates.yaml:10476-10477). "Both" lost its referent once the note listed three conventions.
- Property 3's docstring adds "The Hawaii helper gives the same limit." (test file
- I made body edits beyond the review's list:
- the CI line now names
53f8806db4, its 35 jobs and run41588428535; - the witness table has rows for the two new YAML cases;
- the tests and mutants sections name the head each ran at, and add (g)-(i);
- the extra-files list names the Hawaii file and the register backlog;
- the invariants note the Hawaii check and the explicit tie example.
- the CI line now names
- I neither merged nor pushed, for the reasons above. The re-filed note asked me to merge
origin/mainagain before pushing, but that assumed the earlier session had merged main. It hadn't, and I pushed nothing. - The 9-place window.
np.round(ratio * 1_000, 9)treats any scaled ratio within 5e-10 of a half as a tie.- With whole-dollar lines 8 and 9 and line 9 under $1 billion, a non-tie lies at least 1/(2 × line 9) > 5e-10 away, so only exact ties move.
- Line 8 carries a fraction only when a home's positive value falls short of the debt treated as acquisition debt on it and home equity stays under the cap. That home's room then clamps at 0, so its pro-rata share of the limit stays in line 8. Such a case could round up when line 8 sits within about $0.000002 of a tie, at $4 million of debt.
- A random search of that configuration found no such case. It compared helpers lifted from the file with exact fractions, over every valid first-home value for each draw of balances.
- I left the line as the review wrote it.
- I didn't re-run the readers locally. This round's commits change the share only at exact ties; the rest is documentation and tests. CI at the head passed.
For the follow-up list (not fixed here)
- Hawaii's tie arithmetic (
hi_mortgage_interest_deduction.py:48,np.floor(ratio * 1_000 + 0.5) / 1_000). I ran a witness through the model in a scratch YAML, not committed:- Inputs: 2025, Hawaii, single; $100,000 interest; $1,902,000 from 1986 and $2,098,000 from 2020.
- Line 8 = 1,902,000 + 100,000 = 2,002,000 and line 9 = 4,000,000, so .5005 is an exact tie.
- PE gives 50,000 (share .500); the worksheet's .501 gives 50,100. Federal is 47,550, so the floor doesn't bind.
- As the review said, a failing tie there needs grandfathered debt above the limit.
- New York college tuition credit.
- How the model decides:
ny_college_tuition_credit_eligiblereturns~ny_itemizes.ny_itemizesistax_unit_itemizes & (ny_itemized_deductions >= ny_standard_deduction).ny_itemized_deductions_maxaddsny_college_tuition_deduction.
- This PR raises
ny_interest_deductionfor some filers. A federal itemizer whose New York itemized total now reaches the standard deduction starts itemizing for New York and loses the credit. - New York tax rises when the credit exceeds the tax value of the larger deductions. So "any increase in NY tax would be a defect" needs that exception in the impact check.
- How the model decides:
- Mixed inputs. I ran this through the model in a scratch YAML:
- Inputs: 2025, New York, single;
deductible_mortgage_interest12,000 supplied;home_mortgage_interest5,000; a $1.5M loan from 2020. - The federal tax-unit amounts come to 2,500 deductible and 2,500 non-deductible, so the worksheet path applies: (12,000 + 2,500) × 11/15 = 10,633.33, under the supplied 12,000.
- The inputs contradict each other, so I report no defect. The impact run should confirm that no dataset stores both.
- Inputs: 2025, New York, single;
Proposed follow-up issues
- Round exact ties up in Hawaii's mortgage interest share.
_hi_deductible_sharefloorsratio * 1000 + 0.5, so in binary an exact tie such as 2,002,000 / 4,000,000 = .5005 rounds to .500. Apply New York's 9-place rounding, and add the witness above as a YAML case. - Decide New York itemizing by tax, counting the college tuition credit.
ny_itemizescompares deductions, though its documentation says the lower tax decides, andny_college_tuition_credit_eligibleis~ny_itemizes. Check Tax Law 606(t) and 615 on the choice, and test a filer with tuition expenses near the standard deduction. - The previous round's two follow-ups still stand: a shared non-acquisition balance input that the federal calculation disallows, and an exact grandfathering date.
Generated by Claude Code
|
Hub review in progress Head under review: Firm so far:
Still to do: main-merged test runs, reproducing the defect at main, the college tuition household, mixed inputs, the Hawaii witness, readers, and the body. Generated by Claude Code |
|
Ready for hub review The head hasn't moved since the round 2 brief. I reviewed the whole diff from Can it land? Yes, as far as I can check. Every delta finding is fixed as asked. The tie now rounds up, the defect reproduces at current main, the changed tests pass at the head and on a tree with main merged in, and CI at the head is 35/35. The four findings below are all P3. None changes a result for a household with consistent inputs, except the 9-place rounding case, which needs a line 8 within a millionth of a dollar of a tie. I couldn't reach any legal source from this session (see the end). FindingsP3-1. A wiring slip on the second home's non-acquisition debt survives every test
The only second-home case (YAML non_acquisition_debts = [
tax_unit("ny_first_home_non_acquisition_debt", period).astype(np.float64)
+ tax_unit("ny_second_home_non_acquisition_debt", period).astype(np.float64),
0 * tax_unit("ny_second_home_non_acquisition_debt", period).astype(np.float64),
]Result: YAML 16 passed, Hypothesis 4 passed. The property tests only call the helpers, so they never see the formula's wiring. The code is right today. Case to add (hand value: the second home has no acquisition debt, so its room is its $50,000 value; line 7 = 50,000; line 8 = 450,000; line 9 = 600,000; share .75; $30,000 × .75): - name: The second home's value limits its own non-acquisition debt
period: 2025
absolute_error_margin: 0.01
input:
state_code: NY
filing_status: JOINT
home_mortgage_interest: 30_000
first_home_mortgage_balance: 400_000
first_home_mortgage_origination_year: 2015
ny_first_home_fair_market_value: 2_000_000
ny_second_home_fair_market_value: 50_000
ny_second_home_non_acquisition_debt: 200_000
output:
# Room on the second home: $50,000 - $0 = $50,000, so line 7 = $50,000.
# ($400,000 + $50,000) / $600,000 = .75; $30,000 x .75.
ny_mortgage_interest_deduction: 22_500I ran it at the head: 1 passed. With the second home's value at $1 instead, the head gives 20,010 and mutant (k) gives 25,000. That shows the case kills the mutant: under (k) the debt lands on the first home, whose room is $1.6M, so line 7 = $100,000. P3-2. The 9-place rounding can move a non-tie, and judgment call 4's bound is loose
Whole-dollar lines. For whole-dollar lines 8 and 9, a non-tie sits at least 1/(2 × line 9) from a tie in the scaled ratio. The hand-off says that keeps it outside the 5e-10 window "under $1 billion". Float error in
Fractional line 8. Line 8 carries a fraction when one home's room binds at its value less its prorated share of the limit. In that case the rounding does move a non-tie at ordinary sizes. Witness, 2025, single:
This is defensible: a worksheet filled in whole dollars has line 8 = 1,001,901, which is an exact tie (.4955), and that rounds to .496 = 49,600. But two texts overstate the guarantee:
No code change needed. If the hub wants the whole-dollar reading explicit, round line 8 and line 9 to whole dollars before the share; that makes this case an exact tie. Otherwise replace the end of body line 90 with: "…at most 1, and exceeds the ratio by no more than .0005 apart from float error. The 9-place rounding treats a scaled ratio within 5e-10 of a half as a tie: with whole-dollar lines 8 and 9 below about $999.8 million only exact ties move, and a fractional line 8 that close to a tie rounds as a whole-dollar worksheet would." P3-3. With mixed inputs this PR lowers New York's deduction, and judgment call 2's bound is false thereBody line 40, "so with no non-acquisition debt the result never falls below PE's unrounded federal amount", and Witness, 2025, New York, single:
The worksheet path takes (12,000 + 2,500) × 11/15. The federal interest deduction, which reads the supplied 12,000, stays above that. The inputs contradict each other, so I don't count this as a wrong result. But the PR makes it reachable and lower than main, and the body's bound doesn't hold for it. Replace the end of judgment call 2 with: "…so with no non-acquisition debt, and with the federal amount computed from The hub's population check should confirm that no dataset stores both inputs. P3-4. The phase-out docstring line conflicts with open PR #9977
Hand-off follow-ups: main or this PR?
Tuition witness. 2025, New York, single, age 30:
Checked and sound
What I couldn't check
Generated by Claude Code |
CI: the Pull request run at
53f8806db4passed, all 35 jobs succeeded (run41588428535). The hub lands this after an independent review.Source
The hub checked each quote above against its source on 2026-11-02.
What changed
On main,
ny_itemized_deductions_maxadds the federalinterest_deduction. For loans from 2018 or later its mortgage part uses the federal $750,000 limit ($375,000 separate) and allows no home equity debt. New York's preserved rules allow more.ny_mortgage_interest_deduction(new). From 2018 it applies the pre-TCJA Table 1:deductible_mortgage_interest.ny_interest_deduction(new) = federalinterest_deduction− federaldeductible_mortgage_interest+ny_mortgage_interest_deduction. Starting frominterest_deductionkeeps an interest total supplied directly asdeductible_interest_expense, whichny_itemized_deductions_max.yamluses.ny_itemized_deductions_maxaddsny_interest_deductioninstead ofinterest_deduction. Its existingsubtractsofdisallowed_interest_components(mortgage insurance premiums) is unchanged.gov.states.ny.tax.income.deductions.itemized.interest.home_acquisition_debt_limit(1,000,000 / SEPARATE 500,000) andhome_equity_debt_limit(100,000 / SEPARATE 50,000), from 2018-01-01.ny_mortgage_interest_inputs.py:ny_first_home_fair_market_value,ny_second_home_fair_market_value,ny_first_home_non_acquisition_debt,ny_second_home_non_acquisition_debt.New inputs and their defaults
All four inputs default to 0.
So when a caller supplies neither input, the changes from main are the larger acquisition-debt limit, home equity treatment of acquisition debt above it (up to $100,000), and the larger of the two shares. The property test checks the default limit (property 3).
PE choices (judgment calls)
deductible_mortgage_interestsupplied directly (taxsim and many integration tests do this). There is no federal floor now. The pass-through stays because without it New York would limit such a deduction a second time when balances are present: the case "A directly supplied deduction passes through even with balances" gives 12,000, where the worksheet path would give 12,000 × .7333 = 8,800.Federal follow-up
PE's federal calculation reads only the two acquisition balances, so after 2017 it treats home equity interest included in
home_mortgage_interestlike interest on those balances: fully deductible when they fit the federal limit, and deductible at the same share when they don't. The input documentation now says so, and a follow-up will move that balance to a shared input that the federal calculation disallows.Extra files beyond the spec's list
ny_itemized_deductions_phase_out.py: a docstring now namesny_interest_deduction, the variable the worksheet's line 1 now includes.policyengine_us/tests/core/test_ny_mortgage_debt_limit_invariants.py: the Hypothesis property test.changelog.d/ny-pre-tcja-mortgage-interest.fixed.md.hi_mortgage_interest_deduction.py: its docstring now says PolicyEngine has no Hawaii home value input, since this PR adds New York ones.source_conflicts/candidates.yaml: theus:mortgage-interest-limit-ratio-roundingcandidate now lists the New York file and this PR, and says PE-US follows three conventions, New York's being the larger of the three-place share and the exact ratio.Witness and years
Bug confirmed on
origin/main(0ea8894) with a failing YAML case: 2025, single, $36,000 interest, $900,000 loan from 2020.ny_itemized_deductions_maxwas 30,000; expected 36,000.deductible_mortgage_interest12,000 supplied, $1.5M loan from 2020Years: 2018 onward.
Invariants
policyengine_us/tests/core/test_ny_mortgage_debt_limit_invariants.pychecks all of these with Hypothesis (400 derandomized examples, every filing status, 2018/2025/2026 parameters), plus an explicit exact tie (1,001 / 2,000) for the share. It also checks the helper against a separately written statute-order restatement, which places the limit home by home. The restatement shares the limit between homes the same way (judgment call 3), so it can't catch a wrong sharing rule.Tests (local, one file per process)
53f8806db4:ny_mortgage_interest_deduction.yaml16/16; Hypothesistest_ny_mortgage_debt_limit_invariants.py4/4;policyengine_us/tests/code_health/test_source_conflicts.py103 passed.7538a504f8:ny_itemized_deductions_max5,ny_itemized_deductions_phase_out7,ny_pre_tcja_deductions6,ny_itemizes3,ny_deductions1,ny_taxable_income1,ny_income_tax3, NYintegration11, HIhi_mortgage_interest_deduction22, federaldeductible_mortgage_interest16 anddeductible_mortgage_interest_tax_unit18. All pass.53f8806db4passed.Mutants (each in its own process, code restored after)
(a)-(f) ran at
7538a504f8, with 14 YAML cases.ny_interest_deductionkeeps the federal mortgage part toony_interest_deduction)(g)-(i) ran at
53f8806db4, with 16 YAML cases:np.round: YAML 1 failed (the exact tie, 40,040 instead of 40,080); Hypothesis 1 failed (the share test, at its@example(limit=1_001.0, debt=2_000.0)).ny_second_home_non_acquisition_debt: YAML 1 failed (the second-home case, 30,000 instead of 25,000). Before that case no test read the input.Readers
ny_mortgage_interest_deduction→ny_interest_deduction→ny_itemized_deductions_max, which is read byny_itemized_deductions,ny_itemized_deductions_phase_out, andny_itemized_deductions_{higher,lower}_incremental_reduction.impact: pending (hub)
axiom: (hub files pe-parity before landing)
🤖 Generated with Claude Code