@markcolabs/mcp 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/LICENSE-API.md +111 -0
- package/README.md +128 -205
- package/dist/engines/compoundInterest.d.ts +8 -6
- package/dist/engines/compoundInterest.d.ts.map +1 -1
- package/dist/engines/compoundInterest.js +8 -6
- package/dist/engines/compoundInterest.js.map +1 -1
- package/dist/engines/data/irs2026.d.ts +110 -3
- package/dist/engines/data/irs2026.d.ts.map +1 -1
- package/dist/engines/data/irs2026.js +86 -3
- package/dist/engines/data/irs2026.js.map +1 -1
- package/dist/engines/data/rmd2026.d.ts +59 -0
- package/dist/engines/data/rmd2026.d.ts.map +1 -0
- package/dist/engines/data/rmd2026.js +75 -0
- package/dist/engines/data/rmd2026.js.map +1 -0
- package/dist/engines/data/stateTax2026.d.ts +114 -0
- package/dist/engines/data/stateTax2026.d.ts.map +1 -0
- package/dist/engines/data/stateTax2026.js +348 -0
- package/dist/engines/data/stateTax2026.js.map +1 -0
- package/dist/engines/hsa.d.ts +110 -0
- package/dist/engines/hsa.d.ts.map +1 -0
- package/dist/engines/hsa.js +83 -0
- package/dist/engines/hsa.js.map +1 -0
- package/dist/engines/ira.d.ts +115 -0
- package/dist/engines/ira.d.ts.map +1 -0
- package/dist/engines/ira.js +127 -0
- package/dist/engines/ira.js.map +1 -0
- package/dist/engines/mortgage.d.ts +7 -6
- package/dist/engines/mortgage.d.ts.map +1 -1
- package/dist/engines/mortgage.js +7 -6
- package/dist/engines/mortgage.js.map +1 -1
- package/dist/engines/paycheck.d.ts +57 -18
- package/dist/engines/paycheck.d.ts.map +1 -1
- package/dist/engines/paycheck.js +59 -26
- package/dist/engines/paycheck.js.map +1 -1
- package/dist/engines/retirement401k.d.ts +7 -3
- package/dist/engines/retirement401k.d.ts.map +1 -1
- package/dist/engines/retirement401k.js +7 -3
- package/dist/engines/retirement401k.js.map +1 -1
- package/dist/engines/rmd.d.ts +107 -0
- package/dist/engines/rmd.d.ts.map +1 -0
- package/dist/engines/rmd.js +109 -0
- package/dist/engines/rmd.js.map +1 -0
- package/dist/engines/rothConversion.d.ts +124 -0
- package/dist/engines/rothConversion.d.ts.map +1 -0
- package/dist/engines/rothConversion.js +145 -0
- package/dist/engines/rothConversion.js.map +1 -0
- package/dist/engines/socialSecurity.d.ts +7 -3
- package/dist/engines/socialSecurity.d.ts.map +1 -1
- package/dist/engines/socialSecurity.js +7 -3
- package/dist/engines/socialSecurity.js.map +1 -1
- package/dist/index.d.ts +21 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +109 -11
- package/dist/index.js.map +1 -1
- package/dist/shared/bounds.d.ts +50 -0
- package/dist/shared/bounds.d.ts.map +1 -1
- package/dist/shared/bounds.js +85 -0
- package/dist/shared/bounds.js.map +1 -1
- package/dist/tools/hsa.d.ts +58 -0
- package/dist/tools/hsa.d.ts.map +1 -0
- package/dist/tools/hsa.js +129 -0
- package/dist/tools/hsa.js.map +1 -0
- package/dist/tools/ira.d.ts +55 -0
- package/dist/tools/ira.d.ts.map +1 -0
- package/dist/tools/ira.js +117 -0
- package/dist/tools/ira.js.map +1 -0
- package/dist/tools/paycheck.d.ts +14 -7
- package/dist/tools/paycheck.d.ts.map +1 -1
- package/dist/tools/paycheck.js +24 -11
- package/dist/tools/paycheck.js.map +1 -1
- package/dist/tools/retirement401k.d.ts +3 -3
- package/dist/tools/retirement401k.d.ts.map +1 -1
- package/dist/tools/retirement401k.js +3 -3
- package/dist/tools/retirement401k.js.map +1 -1
- package/dist/tools/rmd.d.ts +60 -0
- package/dist/tools/rmd.d.ts.map +1 -0
- package/dist/tools/rmd.js +130 -0
- package/dist/tools/rmd.js.map +1 -0
- package/dist/tools/rothConversion.d.ts +66 -0
- package/dist/tools/rothConversion.d.ts.map +1 -0
- package/dist/tools/rothConversion.js +141 -0
- package/dist/tools/rothConversion.js.map +1 -0
- package/dist/tools/socialSecurity.d.ts +3 -3
- package/dist/tools/socialSecurity.d.ts.map +1 -1
- package/dist/tools/socialSecurity.js +3 -3
- package/dist/tools/socialSecurity.js.map +1 -1
- package/package.json +19 -5
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-contained 2026 state-income-tax effective-rate table for the
|
|
3
|
+
* `@markcolabs/mcp` paycheck engine (MCP-AUDIT-011 fix, S141 Item #5).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* v0.2.x of the paycheck engine returned a flat 5% state-tax estimate for
|
|
8
|
+
* every income-tax state. For HCOL states (CA top 13.3%, NY top 10.9%, HI
|
|
9
|
+
* top 11%) this was materially wrong — a $1M earner in CA was under-taxed by
|
|
10
|
+
* ~$85k. Documented as a known limitation but YMYL exposure was significant.
|
|
11
|
+
*
|
|
12
|
+
* v0.3.0 replaces the flat estimate with a state-aware effective-rate lookup
|
|
13
|
+
* using marginal-bracket simplification: for each state we precompute a
|
|
14
|
+
* **top-of-bracket effective rate** for several income tiers and pick the
|
|
15
|
+
* tier that brackets the caller's taxable income. This is not a full per-state
|
|
16
|
+
* bracket simulation (out of scope per kickoff) but materially correct for
|
|
17
|
+
* the common HCOL cases that drove the original finding.
|
|
18
|
+
*
|
|
19
|
+
* The site source for the rate data is `site/src/data/tax-tables/` for the
|
|
20
|
+
* three states the site engine models (CA, NY, TX). For the remaining 38
|
|
21
|
+
* income-tax states this module is the canonical mirror — the data is
|
|
22
|
+
* sourced from the Tax Foundation 2026 State Individual Income Tax Rates
|
|
23
|
+
* report (a citable, annually-updated authority).
|
|
24
|
+
*
|
|
25
|
+
* ## Simplification per kickoff
|
|
26
|
+
*
|
|
27
|
+
* Income tiers used for effective-rate lookup:
|
|
28
|
+
* - tier 1: taxable < $50,000 (most filers)
|
|
29
|
+
* - tier 2: taxable < $100,000 (median-to-upper-middle)
|
|
30
|
+
* - tier 3: taxable < $250,000 (HCOL professionals)
|
|
31
|
+
* - tier 4: taxable < $500,000 (high earners)
|
|
32
|
+
* - tier 5: taxable >= $500,000 (top-bracket)
|
|
33
|
+
*
|
|
34
|
+
* The rate at each tier is the **effective** rate (not the marginal top rate)
|
|
35
|
+
* for a hypothetical filer at the top of that tier, accounting for the
|
|
36
|
+
* weighted average across the state's progressive brackets. Flat-rate states
|
|
37
|
+
* use the same rate at every tier. No-income-tax states are omitted (handled
|
|
38
|
+
* by `NO_TAX_STATES` in `federalTax.ts`).
|
|
39
|
+
*
|
|
40
|
+
* ## Source
|
|
41
|
+
*
|
|
42
|
+
* Tax Foundation 2026 State Individual Income Tax Rates and Brackets,
|
|
43
|
+
* effective Jan 1 2026 (with 2026 inflation adjustments where applicable).
|
|
44
|
+
*
|
|
45
|
+
* Last verified: 2026-05-27 (S141 Item #5).
|
|
46
|
+
*
|
|
47
|
+
* @see MCP-AUDIT-011 — Paycheck flat 5% state-tax estimate
|
|
48
|
+
* @see docs/Claude/Architecture/ADR/ADR-0039 § 5 — engine SemVer policy
|
|
49
|
+
*/
|
|
50
|
+
export const STATE_TAX_2026_META = {
|
|
51
|
+
source: "Tax Foundation 2026 State Individual Income Tax Rates",
|
|
52
|
+
lastVerified: "2026-05-27",
|
|
53
|
+
taxYear: 2026,
|
|
54
|
+
methodology: "Top-of-bracket effective rate selected by income tier. Not a full " +
|
|
55
|
+
"per-state bracket simulation — see methodology page for full rates.",
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Pick the income tier appropriate for a given taxable income.
|
|
59
|
+
* Uses left-inclusive boundaries.
|
|
60
|
+
*/
|
|
61
|
+
export function pickIncomeTier(taxableIncome) {
|
|
62
|
+
if (taxableIncome < 50_000)
|
|
63
|
+
return "under50k";
|
|
64
|
+
if (taxableIncome < 100_000)
|
|
65
|
+
return "under100k";
|
|
66
|
+
if (taxableIncome < 250_000)
|
|
67
|
+
return "under250k";
|
|
68
|
+
if (taxableIncome < 500_000)
|
|
69
|
+
return "under500k";
|
|
70
|
+
return "over500k";
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 2026 state effective tax rates (decimals) by income tier.
|
|
74
|
+
*
|
|
75
|
+
* NOT INCLUDED (handled by NO_TAX_STATES in federalTax.ts):
|
|
76
|
+
* AK, FL, NV, NH, SD, TN, TX, WA, WY
|
|
77
|
+
*
|
|
78
|
+
* NH currently taxes only interest/dividends (phased out for wages 2025+),
|
|
79
|
+
* treated as no-tax for wage income.
|
|
80
|
+
*
|
|
81
|
+
* Rates rounded to four decimal places. Local-income-tax piggybacks (NYC,
|
|
82
|
+
* Yonkers, PA municipal EIT) NOT included — surfaced as a `notes` warning
|
|
83
|
+
* for impacted states. State Disability Insurance (CA SDI, NY SDI, NJ SDI)
|
|
84
|
+
* is not income tax and is NOT included.
|
|
85
|
+
*/
|
|
86
|
+
export const STATE_EFFECTIVE_RATES_2026 = {
|
|
87
|
+
AL: {
|
|
88
|
+
stateCode: "AL",
|
|
89
|
+
stateName: "Alabama",
|
|
90
|
+
rates: { under50k: 0.04, under100k: 0.045, under250k: 0.05, under500k: 0.05, over500k: 0.05 },
|
|
91
|
+
},
|
|
92
|
+
AZ: {
|
|
93
|
+
stateCode: "AZ",
|
|
94
|
+
stateName: "Arizona",
|
|
95
|
+
rates: { under50k: 0.025, under100k: 0.025, under250k: 0.025, under500k: 0.025, over500k: 0.025 },
|
|
96
|
+
notes: "Flat 2.5% post-2023 reform.",
|
|
97
|
+
},
|
|
98
|
+
AR: {
|
|
99
|
+
stateCode: "AR",
|
|
100
|
+
stateName: "Arkansas",
|
|
101
|
+
rates: { under50k: 0.038, under100k: 0.039, under250k: 0.039, under500k: 0.039, over500k: 0.039 },
|
|
102
|
+
},
|
|
103
|
+
CA: {
|
|
104
|
+
stateCode: "CA",
|
|
105
|
+
stateName: "California",
|
|
106
|
+
rates: { under50k: 0.04, under100k: 0.065, under250k: 0.093, under500k: 0.103, over500k: 0.123 },
|
|
107
|
+
notes: "Excludes 1% Mental Health Services Tax above $1M and SDI.",
|
|
108
|
+
},
|
|
109
|
+
CO: {
|
|
110
|
+
stateCode: "CO",
|
|
111
|
+
stateName: "Colorado",
|
|
112
|
+
rates: { under50k: 0.044, under100k: 0.044, under250k: 0.044, under500k: 0.044, over500k: 0.044 },
|
|
113
|
+
notes: "Flat 4.4% (2026 estimate post-TABOR refund).",
|
|
114
|
+
},
|
|
115
|
+
CT: {
|
|
116
|
+
stateCode: "CT",
|
|
117
|
+
stateName: "Connecticut",
|
|
118
|
+
rates: { under50k: 0.045, under100k: 0.055, under250k: 0.06, under500k: 0.063, over500k: 0.0699 },
|
|
119
|
+
},
|
|
120
|
+
DE: {
|
|
121
|
+
stateCode: "DE",
|
|
122
|
+
stateName: "Delaware",
|
|
123
|
+
rates: { under50k: 0.045, under100k: 0.052, under250k: 0.066, under500k: 0.066, over500k: 0.066 },
|
|
124
|
+
},
|
|
125
|
+
GA: {
|
|
126
|
+
stateCode: "GA",
|
|
127
|
+
stateName: "Georgia",
|
|
128
|
+
rates: { under50k: 0.0539, under100k: 0.0539, under250k: 0.0539, under500k: 0.0539, over500k: 0.0539 },
|
|
129
|
+
notes: "Flat 5.39% (2026, scheduled to drop annually toward 4.99%).",
|
|
130
|
+
},
|
|
131
|
+
HI: {
|
|
132
|
+
stateCode: "HI",
|
|
133
|
+
stateName: "Hawaii",
|
|
134
|
+
rates: { under50k: 0.07, under100k: 0.08, under250k: 0.0925, under500k: 0.10, over500k: 0.11 },
|
|
135
|
+
notes: "Has many narrow brackets; effective rate approximation.",
|
|
136
|
+
},
|
|
137
|
+
ID: {
|
|
138
|
+
stateCode: "ID",
|
|
139
|
+
stateName: "Idaho",
|
|
140
|
+
rates: { under50k: 0.058, under100k: 0.058, under250k: 0.058, under500k: 0.058, over500k: 0.058 },
|
|
141
|
+
notes: "Flat 5.8% post-2023 reform.",
|
|
142
|
+
},
|
|
143
|
+
IL: {
|
|
144
|
+
stateCode: "IL",
|
|
145
|
+
stateName: "Illinois",
|
|
146
|
+
rates: { under50k: 0.0495, under100k: 0.0495, under250k: 0.0495, under500k: 0.0495, over500k: 0.0495 },
|
|
147
|
+
notes: "Flat 4.95%.",
|
|
148
|
+
},
|
|
149
|
+
IN: {
|
|
150
|
+
stateCode: "IN",
|
|
151
|
+
stateName: "Indiana",
|
|
152
|
+
rates: { under50k: 0.0305, under100k: 0.0305, under250k: 0.0305, under500k: 0.0305, over500k: 0.0305 },
|
|
153
|
+
notes: "Flat 3.05% (2026). Local county taxes (LIT) NOT included.",
|
|
154
|
+
},
|
|
155
|
+
IA: {
|
|
156
|
+
stateCode: "IA",
|
|
157
|
+
stateName: "Iowa",
|
|
158
|
+
rates: { under50k: 0.038, under100k: 0.038, under250k: 0.038, under500k: 0.038, over500k: 0.038 },
|
|
159
|
+
notes: "Flat 3.8% (2026 reform).",
|
|
160
|
+
},
|
|
161
|
+
KS: {
|
|
162
|
+
stateCode: "KS",
|
|
163
|
+
stateName: "Kansas",
|
|
164
|
+
rates: { under50k: 0.031, under100k: 0.0525, under250k: 0.057, under500k: 0.057, over500k: 0.057 },
|
|
165
|
+
},
|
|
166
|
+
KY: {
|
|
167
|
+
stateCode: "KY",
|
|
168
|
+
stateName: "Kentucky",
|
|
169
|
+
rates: { under50k: 0.04, under100k: 0.04, under250k: 0.04, under500k: 0.04, over500k: 0.04 },
|
|
170
|
+
notes: "Flat 4% (2026). Local occupational taxes NOT included.",
|
|
171
|
+
},
|
|
172
|
+
LA: {
|
|
173
|
+
stateCode: "LA",
|
|
174
|
+
stateName: "Louisiana",
|
|
175
|
+
rates: { under50k: 0.03, under100k: 0.03, under250k: 0.03, under500k: 0.03, over500k: 0.03 },
|
|
176
|
+
notes: "Flat 3% (2025 reform).",
|
|
177
|
+
},
|
|
178
|
+
ME: {
|
|
179
|
+
stateCode: "ME",
|
|
180
|
+
stateName: "Maine",
|
|
181
|
+
rates: { under50k: 0.058, under100k: 0.0675, under250k: 0.0715, under500k: 0.0715, over500k: 0.0715 },
|
|
182
|
+
},
|
|
183
|
+
MD: {
|
|
184
|
+
stateCode: "MD",
|
|
185
|
+
stateName: "Maryland",
|
|
186
|
+
rates: { under50k: 0.0475, under100k: 0.0525, under250k: 0.0555, under500k: 0.0575, over500k: 0.0575 },
|
|
187
|
+
notes: "Local county taxes (2.25%–3.2%) NOT included.",
|
|
188
|
+
},
|
|
189
|
+
MA: {
|
|
190
|
+
stateCode: "MA",
|
|
191
|
+
stateName: "Massachusetts",
|
|
192
|
+
rates: { under50k: 0.05, under100k: 0.05, under250k: 0.05, under500k: 0.05, over500k: 0.09 },
|
|
193
|
+
notes: "Flat 5% + 4% millionaire surtax above $1M.",
|
|
194
|
+
},
|
|
195
|
+
MI: {
|
|
196
|
+
stateCode: "MI",
|
|
197
|
+
stateName: "Michigan",
|
|
198
|
+
rates: { under50k: 0.0425, under100k: 0.0425, under250k: 0.0425, under500k: 0.0425, over500k: 0.0425 },
|
|
199
|
+
notes: "Flat 4.25%. Local city taxes NOT included.",
|
|
200
|
+
},
|
|
201
|
+
MN: {
|
|
202
|
+
stateCode: "MN",
|
|
203
|
+
stateName: "Minnesota",
|
|
204
|
+
rates: { under50k: 0.0535, under100k: 0.068, under250k: 0.0785, under500k: 0.0985, over500k: 0.0985 },
|
|
205
|
+
},
|
|
206
|
+
MS: {
|
|
207
|
+
stateCode: "MS",
|
|
208
|
+
stateName: "Mississippi",
|
|
209
|
+
rates: { under50k: 0.044, under100k: 0.044, under250k: 0.044, under500k: 0.044, over500k: 0.044 },
|
|
210
|
+
notes: "Flat 4.4% (2026, phasing toward 4%).",
|
|
211
|
+
},
|
|
212
|
+
MO: {
|
|
213
|
+
stateCode: "MO",
|
|
214
|
+
stateName: "Missouri",
|
|
215
|
+
rates: { under50k: 0.038, under100k: 0.047, under250k: 0.047, under500k: 0.047, over500k: 0.047 },
|
|
216
|
+
},
|
|
217
|
+
MT: {
|
|
218
|
+
stateCode: "MT",
|
|
219
|
+
stateName: "Montana",
|
|
220
|
+
rates: { under50k: 0.047, under100k: 0.059, under250k: 0.059, under500k: 0.059, over500k: 0.059 },
|
|
221
|
+
},
|
|
222
|
+
NE: {
|
|
223
|
+
stateCode: "NE",
|
|
224
|
+
stateName: "Nebraska",
|
|
225
|
+
rates: { under50k: 0.0246, under100k: 0.0464, under250k: 0.052, under500k: 0.052, over500k: 0.052 },
|
|
226
|
+
},
|
|
227
|
+
NJ: {
|
|
228
|
+
stateCode: "NJ",
|
|
229
|
+
stateName: "New Jersey",
|
|
230
|
+
rates: { under50k: 0.0175, under100k: 0.05525, under250k: 0.0637, under500k: 0.0897, over500k: 0.1075 },
|
|
231
|
+
notes: "Excludes SDI/UI/FLI payroll deductions.",
|
|
232
|
+
},
|
|
233
|
+
NM: {
|
|
234
|
+
stateCode: "NM",
|
|
235
|
+
stateName: "New Mexico",
|
|
236
|
+
rates: { under50k: 0.032, under100k: 0.047, under250k: 0.049, under500k: 0.059, over500k: 0.059 },
|
|
237
|
+
},
|
|
238
|
+
NY: {
|
|
239
|
+
stateCode: "NY",
|
|
240
|
+
stateName: "New York",
|
|
241
|
+
rates: { under50k: 0.045, under100k: 0.0585, under250k: 0.0685, under500k: 0.0685, over500k: 0.0882 },
|
|
242
|
+
notes: "Excludes NYC local tax (additional ~3-3.876%) and Yonkers piggyback. " +
|
|
243
|
+
"NYC residents should add ~3% to effective rate.",
|
|
244
|
+
},
|
|
245
|
+
NC: {
|
|
246
|
+
stateCode: "NC",
|
|
247
|
+
stateName: "North Carolina",
|
|
248
|
+
rates: { under50k: 0.0425, under100k: 0.0425, under250k: 0.0425, under500k: 0.0425, over500k: 0.0425 },
|
|
249
|
+
notes: "Flat 4.25% (2026, phasing toward 3.99%).",
|
|
250
|
+
},
|
|
251
|
+
ND: {
|
|
252
|
+
stateCode: "ND",
|
|
253
|
+
stateName: "North Dakota",
|
|
254
|
+
rates: { under50k: 0.0195, under100k: 0.0195, under250k: 0.025, under500k: 0.025, over500k: 0.025 },
|
|
255
|
+
},
|
|
256
|
+
OH: {
|
|
257
|
+
stateCode: "OH",
|
|
258
|
+
stateName: "Ohio",
|
|
259
|
+
rates: { under50k: 0.0275, under100k: 0.035, under250k: 0.035, under500k: 0.035, over500k: 0.035 },
|
|
260
|
+
notes: "Local municipal income taxes NOT included.",
|
|
261
|
+
},
|
|
262
|
+
OK: {
|
|
263
|
+
stateCode: "OK",
|
|
264
|
+
stateName: "Oklahoma",
|
|
265
|
+
rates: { under50k: 0.0375, under100k: 0.0475, under250k: 0.0475, under500k: 0.0475, over500k: 0.0475 },
|
|
266
|
+
},
|
|
267
|
+
OR: {
|
|
268
|
+
stateCode: "OR",
|
|
269
|
+
stateName: "Oregon",
|
|
270
|
+
rates: { under50k: 0.0875, under100k: 0.0875, under250k: 0.099, under500k: 0.099, over500k: 0.099 },
|
|
271
|
+
notes: "High effective rate at all tiers; metro/transit taxes NOT included.",
|
|
272
|
+
},
|
|
273
|
+
PA: {
|
|
274
|
+
stateCode: "PA",
|
|
275
|
+
stateName: "Pennsylvania",
|
|
276
|
+
rates: { under50k: 0.0307, under100k: 0.0307, under250k: 0.0307, under500k: 0.0307, over500k: 0.0307 },
|
|
277
|
+
notes: "Flat 3.07%. Local municipal EIT (1-4%) NOT included.",
|
|
278
|
+
},
|
|
279
|
+
RI: {
|
|
280
|
+
stateCode: "RI",
|
|
281
|
+
stateName: "Rhode Island",
|
|
282
|
+
rates: { under50k: 0.0375, under100k: 0.0475, under250k: 0.0599, under500k: 0.0599, over500k: 0.0599 },
|
|
283
|
+
},
|
|
284
|
+
SC: {
|
|
285
|
+
stateCode: "SC",
|
|
286
|
+
stateName: "South Carolina",
|
|
287
|
+
rates: { under50k: 0.03, under100k: 0.062, under250k: 0.062, under500k: 0.062, over500k: 0.062 },
|
|
288
|
+
},
|
|
289
|
+
UT: {
|
|
290
|
+
stateCode: "UT",
|
|
291
|
+
stateName: "Utah",
|
|
292
|
+
rates: { under50k: 0.0455, under100k: 0.0455, under250k: 0.0455, under500k: 0.0455, over500k: 0.0455 },
|
|
293
|
+
notes: "Flat 4.55%.",
|
|
294
|
+
},
|
|
295
|
+
VT: {
|
|
296
|
+
stateCode: "VT",
|
|
297
|
+
stateName: "Vermont",
|
|
298
|
+
rates: { under50k: 0.0335, under100k: 0.066, under250k: 0.076, under500k: 0.0875, over500k: 0.0875 },
|
|
299
|
+
},
|
|
300
|
+
VA: {
|
|
301
|
+
stateCode: "VA",
|
|
302
|
+
stateName: "Virginia",
|
|
303
|
+
rates: { under50k: 0.0475, under100k: 0.0575, under250k: 0.0575, under500k: 0.0575, over500k: 0.0575 },
|
|
304
|
+
},
|
|
305
|
+
WV: {
|
|
306
|
+
stateCode: "WV",
|
|
307
|
+
stateName: "West Virginia",
|
|
308
|
+
rates: { under50k: 0.0436, under100k: 0.0482, under250k: 0.0482, under500k: 0.0482, over500k: 0.0482 },
|
|
309
|
+
},
|
|
310
|
+
WI: {
|
|
311
|
+
stateCode: "WI",
|
|
312
|
+
stateName: "Wisconsin",
|
|
313
|
+
rates: { under50k: 0.0354, under100k: 0.053, under250k: 0.0765, under500k: 0.0765, over500k: 0.0765 },
|
|
314
|
+
},
|
|
315
|
+
DC: {
|
|
316
|
+
stateCode: "DC",
|
|
317
|
+
stateName: "District of Columbia",
|
|
318
|
+
rates: { under50k: 0.06, under100k: 0.065, under250k: 0.085, under500k: 0.0925, over500k: 0.1075 },
|
|
319
|
+
notes: "DC included for full HCOL coverage even though not a state.",
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Look up the effective state income-tax rate for a given state and taxable income.
|
|
324
|
+
*
|
|
325
|
+
* Returns 0 for no-income-tax states (caller should also check NO_TAX_STATES).
|
|
326
|
+
* Returns 0 for unknown state codes (defensive fallback — caller already validated
|
|
327
|
+
* 2-letter format at the Zod schema layer; this guards against typos that pass
|
|
328
|
+
* Zod but aren't in our table).
|
|
329
|
+
*
|
|
330
|
+
* @param stateCode 2-letter US state code (uppercase)
|
|
331
|
+
* @param taxableIncome Annual taxable income in USD (post-federal-standard-deduction basis)
|
|
332
|
+
* @returns Decimal effective rate (e.g., 0.093 for 9.3%); 0 if state not modeled
|
|
333
|
+
*/
|
|
334
|
+
export function getStateEffectiveRate(stateCode, taxableIncome) {
|
|
335
|
+
const upper = stateCode.trim().toUpperCase();
|
|
336
|
+
const entry = STATE_EFFECTIVE_RATES_2026[upper];
|
|
337
|
+
if (!entry)
|
|
338
|
+
return 0;
|
|
339
|
+
const tier = pickIncomeTier(Math.max(0, taxableIncome));
|
|
340
|
+
return entry.rates[tier];
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Get the full state data entry (for surfacing `notes` in the tool envelope).
|
|
344
|
+
*/
|
|
345
|
+
export function getStateEntry(stateCode) {
|
|
346
|
+
return STATE_EFFECTIVE_RATES_2026[stateCode.trim().toUpperCase()];
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=stateTax2026.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateTax2026.js","sourceRoot":"","sources":["../../../src/engines/data/stateTax2026.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HSA (Health Savings Account) contribution-limit engine — lifted from
|
|
3
|
+
* site/src/utils/hsa-limits.js (functions `getMaxContribution`,
|
|
4
|
+
* `isCatchUpEligible`).
|
|
5
|
+
*
|
|
6
|
+
* Per ADR-0039 § 5: pure synchronous function, ENGINE_VERSION constant,
|
|
7
|
+
* parity test against the site source as the gate.
|
|
8
|
+
*
|
|
9
|
+
* Scope (S141 Wave 1B Item #3): contribution-LIMIT and employer-reduction
|
|
10
|
+
* math. Does NOT compute long-term HSA growth projection (the site calc's
|
|
11
|
+
* `generateGrowthProjection`) or split federal/state/FICA tax-savings
|
|
12
|
+
* breakdown (the site calc's `calculateTotalTaxSavings` returns a 3-component
|
|
13
|
+
* breakdown). For v1 this tool exposes a single `payrollDeductionTaxSavings`
|
|
14
|
+
* convenience field — combined federal+state+FICA at the caller-provided
|
|
15
|
+
* marginal rate — as the simplest useful tax-impact answer. Detailed
|
|
16
|
+
* breakdowns are a future tool: `dc.calculator.hsa.taxSavingsBreakdown`.
|
|
17
|
+
*
|
|
18
|
+
* Math reference (per IRC §223 + IRS Rev. Proc. 2025-19):
|
|
19
|
+
* baseLimit = coverageTier === "family" ? family : selfOnly
|
|
20
|
+
* catchUpAmount = age ≥ 55 ? 1000 : 0
|
|
21
|
+
* totalContributionLimit = baseLimit + catchUpAmount
|
|
22
|
+
* employeeMaxRemaining = max(0, totalContributionLimit − employerContribution)
|
|
23
|
+
* payrollDeductionTaxSavings = marginalRate provided
|
|
24
|
+
* ? employeeMaxRemaining × (marginalRate / 100)
|
|
25
|
+
* : 0
|
|
26
|
+
*
|
|
27
|
+
* Why employer contributions reduce employee max dollar-for-dollar: the IRS
|
|
28
|
+
* §223(b) limit is a TOTAL annual limit across all funding sources, not a
|
|
29
|
+
* per-source limit. An employer that contributes $2,000 to a family-tier HSA
|
|
30
|
+
* leaves $6,750 of room for employee payroll deductions ($8,750 − $2,000).
|
|
31
|
+
*
|
|
32
|
+
* Source: IRS Rev. Proc. 2025-19 (2026 HSA inflation adjustments) +
|
|
33
|
+
* IRC §223(b)(3)(B) (statutory $1,000 catch-up, NOT inflation-indexed).
|
|
34
|
+
* Last verified: 2026-05-27.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* SemVer of the HSA engine. Per ADR-0039 § 5 (reaffirmed in ADR-0041
|
|
38
|
+
* Position #4a): major bump = math change; minor = additive output; patch =
|
|
39
|
+
* numerical correction. NOT bumped for cosmetic refactors.
|
|
40
|
+
* - 1.0.0: initial v1 lift from hsa-limits.js (S141 Wave 1B).
|
|
41
|
+
*/
|
|
42
|
+
export declare const ENGINE_VERSION = "1.0.0";
|
|
43
|
+
/**
|
|
44
|
+
* HDHP coverage tier. IRS canonical names per Rev. Proc. 2025-19:
|
|
45
|
+
* - `"self-only"` (≈ site's `"individual"` spelling)
|
|
46
|
+
* - `"family"` (matches site)
|
|
47
|
+
*/
|
|
48
|
+
export type HsaCoverageTier = "self-only" | "family";
|
|
49
|
+
/** Inputs to the HSA contribution-limit engine. */
|
|
50
|
+
export interface HsaContributionLimitInput {
|
|
51
|
+
/** Current age (drives age-55+ catch-up eligibility). */
|
|
52
|
+
age: number;
|
|
53
|
+
/** HDHP coverage tier. */
|
|
54
|
+
coverageTier: HsaCoverageTier;
|
|
55
|
+
/**
|
|
56
|
+
* Annual employer HSA contribution, USD. Reduces the employee's eligible
|
|
57
|
+
* payroll-deduction room dollar-for-dollar. Defaults to 0.
|
|
58
|
+
*/
|
|
59
|
+
employerContribution?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Estimated marginal federal tax rate, whole-number percent (e.g., 22 for
|
|
62
|
+
* 22%). Optional — when omitted, `payrollDeductionTaxSavings` returns 0.
|
|
63
|
+
* Combined federal+state+FICA is a future tool; for v1 this is treated as
|
|
64
|
+
* the user's effective marginal rate against the remaining employee
|
|
65
|
+
* contribution.
|
|
66
|
+
*/
|
|
67
|
+
estimatedMarginalRatePercent?: number;
|
|
68
|
+
}
|
|
69
|
+
/** Result payload returned by the engine. */
|
|
70
|
+
export interface HsaContributionLimitResult {
|
|
71
|
+
/** Base IRS limit for the selected coverage tier (without catch-up), USD. */
|
|
72
|
+
contributionLimit: number;
|
|
73
|
+
/** Whether the user qualifies for the age 55+ catch-up. */
|
|
74
|
+
catchUpEligible: boolean;
|
|
75
|
+
/** Catch-up amount applied ($1,000 if eligible, else 0), USD. */
|
|
76
|
+
catchUpAmount: number;
|
|
77
|
+
/** Total annual limit (contributionLimit + catchUpAmount), USD. */
|
|
78
|
+
totalContributionLimit: number;
|
|
79
|
+
/** Echoes the input employer contribution, USD. */
|
|
80
|
+
employerContribution: number;
|
|
81
|
+
/**
|
|
82
|
+
* Remaining room the EMPLOYEE can contribute via payroll after subtracting
|
|
83
|
+
* the employer contribution. Clamped at 0 (an over-the-cap employer
|
|
84
|
+
* contribution does not produce negative employee room). USD.
|
|
85
|
+
*/
|
|
86
|
+
employeeMaxRemaining: number;
|
|
87
|
+
/**
|
|
88
|
+
* Estimated tax savings if the employee contributes employeeMaxRemaining
|
|
89
|
+
* via payroll, at the provided marginal rate. 0 when marginal rate is not
|
|
90
|
+
* provided. USD.
|
|
91
|
+
*/
|
|
92
|
+
payrollDeductionTaxSavings: number;
|
|
93
|
+
/** Provenance metadata. */
|
|
94
|
+
meta: {
|
|
95
|
+
/** IRS tax year these limits apply to. */
|
|
96
|
+
tableYear: number;
|
|
97
|
+
/** Source authority (IRS revenue procedure / IRC citation). */
|
|
98
|
+
source: string;
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Compute the HSA contribution limit + employer-reduction + payroll-deduction
|
|
103
|
+
* tax savings for the given inputs.
|
|
104
|
+
*
|
|
105
|
+
* 1-to-1 logic port of site/src/utils/hsa-limits.js `getMaxContribution` +
|
|
106
|
+
* `isCatchUpEligible`, extended with the explicit employer-reduction math
|
|
107
|
+
* and an optional payroll-deduction tax-savings convenience field.
|
|
108
|
+
*/
|
|
109
|
+
export declare function contributionLimit(input: HsaContributionLimitInput): HsaContributionLimitResult;
|
|
110
|
+
//# sourceMappingURL=hsa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsa.d.ts","sourceRoot":"","sources":["../../src/engines/hsa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,QAAQ,CAAC;AAErD,mDAAmD;AACnD,MAAM,WAAW,yBAAyB;IACxC,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,YAAY,EAAE,eAAe,CAAC;IAC9B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;OAMG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AAED,6CAA6C;AAC7C,MAAM,WAAW,0BAA0B;IACzC,6EAA6E;IAC7E,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,eAAe,EAAE,OAAO,CAAC;IACzB,iEAAiE;IACjE,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,mDAAmD;IACnD,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,0BAA0B,EAAE,MAAM,CAAC;IACnC,2BAA2B;IAC3B,IAAI,EAAE;QACJ,0CAA0C;QAC1C,SAAS,EAAE,MAAM,CAAC;QAClB,+DAA+D;QAC/D,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,yBAAyB,GAC/B,0BAA0B,CAiD5B"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HSA (Health Savings Account) contribution-limit engine — lifted from
|
|
3
|
+
* site/src/utils/hsa-limits.js (functions `getMaxContribution`,
|
|
4
|
+
* `isCatchUpEligible`).
|
|
5
|
+
*
|
|
6
|
+
* Per ADR-0039 § 5: pure synchronous function, ENGINE_VERSION constant,
|
|
7
|
+
* parity test against the site source as the gate.
|
|
8
|
+
*
|
|
9
|
+
* Scope (S141 Wave 1B Item #3): contribution-LIMIT and employer-reduction
|
|
10
|
+
* math. Does NOT compute long-term HSA growth projection (the site calc's
|
|
11
|
+
* `generateGrowthProjection`) or split federal/state/FICA tax-savings
|
|
12
|
+
* breakdown (the site calc's `calculateTotalTaxSavings` returns a 3-component
|
|
13
|
+
* breakdown). For v1 this tool exposes a single `payrollDeductionTaxSavings`
|
|
14
|
+
* convenience field — combined federal+state+FICA at the caller-provided
|
|
15
|
+
* marginal rate — as the simplest useful tax-impact answer. Detailed
|
|
16
|
+
* breakdowns are a future tool: `dc.calculator.hsa.taxSavingsBreakdown`.
|
|
17
|
+
*
|
|
18
|
+
* Math reference (per IRC §223 + IRS Rev. Proc. 2025-19):
|
|
19
|
+
* baseLimit = coverageTier === "family" ? family : selfOnly
|
|
20
|
+
* catchUpAmount = age ≥ 55 ? 1000 : 0
|
|
21
|
+
* totalContributionLimit = baseLimit + catchUpAmount
|
|
22
|
+
* employeeMaxRemaining = max(0, totalContributionLimit − employerContribution)
|
|
23
|
+
* payrollDeductionTaxSavings = marginalRate provided
|
|
24
|
+
* ? employeeMaxRemaining × (marginalRate / 100)
|
|
25
|
+
* : 0
|
|
26
|
+
*
|
|
27
|
+
* Why employer contributions reduce employee max dollar-for-dollar: the IRS
|
|
28
|
+
* §223(b) limit is a TOTAL annual limit across all funding sources, not a
|
|
29
|
+
* per-source limit. An employer that contributes $2,000 to a family-tier HSA
|
|
30
|
+
* leaves $6,750 of room for employee payroll deductions ($8,750 − $2,000).
|
|
31
|
+
*
|
|
32
|
+
* Source: IRS Rev. Proc. 2025-19 (2026 HSA inflation adjustments) +
|
|
33
|
+
* IRC §223(b)(3)(B) (statutory $1,000 catch-up, NOT inflation-indexed).
|
|
34
|
+
* Last verified: 2026-05-27.
|
|
35
|
+
*/
|
|
36
|
+
import { LIMITS_HSA_2026 } from "./data/irs2026.js";
|
|
37
|
+
/**
|
|
38
|
+
* SemVer of the HSA engine. Per ADR-0039 § 5 (reaffirmed in ADR-0041
|
|
39
|
+
* Position #4a): major bump = math change; minor = additive output; patch =
|
|
40
|
+
* numerical correction. NOT bumped for cosmetic refactors.
|
|
41
|
+
* - 1.0.0: initial v1 lift from hsa-limits.js (S141 Wave 1B).
|
|
42
|
+
*/
|
|
43
|
+
export const ENGINE_VERSION = "1.0.0";
|
|
44
|
+
/**
|
|
45
|
+
* Compute the HSA contribution limit + employer-reduction + payroll-deduction
|
|
46
|
+
* tax savings for the given inputs.
|
|
47
|
+
*
|
|
48
|
+
* 1-to-1 logic port of site/src/utils/hsa-limits.js `getMaxContribution` +
|
|
49
|
+
* `isCatchUpEligible`, extended with the explicit employer-reduction math
|
|
50
|
+
* and an optional payroll-deduction tax-savings convenience field.
|
|
51
|
+
*/
|
|
52
|
+
export function contributionLimit(input) {
|
|
53
|
+
const { age, coverageTier, employerContribution = 0, estimatedMarginalRatePercent, } = input;
|
|
54
|
+
// Base contribution limit per coverage tier (IRS Rev. Proc. 2025-19).
|
|
55
|
+
const baseLimit = coverageTier === "family"
|
|
56
|
+
? LIMITS_HSA_2026.family
|
|
57
|
+
: LIMITS_HSA_2026.selfOnly;
|
|
58
|
+
// Catch-up: $1,000 if age ≥ 55 (statutory, IRC §223(b)(3)(B)).
|
|
59
|
+
const catchUpEligible = age >= LIMITS_HSA_2026.catchUpAge;
|
|
60
|
+
const catchUpAmount = catchUpEligible ? LIMITS_HSA_2026.catchUp : 0;
|
|
61
|
+
const totalContributionLimit = baseLimit + catchUpAmount;
|
|
62
|
+
// Employer contribution reduces employee max dollar-for-dollar; clamp at 0.
|
|
63
|
+
const employeeMaxRemaining = Math.max(0, totalContributionLimit - employerContribution);
|
|
64
|
+
// Payroll-deduction tax savings (combined federal + state + FICA proxy).
|
|
65
|
+
// Pre-tax payroll deduction reduces taxable income → marginal-rate savings.
|
|
66
|
+
const payrollDeductionTaxSavings = typeof estimatedMarginalRatePercent === "number"
|
|
67
|
+
? Math.round(employeeMaxRemaining * (estimatedMarginalRatePercent / 100) * 100) / 100
|
|
68
|
+
: 0;
|
|
69
|
+
return {
|
|
70
|
+
contributionLimit: baseLimit,
|
|
71
|
+
catchUpEligible,
|
|
72
|
+
catchUpAmount,
|
|
73
|
+
totalContributionLimit,
|
|
74
|
+
employerContribution,
|
|
75
|
+
employeeMaxRemaining,
|
|
76
|
+
payrollDeductionTaxSavings,
|
|
77
|
+
meta: {
|
|
78
|
+
tableYear: 2026,
|
|
79
|
+
source: "IRS Rev. Proc. 2025-19; IRC §223(b)(3)(B) (statutory $1,000 catch-up)",
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=hsa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsa.js","sourceRoot":"","sources":["../../src/engines/hsa.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AA+DtC;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAgC;IAEhC,MAAM,EACJ,GAAG,EACH,YAAY,EACZ,oBAAoB,GAAG,CAAC,EACxB,4BAA4B,GAC7B,GAAG,KAAK,CAAC;IAEV,sEAAsE;IACtE,MAAM,SAAS,GACb,YAAY,KAAK,QAAQ;QACvB,CAAC,CAAC,eAAe,CAAC,MAAM;QACxB,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC;IAE/B,+DAA+D;IAC/D,MAAM,eAAe,GAAG,GAAG,IAAI,eAAe,CAAC,UAAU,CAAC;IAC1D,MAAM,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpE,MAAM,sBAAsB,GAAG,SAAS,GAAG,aAAa,CAAC;IAEzD,4EAA4E;IAC5E,MAAM,oBAAoB,GAAG,IAAI,CAAC,GAAG,CACnC,CAAC,EACD,sBAAsB,GAAG,oBAAoB,CAC9C,CAAC;IAEF,yEAAyE;IACzE,4EAA4E;IAC5E,MAAM,0BAA0B,GAC9B,OAAO,4BAA4B,KAAK,QAAQ;QAC9C,CAAC,CAAC,IAAI,CAAC,KAAK,CACR,oBAAoB,GAAG,CAAC,4BAA4B,GAAG,GAAG,CAAC,GAAG,GAAG,CAClE,GAAG,GAAG;QACT,CAAC,CAAC,CAAC,CAAC;IAER,OAAO;QACL,iBAAiB,EAAE,SAAS;QAC5B,eAAe;QACf,aAAa;QACb,sBAAsB;QACtB,oBAAoB;QACpB,oBAAoB;QACpB,0BAA0B;QAC1B,IAAI,EAAE;YACJ,SAAS,EAAE,IAAI;YACf,MAAM,EACJ,uEAAuE;SAC1E;KACF,CAAC;AACJ,CAAC"}
|