Skip to content

Implement Maine PTFC unknown-utilities 15% rule (Schedule PTFC line 5c) - #9267

Open
DTrim99 wants to merge 4 commits into
PolicyEngine:mainfrom
DTrim99:fix/me-ptfc-utilities-in-rent-v2
Open

Implement Maine PTFC unknown-utilities 15% rule (Schedule PTFC line 5c)#9267
DTrim99 wants to merge 4 commits into
PolicyEngine:mainfrom
DTrim99:fix/me-ptfc-utilities-in-rent-v2

Conversation

@DTrim99

@DTrim99 DTrim99 commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Surfaced by PolicyEngine/policyengine-taxsim#1126 (ME renter with rent that includes utilities).

Problem

Maine's property tax fairness credit treats 15% of rent as "rent constituting property taxes," after first excluding any heat/utilities included in the rent. Per 2022 Schedule PTFC/STFC line 5c: if the rent includes utilities and the amount is known, subtract it; if the rent includes utilities and the amount is not known, subtract 15% of gross rent instead.

me_property_tax_fairness_credit_countable_rent only handled the known-amount case (utilities_included_in_rent * utility_expense) and its comment noted the unknown-amount branch was "not implemented." So a filer whose rent includes utilities but who did not itemize a utility amount received no utility exclusion at all, overstating the countable rent (and the credit).

Fix

  • Implement the line-5c fallback: when utilities_included_in_rent is true and the utility amount is unknown (utility_expense is 0), deduct 15% of gross rent before applying the 15% rent-constituting-property-tax rate.
  • Add parameter gov.states.me.tax.income.credits.fairness.property_tax.rate.utilities_included_in_rent (0.15) for the utility fraction.
  • Add a countable-rent test for the unknown-amount case.

Example

Rent $17,139 with utilities included, amount unknown: utility portion = 15% × 17,139 = 2,571; countable rent = 15% × (17,139 − 2,571) = 2,185, matching the Maine worksheet (previously PE used the full 15% × 17,139 = 2,571). The known-amount and utilities-not-included cases are unchanged.

@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (57743a2) to head (e5a551c).
⚠️ Report is 22 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #9267   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            3         2    -1     
  Lines           65        26   -39     
=========================================
- Hits            65        26   -39     
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

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

☔ View full report in Codecov by Harness.
📢 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.

@PavelMakarchuk PavelMakarchuk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation mechanics check out — all 34 tests in the ME PTFC suite pass on the branch, the new parameter loads with correct metadata, utilities_included_in_rent defaults to false so microsim defaults are unaffected, no partner contract tests are touched, and the worksheet math in the new test (127.5 = (1000 − 150) × 0.15) is internally consistent with the quoted form text.

Requesting changes for two findings on the rewritten formula, detailed inline:

  1. utility_expense is the wrong "amount known" discriminator — it's the household's general SNAP-style utility expense total, not the utility portion of rent, so the new 15% fallback only fires when the household reports zero utility expenses of any kind, and separately-paid utilities get subtracted from rent.
  2. No clamp when utilities exceed rent — countable rent can go negative and offsets real_estate_taxes downstream; line 5d on the form can never be negative.

Caveat: maine.gov was unreachable from the review environment, so the line-5c rule was verified against the PR's quoted form text and worksheet example rather than the form PDF itself.


Generated by Claude Code

@DTrim99

DTrim99 commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator Author

Fixes applied from @PavelMakarchuk's review

Both findings addressed and pushed (ME PTFC suite 36/36). Thanks for the catch — both were masked by the old tests.

F1 — wrong known/unknown discriminator (fixed)

You're right that utility_expense (the SPM-unit's general SNAP-style utility total) is the wrong signal for "is the utility portion of rent known?" — it made the line-5c 15% fallback unreachable for any household reporting utility expenses and subtracted separately-paid utilities from rent. Added a dedicated me_ptfc_utilities_included_in_rent (TaxUnit, USD, default 0) and rewired the split off the utilities_included_in_rent boolean + that amount:

  • not included in rent → no subtraction (full rent counts);
  • included & amount known (> 0) → subtract that amount;
  • included & amount unknown (0) → subtract the 15%-of-rent estimate (line 5c).

Your concrete case now resolves to the form's (12,000 − 1,800) × 0.15 = 1,530 instead of 1,710, and the separately-paid utility_expense is no longer subtracted.

F2 — clamp when utilities exceed rent (fixed)

net_rent is now max_(rent − utility_portion, 0), so countable rent can never go negative and offset real_estate_taxes downstream (line 5d ≥ 0). Your rent = 2,400 / utilities = 3,600 → −180 case now returns 0.

Tests

Appended two demonstrating cases that fail if either fix is reverted:

  • separately-paid-utilities (rent 12,000, included-amount unknown, general utility_expense 600) → 1,530 (would be 1,710 under the old discriminator);
  • utilities-exceed-rent (rent 2,400, included-amount 3,600) → 0 (would be −180 unclamped).

The existing known-amount case (1000 − 150) × 0.15 = 127.5 still passes. No parameter values changed (the 15% rates were already added by this PR).

🤖 Generated with Claude Code

@DTrim99
DTrim99 requested a review from PavelMakarchuk August 17, 2026 13:20
@PavelMakarchuk

Copy link
Copy Markdown
Collaborator

PR Review (follow-up)

Re-reviewed head bea2956 against the 2022 and 2023 Schedule PTFC/STFC instructions (line 5a–5e) and 36 M.R.S. §5219-KK.

🔴 Critical (Must Fix)

None.

🟡 Should Address

  1. Changelog type. changelog.d/me-ptfc-utilities-in-rent.fixed.md — the PR adds a new parameter (rate/utilities_included_in_rent.yaml) and a new input variable (me_ptfc_utilities_included_in_rent), which by repo convention is added (minor bump), not fixed. Rename to .added.md.

🟢 Suggestions

  1. Naming / documentationme_ptfc_utilities_included_in_rent.py: the sibling family is me_property_tax_fairness_credit_*; consider the long form for consistency. Either way, add documentation stating that 0 means "amount unknown" (triggers the 15% estimate), since a known $0 is indistinguishable from unknown at ..._countable_rent.py:26.
  2. Referencesutilities_included_in_rent.yaml:9-12: also cite the 2023 line-5c instruction text (p.2) and a pre-2022 form to support the 2014-01-01 start (only 2022/2023 forms are cited; rate/rent.yaml already cites 2021).
  3. Tests — add an integration case in me_property_tax_fairness_credit.yaml (rent with unknown utilities → credit) and a boundary where the known utility amount equals rent (→ 0 countable rent).

Validation Summary

Check Result
Regulatory Accuracy 0 issues — line 5c: if utilities included and amount known, subtract it; if unknown, subtract 15% of gross rent (5a); 5d = 5a − 5c; 5e = 5d × 15%. Code matches exactly, incl. the "included AND unknown" condition
Reference Quality 0 issues (1 suggestion) — 2022 p.2 / 2023 p.1 corroborate 15%
Code Patterns 0 issues — vectorized where/max_, TaxUnit level matches caller, non-ME users of utilities_included_in_rent (MI home heating) unaffected, input defaults 0 so microsim unchanged
Test Coverage 0 blocking gaps (1 suggestion) — not-included / known / unknown / unknown+separate utilities / known > rent clamp all covered
CI Status Passing, codecov 100%
Prior review Both items (F1 discriminator, F2 clamp) addressed in bea2956

Verdict: APPROVE once the changelog type is added.

@DTrim99

DTrim99 commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up review addressed — thanks @PavelMakarchuk

All items from your 2026-08-18 follow-up applied (ME PTFC suite 38/38).

Should

  • Changelog type → renamed me-ptfc-utilities-in-rent.fixed.md to .added.md (the PR adds a new parameter and input variable, so added is right).

Suggestions

  • Documentationme_ptfc_utilities_included_in_rent now documents that 0 means the amount is unknown (which triggers the 15%-of-gross-rent line-5c estimate), so a known $0 is distinguishable in intent from unknown. Kept the me_ptfc_ name (you'd flagged the long-form as optional).
  • References → added the 2014 Schedule PTFC line-5c form (14_1040_sched_ptfc, p.2 — "multiply line 5a by 15%") to support the 2014-01-01 start, alongside the existing 2022/2023 forms. No value or start-date change.
  • Tests → added an integration case (ME household, rent $6,000 with utilities included but amount unknown → line-5c estimate $900 → countable rent 0.15 × (6000 − 900) = 765 → credit 765, vs 900 without the estimate) and a boundary case where the known utility amount equals rent → net rent clamps to 0 → countable rent 0.

CI/codecov should stay green. Let me know if you'd prefer the long-form variable rename after all.

Fixed with Claude Code assistance.

@PavelMakarchuk PavelMakarchuk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review (complete:review-pr — re-review after 8/18 commits)

Both findings from my 8/16 review are genuinely fixed, verified against the form text extracted mechanically (2022 Schedule PTFC/STFC p. 2; 2014 instructions p. 4; 36 M.R.S. §5219-KK(1)(E)):

  1. Discriminator ✓ — the new dedicated me_ptfc_utilities_included_in_rent input replaces utility_expense (the SPM-unit separately-paid utilities aggregate, which the form's line 5c does not mean). Countable-rent Case 4 is a regression guard that inverts if the old discriminator returns.
  2. Negative clamp ✓ — max_(rent - utility_portion, 0), with boundary tests at equal-to-rent and exceeding-rent.

The line 5c implementation reproduces all three form branches exactly — "If line 5b is yes and you know the amount… enter that amount… If yes, and you do not know the amount paid, multiply line 5a by 15% (.15)… If line 5b is no, enter '0'" — and the 0.15 is parameterized separately from the line-5e rent rate with correct page anchors for 2014/2022/2023 (the 2014-01-01 start date checks out against the 2014 form). All six countable-rent cases plus the end-to-end credit case (765) recompute correctly by hand; the full ME credits suite (125 tests) passes on the branch. Microsim-safe: utilities_included_in_rent is imputed nowhere, so defaults are unaffected. CI green.

🟡 Should address (non-blocking, but №1 is worth settling before merge since it's a public API name)

  1. Variable name breaks the folder convention — every sibling spells out me_property_tax_fairness_credit_*; me_ptfc_ has no precedent in the repo, and renaming a user-facing input after release is a breaking API change. Suggest me_property_tax_fairness_credit_utilities_included_in_rent_amount (the _amount suffix also disambiguates from the boolean utilities_included_in_rent).
  2. Parameter description — leads with a subordinate clause and uses "gross rent" in the opposite sense from the statute's term of art (§5219-KK(1)(E) defines "gross rent" as rent exclusive of utility charges, i.e. line 5d, not 5a). Suggest e.g. "Maine excludes this share of the rent paid as utilities included in rent when the amount is not known under the property tax fairness credit."

🟢 Suggestions

  • Add the mirror-image test: utilities_included_in_rent: false with a nonzero amount → no exclusion (guards the included * gate, form's "If line 5b is no" branch).
  • Label/description say "heat or utilities"; the form covers "heat, utilities, furniture, or similar items" — broaden the wording.
  • Test-name labels "(F1…)"/"(F2…)" are session-internal identifiers; the comment bodies are excellent, just reword the labels.
  • The clamp comment ("Line 5d (5a − 5c) can never be negative") slightly overstates the form — it's a defensive guard against user input where 5c exceeds 5a.
  • Drive-by while the folder is open: sibling rate/rent.yaml has label: …income rate — copy-paste error for the rent rate.

Validation summary

Check Result
Regulatory accuracy 0 issues (all three 5c branches match the form verbatim)
Reference quality Anchors verified for all three form years; 2014 start corroborated
Code patterns Clean (vectorized, parameterized, correct entities); naming nit above
Test coverage 6 unit + 1 end-to-end recompute correctly; 125-test suite passes
CI Passing (full suite)

@PavelMakarchuk

Copy link
Copy Markdown
Collaborator

PR 9267 — ME Property Tax Fairness Credit: Schedule PTFC/STFC line 5c utilities-in-rent rule

Program Review

Program: Maine Property Tax Fairness Credit (36 M.R.S. §5219-KK) — implements Schedule PTFC/STFC line 5c: when rent includes heat/utilities/furniture and the amount is known, subtract it; when unknown, subtract a 15% estimate of rent; when not included, subtract nothing. New 0.15 parameter, new dollar-amount input variable, rewritten countable-rent formula (drops an erroneous SPMUnit-level utility_expense subtraction), tests, changelog.

Source Documents

# Document Link Pages
1 2022 Form 1040ME Schedule PTFC/STFC (line 5c on file p. 2) https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/22_1040me_sched_pstfc_ff.pdf 4 (all rendered; p. 2 re-rendered at 600 DPI)
2 2014 Form 1040ME Schedule PTFC (line 5c on file p. 2) https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/14_1040_sched%20ptfc_download.pdf 4 (all rendered)
3 2023 Form 1040ME Schedule PTFC/STFC (line 5c moved to file p. 1) https://www.maine.gov/revenue/sites/maine.gov.revenue/files/inline-files/23_1040me_sched_pstfc_ff.pdf 4 (all rendered; p. 1 re-rendered at 600 DPI)
4 36 M.R.S. §5219-KK (statute, HTML → text) https://legislature.maine.gov/statutes/36/title36sec5219-KK.html n/a (text-extracted)

Verification-phase supplements: 2013 Schedule PTFC (NBER mirror, ext-1) and 2016/2019/2021/2024/2025 Schedule PTFC/STFC forms (ext-2 continuity sample) — text-extracted, not rendered.

  • Year: 2014– (parameter effective date); tests use period 2022
  • Scope: PR changes only
  • Reviewed head SHA: b008eae
  • Mode: full

Critical

None. The three line-5c branches, the 0.15 value, the 5c → 5d → 5e ordering, the 2014-01-01 effective date, and all three reference page anchors match the extracted sources; every formula branch has at least one passing test; CI is passing.


Should

A1 — Wording understates the form's scope and misuses "gross rent" (VERIFIED mismatch, documentation-only; value 0.15 correct)

  • policyengine_us/parameters/gov/states/me/tax/income/credits/fairness/property_tax/rate/utilities_included_in_rent.yaml:1,7 (description, label)
  • policyengine_us/variables/gov/states/me/tax/income/credits/fairness/property_tax_fairness_credit/me_ptfc_utilities_included_in_rent.py:8,11 (label, documentation)
  • .../me_property_tax_fairness_credit_countable_rent.py:21-22 (comment)
  • changelog.d/me-ptfc-utilities-in-rent.added.md:1

Confirmed by verifier at 600 DPI against the 2022 form (p. 2) and 2023 form (p. 1), plus the 2014 text layer (p. 2): all three forms say "heat, utilities, furniture, or similar items" (statute §5219-KK(1)(E) is broader still: "utilities, services, furniture, furnishings or personal property appliances"). The repo strings say "heat or utilities" / "utilities" throughout. Classified as documentation, not a value mismatch — the formula reads only the parameter's numeric value, which is correct.

Second wording defect at the same loci: the description, variable documentation, and changelog all apply 15% to "gross rent", but §5219-KK(1)(E) defines gross rent as the figure exclusive of utility charges — i.e. the post-line-5c amount, the base of the sibling rate/rent.yaml. Because both parameters are 0.15, the current wording makes two legally distinct rates on different bases read as the same rule. Fix together: broaden every string to the form's own terms and replace "gross rent" with "rent paid (Schedule PTFC/STFC line 5a)"; also reshape the parameter description to the convention ([State] [verb] …; sibling rate/rent.yaml:1 shows the target shape) and note in the countable-rent formula that the generic boolean utilities_included_in_rent serves as a narrower-named proxy for line 5b.

A2 — Naming: me_ptfc_ abbreviation breaks the folder convention and the name reads as the adjacent boolean

  • .../me_ptfc_utilities_included_in_rent.py:4 (class name)
  • .../me_property_tax_fairness_credit_countable_rent.py:16,20 (both names two lines apart)
  • .../rate/utilities_included_in_rent.yaml (filename)

All eight sibling variables spell out me_property_tax_fairness_credit_*; me_ptfc_ appears nowhere else in the repo. The new USD-amount variable is character-for-character the existing bool utilities_included_in_rent (variables/household/expense/housing/utilities_included_in_rent.py:4) with a state prefix, and the two are read on adjacent lines. The parameter path compounds it: rent * p.rate.utilities_included_in_rent reads as multiplying by a flag — three same-named things of three types in one formula. Recommend me_property_tax_fairness_credit_utilities_in_rent_amount (or ..._line_5c_amount) and a rate filename that names what it scales (e.g. rate/utilities_share_of_rent.yaml). Flagged independently by regulatory, code, and reference validators.

A3 — Two mutation-guard tests missing for the exact bug being fixed (downgraded from the edge-case checker's "critical")

policyengine_us/tests/policy/baseline/gov/states/me/tax/income/credits/property_tax_fairness_credit/me_property_tax_fairness_credit_countable_rent.yaml

Severity call: no branch of the new formula has zero coverage — Case 1 exercises included=false (branch 3), Case 2 the known branch, Cases 3–4 the unknown branch, Cases 5–6 the clamp — so per canonical rules these are mutation-coverage gaps on a tested variable, SHOULD not CRITICAL. They are the two highest-value additions:

  1. Gate mirror: no case has utilities_included_in_rent: false with a nonzero me_ptfc_utilities_included_in_rent; dropping the included * multiplier entirely passes all six existing cases. The form is explicit: "If line 5b is no, enter '0' on line 5c." Add rent 1_000 / false / amount 400 → 150 (ungated would give 90).
  2. Known-branch utility_expense guard: Case 4 pins the removed utility_expense subtraction only in the unknown branch; reintroducing it inside the known branch passes every current case. Add rent 12_000 / true / amount 1_200 / heating_cooling_expense: 600 → 1_620 (regression would give 1_530).

A4 — Additional coverage gaps on the new formula

Same test files. Six gaps, none merge-blocking individually: (a) multi-person rent aggregation — every case is a one-person unit, so a head-only rent read is invisible (add JOINT, 6_000+4_000 → 1_275); (b) renter and owner combined — me_property_tax_fairness_credit_countable_rent_property_tax is never computed with both addends nonzero anywhere in the repo (add rent 4_000 + real_estate_taxes 200 → credit 710); (c) zero rent with utilities included, both sub-branches (known-amount case is the only zero-minuend clamp firing: max(0−500,0)=0); (d) the > 0 discriminator boundary — a $1 known amount jumps countable rent 127.5 → 149.85, a real cliff created by the zero sentinel, worth pinning against a future >= 0/!= 0 edit; (e) negative recorded amount (falls into the estimate branch today; != 0 would inflate the credit); (f) the default-input path (rent only, nothing set → plain 15% of rent), which is what the entire microdata population takes; (g) an end-to-end known-amount credit case (credit Case 4 covers only the unknown branch, amount 1_000 on rent 6_000 → 750). Ready-to-paste YAML for all of these is in pr9267-review-tests.md.

A5 — Test hygiene: missing error margins (real flakiness risk) and review-round jargon baked into permanent files

  • me_property_tax_fairness_credit_countable_rent.yaml (all 6 cases), me_property_tax_fairness_credit.yaml Case 4 — no absolute_error_margin. The values run 0.15 twice through float32 (Case 4: 12_000 → 1_530) and 0.15 is not exactly representable; the convention requires absolute_error_margin: 0.01 on currency outputs (the sibling ..._base_cap.yaml already sets one).
  • me_property_tax_fairness_credit_countable_rent.yaml:34,46-48,50 — "F1 discriminator", "F2 non-negative clamp", "old buggy discriminator", "this case inverts if F1 is reverted" are this review thread's internal finding IDs; meaningless to the next reader. Rename in domain terms (e.g. "Case 4, utilities included with amount unknown; separately-paid utility expenses are ignored."). Minor: Case 4's name says utility_expenses but the input is heating_cooling_expense; Case 1's name is ungrammatical ("utilities did not include in rent"); names lack the convention's trailing period and several exceed 90 chars.

A6 — Line 5d clamp comment asserts a form rule that is not printed, and Cases 5/6 encode the clamp's own output as the expectation

.../me_property_tax_fairness_credit_countable_rent.py:32-33 — the comment "Line 5d (5a - 5c) can never be negative" presents form text that does not exist: all three form years say only "Line 5a minus line 5c" (verified across the full line-5 block and instructions in the 2014/2022/2023 extracts). The clamp is a sound modelling guard — in the unknown branch 5d = 0.85 × 5a ≥ 0, and in the known branch 5c is by construction a component of 5a — so reword to state that rationale ("clamp guards inconsistent user input") instead of asserting a form rule. Correspondingly, me_property_tax_fairness_credit_countable_rent.yaml:50-70 (Cases 5–6, amount > rent and amount = rent → 0) derive their expectations from the clamp under review, not from any external ground truth (CLAUDE.md evidence rule 4 circularity). Keep the cases but annotate them as invalid-input guards, not Maine-published results.


Suggestions

S1 — Zero-as-"unknown" sentinel: document the convention and the default-path behavior

.../me_ptfc_utilities_included_in_rent.py:11, .../me_property_tax_fairness_credit_countable_rent.py:26. included_amount > 0 makes a genuinely known $0 indistinguishable from "unknown" (arguably impossible per the instruction, so benign); a separate ..._amount_known boolean would make the three branches explicit. Also note in the PR description that any record with the flag true and no amount now takes the 15% estimate instead of the old utility_expense subtraction — a default-driven change whose population-level reach is nil today (see xref result below) but which activates for household/API users.

S2 — Add the statute for the utilities-exclusion authority, and a comment recording why §5219-KK is not cited for the 15%

.../rate/utilities_included_in_rent.yaml:8-14. The form-only citation set is correct (verified: §5219-KK contains no unknown-amount estimate; its only 15% is the line-5e rate) — do not "fix" it by citing the statute for this value. But a one-line YAML comment recording that the omission is intentional would stop a future reviewer from adding the wrong-15% citation, and the statute URL could be added for the underlying exclusion concept, matching the sibling rate/rent.yaml.

S3 — documentation field on the new variable

.../me_ptfc_utilities_included_in_rent.py:11. The model-development reference says use reference, never documentation; ~20% of existing variables carry it, so this is convention drift, not a defect. Consider moving the sentinel explanation into the formula comment where it is acted on.

S4 — Period variation and the two-indistinguishable-0.15s note

All seven new/edited cases are period: 2022. One repeat of the unknown branch in 2014 and/or 2024 would pin the parameter's 2014-01-01 start and continuity. Separately, p.rate.utilities_included_in_rent and p.rate.rent are both 0.15, so no baseline YAML case can distinguish them — add a one-line comment at the top of the countable-rent test file so a future reader does not assume the tests pin them separately. Avoid any known-amount case where amount = 0.15 × rent (both branches coincide; proves nothing).

S5 — Minor polish

Comment volume in the formula (nine comment lines for eight code lines; lines 21–25 restate the where below them); amount_known could be inlined; changelog fragment type .added under a fix/ branch (defensible — the fragment covers a new user-facing input — flagged only because they disagree); me_ptfc_utilities_included_in_rent: 0 in Case 1 restates the default; trailing blank line at end of me_property_tax_fairness_credit.yaml.

S6 — Consider a generic household-level amount input

.../me_ptfc_utilities_included_in_rent.py:4. The dollar amount of utilities bundled into rent is not Maine-specific; the sibling boolean lives at variables/household/expense/housing/ and is already consumed by Michigan's home heating credit. A shared input would avoid a second state-only user-facing field later. Design preference, not a defect.

S7 — Pre-existing nits noticed in passing (outside PR scope)

.../rate/rent.yaml: (a) label reads "Maine property tax fairness credit income rate" though it holds the line-5e rent rate; (b) its "2024 Form 1040ME… Line 5(e)" reference href points at the 2023 file. Neither is touched by this PR; fix opportunistically.


Confirmed correct (highlights)

  • Three line-5c branches match the form exactly (known amount / 15% estimate / zero), in all three cited years, verified on rendered page images and at 600 DPI for 2022/2023.
  • 0.15 value verified 8 form-years deep: PR-cited 2014/2022/2023 plus continuity sample 2016/2019/2021/2024/2025 (ext-2: CONTINUITY CONFIRMED, identical operative wording throughout) — the single 2014-01-01: 0.15 entry stands on unusually strong evidence.
  • 2014-01-01 start date is correct (ext-1 investigated and cleared): ext-1 showed a TY2013 Schedule PTFC with the same 15% estimate existed — but under the predecessor credit, 36 M.R.S. §5219-II, a materially different program (25%-of-rent base, 40% credit, $300/$400 caps) that PE does not model; the modeled §5219-KK credit applies "for tax years beginning on or after January 1, 2014" and every sibling parameter uses the same 2014-01-01 start. A pre-2014 model of the §5219-II credit would be a separate feature, not a fix to this parameter.
  • Form-only citation for the 15% estimate is the right call: §5219-KK supplies the line-5e rate and the utilities exclusion but no estimation rule; citing it here would corroborate the wrong 15%. All four page anchors verified against actual file pages (2023's layout move to p. 1 correctly reflected).
  • Dropping utility_expense is a genuine fix: the old code subtracted the household's separately paid SPMUnit-level utility bills from rent — no basis on the form, plus a cross-entity aggregation bug — and its own comment conceded the unknown-amount case was unimplemented.
  • Microsimulation reach checked and cleared (xref-1: REJECTED): neither utilities_included_in_rent nor the new input is imputed anywhere in policyengine-us-data (CPS/ECPS/ACS/PUF); defaults hold for 100% of records, so this PR cannot move population-level ME PTFC results.
  • All seven test expectations independently re-derived against the 2022 form's 5c→5d→5e sequence and the benefit-base/cap parameters (integration case: 900 → 5_100 → 765, cap $1,000 non-binding). Code patterns clean: fully vectorized, fully parameterized (separate parameter correctly created rather than reusing the coincidentally equal rate/rent), correct entity/period usage, ruff clean, changelog fragment present.

PDF Audit Summary

Category Count
Confirmed correct (repo value = PDF) 13 (+5 continuity form-years via ext-2)
Mismatches verified 1 (wording-scope only, value correct → A1)
Mismatches rejected 0
Cross-reference checks 1 (microsim imputation — REJECTED, cleared)
External-document checks 2 (ext-1 TY2013 — cleared with reasoning above; ext-2 continuity — CONFIRMED)
Unmodeled program features 1 (§5219-KK(1)(E) assessor arm's-length rent adjustment; not modelable from microdata)
Pre-existing (outside PR scope) 2 (rent.yaml label misnomer; 2024 reference href → 2023 file → S7)

Validation Summary

Validator Result
Regulatory PASS — 0 critical; 3 should, 6 suggestions (consolidated above)
Reference 4/4 citations corroborated with correct page anchors; effective date corroborated twice; form-only 15% citation confirmed correct
Code PASS — 0 critical; naming/wording advisories consolidated (A1, A2); 10 pattern checks clean; ruff clean
Tests All 7 expectations verified; 2 mutation gaps downgraded from critical per policy (every branch has coverage) → A3; further gaps → A4; margin/jargon hygiene → A5
PDF audit 13 matches, 1 wording-only mismatch across 12 rendered pages + 2 at 600 DPI
Verifiers mismatch-1 CONFIRMED (doc-only); xref-1 REJECTED; ext-1 cleared (predecessor program, not an error); ext-2 continuity CONFIRMED
CI Passing YES (all checks pass)

Branch Status

The branch is 347 commits behind base (3 ahead). Rebase recommended before merge. Staleness did not affect any finding: all findings were verified against the PR snapshot at head SHA b008eae.

Review Severity: COMMENT

Zero critical findings. The value, mechanics, effective date, references, and formula are all verified correct against three cited form years, five additional sampled years, and the statute; the six SHOULD items are documentation wording, naming, and test-coverage improvements on a substantively correct fix.

Next Steps

Run the fix-pr workflow against this report: apply A1's wording broadening and gross-rent correction, A2's renames, A3's two mutation-guard tests, then the remaining A-items (coverage cases, margins, jargon scrub, clamp-comment reword) and any S-items worth taking; rebase on base and re-run CI.

DTrim99 and others added 4 commits August 24, 2026 09:23
Maine's property tax fairness credit computes rent constituting property
taxes as 15% of rent, after excluding any heat/utilities included in the
rent. Schedule PTFC/STFC line 5c provides that when the rent includes
utilities but the amount is not known, 15% of gross rent is treated as
the utility portion. me_property_tax_fairness_credit_countable_rent
previously left that fallback unimplemented, so a filer whose rent
includes utilities but who did not itemize a utility amount received no
utility exclusion. Add the 15% fallback and a parameter for the fraction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ator and clamp

- F1: the known/unknown split for the utility portion of rent was keyed on the
  household's general utility_expense (SNAP-style total), making the line-5c 15%
  fallback unreachable whenever any utility expense was reported and subtracting
  separately-paid utilities from rent. Add a dedicated me_ptfc_utilities_included_in_rent
  amount and drive the split off the utilities_included_in_rent boolean + that amount:
  not included -> no subtraction; included & known -> subtract it; included & unknown
  -> subtract the 15%-of-rent estimate.
- F2: clamp net rent with max_(rent - utility_portion, 0) so countable rent can never
  go negative and offset real_estate_taxes downstream (Schedule PTFC line 5d >= 0).
- Tests: add a separately-paid-utilities case (1,530, inverts if F1 reverted) and a
  utilities-exceed-rent clamp case (0). ME PTFC suite 36/36.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…(ME PTFC)

- Changelog: rename me-ptfc-utilities-in-rent.fixed.md -> .added.md (the PR adds a new
  parameter and input variable, so 'added' per repo convention).
- Documentation: me_ptfc_utilities_included_in_rent now documents that 0 means the amount
  is unknown (triggers the 15%-of-gross-rent line-5c estimate), disambiguating a known $0.
- References: utilities_included_in_rent.yaml adds the 2014 Schedule PTFC line-5c form
  (supports the 2014-01-01 start) alongside the 2022/2023 forms. No value/date change.
- Tests: integration case (rent with unknown utilities -> line-5c estimate -> positive
  credit) and a known-amount-equals-rent boundary (-> 0 countable rent). ME PTFC suite 38/38.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, add coverage (ME PTFC)

- A2: rename me_ptfc_utilities_included_in_rent -> me_property_tax_fairness_credit_utilities_in_rent_amount
  and rate/utilities_included_in_rent.yaml -> rate/utilities_share_of_rent.yaml (spelled-out sibling
  convention; the amount no longer reads as the adjacent utilities_included_in_rent boolean).
- A1: broaden 'heat or utilities' -> 'heat, utilities, furniture, or similar items'; replace 'gross rent'
  with 'rent paid (Schedule PTFC/STFC line 5a)' (gross rent is the utilities-exclusive base per 5219-KK(1)(E)).
- A6: reword the line-5d clamp comment to the modelling rationale (guards inconsistent input), not unprinted form text.
- A3/A4: mutation-guard tests (gate mirror; known-branch utility_expense guard) + coverage (multi-person,
  renter+owner, zero rent, >0 boundary, negative amount, default path, e2e known-amount credit).
- A5: absolute_error_margin on all cases; rename review-jargon case names to domain terms.
- S2/S3/S5/S7: statute-not-cited-for-15% note; move sentinel doc into the formula comment; comment/style
  polish; fix pre-existing rate/rent.yaml label + 2024 reference href.

No parameter value changed (0.15 intact). ME PTFC suite 50/50.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DTrim99
DTrim99 force-pushed the fix/me-ptfc-utilities-in-rent-v2 branch from b008eae to e5a551c Compare August 24, 2026 13:27
@DTrim99

DTrim99 commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up review addressed — thanks @PavelMakarchuk

Applied all six SHOULD items and the actionable suggestions from your 2026-08-23 review (ME PTFC suite 50/50, rebased on main). No parameter value changed (0.15 intact).

Should

  • A2 (naming) — renamed the variable me_ptfc_utilities_included_in_rentme_property_tax_fairness_credit_utilities_in_rent_amount (spelled-out sibling convention) and the parameter rate/utilities_included_in_rent.yamlrate/utilities_share_of_rent.yaml (names what it scales). It no longer reads as the adjacent utilities_included_in_rent boolean.
  • A1 (wording) — broadened "heat or utilities" → "heat, utilities, furniture, or similar items" (the form's terms), and replaced "gross rent" with "rent paid (Schedule PTFC/STFC line 5a)" across the param description/label, variable label, formula comment, and changelog — since §5219-KK(1)(E) defines gross rent as exclusive of utilities. Reshaped the param description to the [State] [verb] … convention.
  • A6 — reworded the line-5d clamp comment to the modelling rationale (guards inconsistent input; unknown branch 0.85×5a ≥ 0, known branch 5c is a component of 5a) rather than asserting unprinted form text.
  • A3 — added the two mutation guards: the gate mirror (utilities_included_in_rent: false + amount 400 → 150, not 90) and the known-branch utility_expense guard (rent 12k / amount 1,200 / heating_cooling 600 → 1,620, not 1,530).
  • A4 — added the coverage cases: multi-person JOINT aggregation (1,275), renter+owner combined (credit 710), zero-rent both sub-branches, the >0 sentinel boundary ($1 → 149.85), negative amount → estimate branch, the default rent-only path (15% of rent), and an e2e known-amount credit case (750).
  • A5absolute_error_margin: 0.01 on every case; renamed the "F1/F2/discriminator" review-jargon case names to domain terms (and fixed the utility_expenses-vs-heating_cooling name, the ungrammatical name, trailing periods, ≤90 chars).

Suggestions

  • S2 — noted in the parameter that §5219-KK is intentionally not cited for the 15% (the statute has no unknown-amount estimate), so a future reviewer won't add the wrong citation. S3 — moved the zero-as-unknown sentinel explanation out of documentation into the formula comment. S4 — added 2014 and 2024 unknown-branch pins + a header note that both 0.15 rates can't be distinguished by baseline cases. S5 — trimmed the formula comments, inlined amount_known, dropped the redundant default-restating input, removed the trailing blank line. S7 — fixed the pre-existing rate/rent.yaml label ("income rate" → rent rate) and the mislabeled 2024→2023 reference.

Not applied — S6 (make it a generic household-level input): that conflicts with A2's state-specific rename you (and three validators) asked for, and you flagged it as "design preference, not a defect," so I kept the state-specific variable. Happy to revisit if you'd prefer the shared-input direction instead.

Also annotated Cases 5/6 (amount ≥ rent → 0) as invalid-input clamp guards rather than Maine-published results, per your circularity note.

Fixed with Claude Code assistance.

@DTrim99
DTrim99 requested a review from PavelMakarchuk August 24, 2026 14:30
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.

2 participants