Skip to content

Document scale-lookup boundary conventions: right=True needs a -.inf first threshold - #85

Merged
hua7450 merged 1 commit into
PolicyEngine:mainfrom
hua7450:scale-lookup-boundary-conventions
Sep 1, 2026
Merged

Document scale-lookup boundary conventions: right=True needs a -.inf first threshold#85
hua7450 merged 1 commit into
PolicyEngine:mainfrom
hua7450:scale-lookup-boundary-conventions

Conversation

@hua7450

@hua7450 hua7450 commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Documents how to key single_amount bracket parameters when the source table prints closed integer bands, and the right=True trap that bit NY IT-214 (policyengine-us #9313).

Closes #83

What changed

  • references/parameters.md — new "Scale-lookup boundary conventions" subsection: the convention table (band starts + default calc vs. band tops + right=True), the first-threshold trap table, a right=True checklist, the round-half-up-before-lookup rule, and a CI-verified <!-- verify --> example.
  • references/variables.md — gotcha bullet: right=True at every call site, floor/round before the lookup.
  • references/tests.md — coverage bullet: test at exactly $0 and exactly at a band top for every single_amount lookup.
  • SKILL.md — routing row and trigger words.

Design decision

The convention is fixed by the source wording (statute / form / manual): band starts printed → band-start keys; "over X but not over Y" → band-top keys with right=True and -.inf. The issue's original "pick one convention per program" rule was dropped: tables keyed faithfully to their own wording already agree at every boundary.

This also replaces the previous 0.0001 threshold-shift guidance for "above X" with right=True + -.inf, which is exact and needs no epsilon. The old pattern is mentioned as legacy so readers recognize it in existing code.

Evidence (policyengine-core 3.30, SingleAmountTaxScale.calc)

Probe incomes [-100, 0, 3000, 3001], bands "$0–3,000 → 375; 3,001+ → 330":

keying call result
band starts [0, 3001] default [0, 375, 375, 330]
band tops [-inf, 3000] right=True [375, 375, 375, 330]
band tops [0, 3000] right=True [0, 0, 375, 330] ← exactly $0 zeroed
band tops [0, 3000] default [0, 375, 330, 330] ← the IT-214 bug

MarginalRateTaxScale.calc(..., right=True) raises TypeError, so the checklist notes right= exists only on single_amount/marginal_amount scales. np.round(3000.5) == 3000 (half-to-even) vs np.floor(3000.5 + 0.5) == 3001 (half-up).

Follow-up (policyengine-us, not in this PR)

A sweep of the 97 calc(..., right=True) call sites in policyengine-us found 48 whose parameter has a first threshold ≥ 0. Confirmed misfires at an input of exactly 0: CO CDCC match (0 instead of 0.5), HI CDCC rate (0 instead of 0.25), OH exemption credit ($0 instead of $20); CT personal credit rate returns 0 at exactly $15,000. Worth a separate policyengine-us issue.

Test plan

  • uv run pytest --ignore=tests/test_skill_examples.py — 152 passed
  • New <!-- verify --> block executed against the installed core — passes
  • CI skill-examples job

🤖 Generated with Claude Code

single_amount lookups are lower-bound inclusive by default, so a source table
printed as closed integer bands must be keyed by its wording: band starts with
the default calc, or band tops with calc(..., right=True). The right=True form
requires a -.inf first threshold, because a value exactly equal to the first
threshold otherwise falls below the scale and returns 0.

Adds the convention table, the first-threshold trap table, a right=True
checklist, the round-before-lookup rule, and a CI-verified example to
references/parameters.md; cross-reference bullets in variables.md and tests.md;
and routing/trigger updates in SKILL.md. Replaces the 0.0001 threshold-shift
guidance for "above X" with right=True + -.inf.

Closes PolicyEngine#83

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hua7450
hua7450 merged commit 87b6e33 into PolicyEngine:main Sep 1, 2026
2 checks passed
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.

Document scale-lookup boundary conventions: right=True needs a -.inf first threshold

1 participant