@markcolabs/mcp 0.3.0 → 0.4.1

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.
Files changed (115) hide show
  1. package/README.md +126 -186
  2. package/dist/index.d.ts +9 -35
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +56 -284
  5. package/dist/index.js.map +1 -1
  6. package/package.json +15 -13
  7. package/LICENSE-API.md +0 -111
  8. package/dist/disclaimers/ymyl.d.ts +0 -16
  9. package/dist/disclaimers/ymyl.d.ts.map +0 -1
  10. package/dist/disclaimers/ymyl.js +0 -20
  11. package/dist/disclaimers/ymyl.js.map +0 -1
  12. package/dist/engines/compoundInterest.d.ts +0 -75
  13. package/dist/engines/compoundInterest.d.ts.map +0 -1
  14. package/dist/engines/compoundInterest.js +0 -74
  15. package/dist/engines/compoundInterest.js.map +0 -1
  16. package/dist/engines/data/federalTax.d.ts +0 -47
  17. package/dist/engines/data/federalTax.d.ts.map +0 -1
  18. package/dist/engines/data/federalTax.js +0 -111
  19. package/dist/engines/data/federalTax.js.map +0 -1
  20. package/dist/engines/data/irs2026.d.ts +0 -137
  21. package/dist/engines/data/irs2026.d.ts.map +0 -1
  22. package/dist/engines/data/irs2026.js +0 -113
  23. package/dist/engines/data/irs2026.js.map +0 -1
  24. package/dist/engines/data/rmd2026.d.ts +0 -59
  25. package/dist/engines/data/rmd2026.d.ts.map +0 -1
  26. package/dist/engines/data/rmd2026.js +0 -75
  27. package/dist/engines/data/rmd2026.js.map +0 -1
  28. package/dist/engines/data/ssa.d.ts +0 -39
  29. package/dist/engines/data/ssa.d.ts.map +0 -1
  30. package/dist/engines/data/ssa.js +0 -55
  31. package/dist/engines/data/ssa.js.map +0 -1
  32. package/dist/engines/data/stateTax2026.d.ts +0 -114
  33. package/dist/engines/data/stateTax2026.d.ts.map +0 -1
  34. package/dist/engines/data/stateTax2026.js +0 -348
  35. package/dist/engines/data/stateTax2026.js.map +0 -1
  36. package/dist/engines/hsa.d.ts +0 -110
  37. package/dist/engines/hsa.d.ts.map +0 -1
  38. package/dist/engines/hsa.js +0 -83
  39. package/dist/engines/hsa.js.map +0 -1
  40. package/dist/engines/ira.d.ts +0 -115
  41. package/dist/engines/ira.d.ts.map +0 -1
  42. package/dist/engines/ira.js +0 -127
  43. package/dist/engines/ira.js.map +0 -1
  44. package/dist/engines/mortgage.d.ts +0 -70
  45. package/dist/engines/mortgage.d.ts.map +0 -1
  46. package/dist/engines/mortgage.js +0 -60
  47. package/dist/engines/mortgage.js.map +0 -1
  48. package/dist/engines/paycheck.d.ts +0 -128
  49. package/dist/engines/paycheck.d.ts.map +0 -1
  50. package/dist/engines/paycheck.js +0 -142
  51. package/dist/engines/paycheck.js.map +0 -1
  52. package/dist/engines/retirement401k.d.ts +0 -109
  53. package/dist/engines/retirement401k.d.ts.map +0 -1
  54. package/dist/engines/retirement401k.js +0 -130
  55. package/dist/engines/retirement401k.js.map +0 -1
  56. package/dist/engines/rmd.d.ts +0 -107
  57. package/dist/engines/rmd.d.ts.map +0 -1
  58. package/dist/engines/rmd.js +0 -109
  59. package/dist/engines/rmd.js.map +0 -1
  60. package/dist/engines/rothConversion.d.ts +0 -124
  61. package/dist/engines/rothConversion.d.ts.map +0 -1
  62. package/dist/engines/rothConversion.js +0 -145
  63. package/dist/engines/rothConversion.js.map +0 -1
  64. package/dist/engines/socialSecurity.d.ts +0 -63
  65. package/dist/engines/socialSecurity.d.ts.map +0 -1
  66. package/dist/engines/socialSecurity.js +0 -139
  67. package/dist/engines/socialSecurity.js.map +0 -1
  68. package/dist/envelope.d.ts +0 -76
  69. package/dist/envelope.d.ts.map +0 -1
  70. package/dist/envelope.js +0 -34
  71. package/dist/envelope.js.map +0 -1
  72. package/dist/shared/bounds.d.ts +0 -133
  73. package/dist/shared/bounds.d.ts.map +0 -1
  74. package/dist/shared/bounds.js +0 -206
  75. package/dist/shared/bounds.js.map +0 -1
  76. package/dist/tools/compoundInterest.d.ts +0 -48
  77. package/dist/tools/compoundInterest.d.ts.map +0 -1
  78. package/dist/tools/compoundInterest.js +0 -107
  79. package/dist/tools/compoundInterest.js.map +0 -1
  80. package/dist/tools/hsa.d.ts +0 -58
  81. package/dist/tools/hsa.d.ts.map +0 -1
  82. package/dist/tools/hsa.js +0 -129
  83. package/dist/tools/hsa.js.map +0 -1
  84. package/dist/tools/ira.d.ts +0 -55
  85. package/dist/tools/ira.d.ts.map +0 -1
  86. package/dist/tools/ira.js +0 -117
  87. package/dist/tools/ira.js.map +0 -1
  88. package/dist/tools/mortgage.d.ts +0 -51
  89. package/dist/tools/mortgage.d.ts.map +0 -1
  90. package/dist/tools/mortgage.js +0 -112
  91. package/dist/tools/mortgage.js.map +0 -1
  92. package/dist/tools/paycheck.d.ts +0 -61
  93. package/dist/tools/paycheck.d.ts.map +0 -1
  94. package/dist/tools/paycheck.js +0 -135
  95. package/dist/tools/paycheck.js.map +0 -1
  96. package/dist/tools/retirement401k.d.ts +0 -85
  97. package/dist/tools/retirement401k.d.ts.map +0 -1
  98. package/dist/tools/retirement401k.js +0 -141
  99. package/dist/tools/retirement401k.js.map +0 -1
  100. package/dist/tools/rmd.d.ts +0 -60
  101. package/dist/tools/rmd.d.ts.map +0 -1
  102. package/dist/tools/rmd.js +0 -130
  103. package/dist/tools/rmd.js.map +0 -1
  104. package/dist/tools/rothConversion.d.ts +0 -66
  105. package/dist/tools/rothConversion.d.ts.map +0 -1
  106. package/dist/tools/rothConversion.js +0 -141
  107. package/dist/tools/rothConversion.js.map +0 -1
  108. package/dist/tools/socialSecurity.d.ts +0 -51
  109. package/dist/tools/socialSecurity.d.ts.map +0 -1
  110. package/dist/tools/socialSecurity.js +0 -117
  111. package/dist/tools/socialSecurity.js.map +0 -1
  112. package/dist/util/zod-to-json-schema.d.ts +0 -28
  113. package/dist/util/zod-to-json-schema.d.ts.map +0 -1
  114. package/dist/util/zod-to-json-schema.js +0 -98
  115. package/dist/util/zod-to-json-schema.js.map +0 -1
@@ -1,128 +0,0 @@
1
- /**
2
- * Paycheck net-pay engine — lifted from
3
- * site/src/utils/paycheck-tax-engine.js (functions `calculateBracketTax`,
4
- * `calculateFederalWithholding`, `calculateFICA`).
5
- *
6
- * Per ADR-0039 § 5: pure synchronous functions, ENGINE_VERSION constant,
7
- * parity test against the site source as the gate.
8
- *
9
- * ## v0.3.0 changes (S141 Item #5)
10
- *
11
- * Two YMYL-grade corrections vs v1.0.0:
12
- *
13
- * 1. **MCP-AUDIT-011 — State-aware tax estimate.** The v1.0.0 flat 5% state
14
- * estimate is replaced with a state-aware effective-rate lookup using
15
- * marginal-bracket simplification (see `engines/data/stateTax2026.ts`).
16
- * Rates sourced from the Tax Foundation 2026 State Individual Income Tax
17
- * Rates report. No-tax states still return $0.
18
- *
19
- * 2. **MCP-AUDIT-012 — Additional Medicare base.** The 0.9% Additional
20
- * Medicare tax now correctly uses the FICA wages base
21
- * (gross − pre-tax cafeteria-plan deductions: 401k/HSA/dep-care/FSA),
22
- * not raw gross. Matches the IRS § 3101(b)(2) rule.
23
- *
24
- * Engine version bumped 1.0.0 → 1.1.0 (additive: new `state` semantics +
25
- * new result fields). Math output differs in two ways: state tax becomes
26
- * state-correct, and Additional Medicare correctly excludes pre-tax
27
- * deductions. Per ADR-0039 § 5 / ADR-0041 D4a, a math fix is a patch bump
28
- * if not breaking the public surface; we're using a MINOR bump because we
29
- * add new result fields (`stateTaxSource`, `stateTaxNotes`,
30
- * `stateEffectiveRate`).
31
- *
32
- * Math reference (annualized) — v0.3.0:
33
- * federalTaxableIncome = max(0, grossAnnual − preTaxAnnual − stdDeduction)
34
- * federalTax = bracketsLookup(federalTaxableIncome, brackets[filingStatus])
35
- * ficaWages = max(0, grossAnnual − preTaxAnnual) // pre-tax deductions reduce FICA base
36
- * ssTax = min(ficaWages, ssWageBase) * 0.062
37
- * medicare = ficaWages * 0.0145
38
- * addlMed = max(0, ficaWages − addlMedThreshold[filingStatus]) * 0.009
39
- * stateTax = noTaxState ? 0 : federalTaxableIncome * stateEffectiveRate(state, federalTaxableIncome)
40
- * netAnnual = grossAnnual − preTaxAnnual − federalTax − ficaTax − stateTax − postTaxAnnual
41
- * per-paycheck values = annual / payPeriodsPerYear
42
- */
43
- import { type FilingStatus, type PayFrequencyLabel } from "./data/federalTax.js";
44
- /**
45
- * SemVer of the paycheck engine. Per ADR-0039 § 5 (reaffirmed in ADR-0041 Position #4a):
46
- * major bump = math change; minor = additive output; patch = numerical correction.
47
- * NOT bumped for cosmetic refactors.
48
- * - 0.2.0 (v0.1.0 publish): initial port (S136), shipped under out-of-policy package-surface version.
49
- * - 1.0.0 (v0.2.0 publish): one-time reset to align with ADR-0039 § 5 per ADR-0041 D4a.
50
- * Math unchanged.
51
- * - 1.1.0 (v0.3.0 publish, S141 Item #5): state-aware tax (MCP-AUDIT-011) +
52
- * Additional Medicare on FICA wages (MCP-AUDIT-012). Additive output fields:
53
- * stateTaxSource, stateTaxNotes, stateEffectiveRate. Per-state math differs
54
- * vs 1.0.0 for non-no-tax states; Additional Medicare differs for high
55
- * earners with pre-tax deductions.
56
- */
57
- export declare const ENGINE_VERSION = "1.1.0";
58
- /** Inputs to the paycheck net-pay engine. */
59
- export interface PaycheckNetPayInput {
60
- /** Gross annual salary, USD. */
61
- grossAnnualSalary: number;
62
- /** Pay frequency. */
63
- payFrequency: PayFrequencyLabel;
64
- /** Federal filing status (camelCase, matches paycheck engine). */
65
- federalFilingStatus: FilingStatus;
66
- /** Two-letter state code (e.g., "CA", "TX"). */
67
- state: string;
68
- /** Number of dependents claimed. */
69
- dependents: number;
70
- /** Total pre-tax deductions (401k, HSA, FSA, etc.) per year, USD. */
71
- preTaxDeductionsAnnual: number;
72
- /** Total post-tax deductions (Roth contributions, garnishments, etc.) per year, USD. */
73
- postTaxDeductionsAnnual: number;
74
- }
75
- /** Result payload returned by the engine. */
76
- export interface PaycheckNetPayResult {
77
- /** Gross pay per paycheck, USD. */
78
- grossPerPaycheck: number;
79
- /** Federal income-tax withholding per paycheck, USD. */
80
- federalTax: number;
81
- /** Total FICA per paycheck (SS + Medicare + Additional Medicare), USD. */
82
- ficaTax: number;
83
- /** State-tax estimate per paycheck, USD. */
84
- stateTax: number;
85
- /** Net pay per paycheck, USD. */
86
- netPay: number;
87
- /** Number of pay periods per year. */
88
- payPeriodsPerYear: number;
89
- /** Annualized federal tax, USD. */
90
- federalTaxAnnual: number;
91
- /** Annualized FICA, USD. */
92
- ficaTaxAnnual: number;
93
- /** Annualized state tax estimate, USD. */
94
- stateTaxAnnual: number;
95
- /** Annualized net pay, USD. */
96
- netPayAnnual: number;
97
- /** Whether the state has no income tax. */
98
- noStateIncomeTax: boolean;
99
- /**
100
- * v1.1.0 additive — citable source for the state-tax effective rate used.
101
- * Same Tax Foundation 2026 report regardless of state; included for caller
102
- * provenance.
103
- */
104
- stateTaxSource: string;
105
- /**
106
- * v1.1.0 additive — state-specific caveats (e.g., "Excludes NYC local tax",
107
- * "Local municipal EIT NOT included"). Empty string when no caveats apply
108
- * (no-tax states, flat-rate states with no local-tax overlay, etc.).
109
- */
110
- stateTaxNotes: string;
111
- /**
112
- * v1.1.0 additive — the effective rate (decimal, 0.093 = 9.3%) the engine
113
- * applied to taxable income for the state-tax estimate. 0 for no-tax states
114
- * and for state codes not modeled in our table.
115
- */
116
- stateEffectiveRate: number;
117
- }
118
- /**
119
- * Compute net pay (and the annualized + per-paycheck breakdown).
120
- *
121
- * Implementation note: dependents currently has no effect under the simplified
122
- * 2026 federal Percentage Method (the site engine likewise doesn't apply
123
- * dependent credits in the per-paycheck calc). The field is part of the
124
- * contract for forward compatibility (Form W-4 line 3 dependents credit may be
125
- * added in a later engine version).
126
- */
127
- export declare function netPay(input: PaycheckNetPayInput): PaycheckNetPayResult;
128
- //# sourceMappingURL=paycheck.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paycheck.d.ts","sourceRoot":"","sources":["../../src/engines/paycheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAQL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EAEvB,MAAM,sBAAsB,CAAC;AAO9B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,gCAAgC;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qBAAqB;IACrB,YAAY,EAAE,iBAAiB,CAAC;IAChC,kEAAkE;IAClE,mBAAmB,EAAE,YAAY,CAAC;IAClC,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,sBAAsB,EAAE,MAAM,CAAC;IAC/B,wFAAwF;IACxF,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,6CAA6C;AAC7C,MAAM,WAAW,oBAAoB;IACnC,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,4BAA4B;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,cAAc,EAAE,MAAM,CAAC;IACvB,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,gBAAgB,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CA+EvE"}
@@ -1,142 +0,0 @@
1
- /**
2
- * Paycheck net-pay engine — lifted from
3
- * site/src/utils/paycheck-tax-engine.js (functions `calculateBracketTax`,
4
- * `calculateFederalWithholding`, `calculateFICA`).
5
- *
6
- * Per ADR-0039 § 5: pure synchronous functions, ENGINE_VERSION constant,
7
- * parity test against the site source as the gate.
8
- *
9
- * ## v0.3.0 changes (S141 Item #5)
10
- *
11
- * Two YMYL-grade corrections vs v1.0.0:
12
- *
13
- * 1. **MCP-AUDIT-011 — State-aware tax estimate.** The v1.0.0 flat 5% state
14
- * estimate is replaced with a state-aware effective-rate lookup using
15
- * marginal-bracket simplification (see `engines/data/stateTax2026.ts`).
16
- * Rates sourced from the Tax Foundation 2026 State Individual Income Tax
17
- * Rates report. No-tax states still return $0.
18
- *
19
- * 2. **MCP-AUDIT-012 — Additional Medicare base.** The 0.9% Additional
20
- * Medicare tax now correctly uses the FICA wages base
21
- * (gross − pre-tax cafeteria-plan deductions: 401k/HSA/dep-care/FSA),
22
- * not raw gross. Matches the IRS § 3101(b)(2) rule.
23
- *
24
- * Engine version bumped 1.0.0 → 1.1.0 (additive: new `state` semantics +
25
- * new result fields). Math output differs in two ways: state tax becomes
26
- * state-correct, and Additional Medicare correctly excludes pre-tax
27
- * deductions. Per ADR-0039 § 5 / ADR-0041 D4a, a math fix is a patch bump
28
- * if not breaking the public surface; we're using a MINOR bump because we
29
- * add new result fields (`stateTaxSource`, `stateTaxNotes`,
30
- * `stateEffectiveRate`).
31
- *
32
- * Math reference (annualized) — v0.3.0:
33
- * federalTaxableIncome = max(0, grossAnnual − preTaxAnnual − stdDeduction)
34
- * federalTax = bracketsLookup(federalTaxableIncome, brackets[filingStatus])
35
- * ficaWages = max(0, grossAnnual − preTaxAnnual) // pre-tax deductions reduce FICA base
36
- * ssTax = min(ficaWages, ssWageBase) * 0.062
37
- * medicare = ficaWages * 0.0145
38
- * addlMed = max(0, ficaWages − addlMedThreshold[filingStatus]) * 0.009
39
- * stateTax = noTaxState ? 0 : federalTaxableIncome * stateEffectiveRate(state, federalTaxableIncome)
40
- * netAnnual = grossAnnual − preTaxAnnual − federalTax − ficaTax − stateTax − postTaxAnnual
41
- * per-paycheck values = annual / payPeriodsPerYear
42
- */
43
- import { FEDERAL_TAX_BRACKETS_2026, STANDARD_DEDUCTIONS_2026, ADDITIONAL_MEDICARE_THRESHOLDS_2026, FICA_RATES, SS_WAGE_BASE, PAY_PERIODS_PER_YEAR, NO_TAX_STATES, } from "./data/federalTax.js";
44
- import { getStateEffectiveRate, getStateEntry, STATE_TAX_2026_META, } from "./data/stateTax2026.js";
45
- /**
46
- * SemVer of the paycheck engine. Per ADR-0039 § 5 (reaffirmed in ADR-0041 Position #4a):
47
- * major bump = math change; minor = additive output; patch = numerical correction.
48
- * NOT bumped for cosmetic refactors.
49
- * - 0.2.0 (v0.1.0 publish): initial port (S136), shipped under out-of-policy package-surface version.
50
- * - 1.0.0 (v0.2.0 publish): one-time reset to align with ADR-0039 § 5 per ADR-0041 D4a.
51
- * Math unchanged.
52
- * - 1.1.0 (v0.3.0 publish, S141 Item #5): state-aware tax (MCP-AUDIT-011) +
53
- * Additional Medicare on FICA wages (MCP-AUDIT-012). Additive output fields:
54
- * stateTaxSource, stateTaxNotes, stateEffectiveRate. Per-state math differs
55
- * vs 1.0.0 for non-no-tax states; Additional Medicare differs for high
56
- * earners with pre-tax deductions.
57
- */
58
- export const ENGINE_VERSION = "1.1.0";
59
- const ROUND = (v) => Math.round(v * 100) / 100;
60
- /**
61
- * Progressive bracket lookup — verbatim port of site `calculateBracketTax`.
62
- */
63
- function bracketTax(taxableIncome, brackets) {
64
- if (!brackets.length || taxableIncome <= 0)
65
- return 0;
66
- for (let i = brackets.length - 1; i >= 0; i--) {
67
- const b = brackets[i];
68
- if (taxableIncome > b.min) {
69
- const taxableInBracket = taxableIncome - b.min;
70
- return b.baseTax + taxableInBracket * b.rate;
71
- }
72
- }
73
- return 0;
74
- }
75
- /**
76
- * Compute net pay (and the annualized + per-paycheck breakdown).
77
- *
78
- * Implementation note: dependents currently has no effect under the simplified
79
- * 2026 federal Percentage Method (the site engine likewise doesn't apply
80
- * dependent credits in the per-paycheck calc). The field is part of the
81
- * contract for forward compatibility (Form W-4 line 3 dependents credit may be
82
- * added in a later engine version).
83
- */
84
- export function netPay(input) {
85
- const { grossAnnualSalary, payFrequency, federalFilingStatus, state, preTaxDeductionsAnnual, postTaxDeductionsAnnual, } = input;
86
- const periodsPerYear = PAY_PERIODS_PER_YEAR[payFrequency];
87
- // Annual basis after pre-tax deductions (income-tax-reducible).
88
- const adjustedAnnual = Math.max(0, grossAnnualSalary - preTaxDeductionsAnnual);
89
- // Federal: standard deduction → taxable income → bracket lookup.
90
- const stdDeduction = STANDARD_DEDUCTIONS_2026[federalFilingStatus];
91
- const federalTaxable = Math.max(0, adjustedAnnual - stdDeduction);
92
- const federalTaxAnnual = bracketTax(federalTaxable, FEDERAL_TAX_BRACKETS_2026[federalFilingStatus]);
93
- // FICA on gross less pre-tax cafeteria-plan deductions; we conservatively
94
- // apply all pre-tax deductions to FICA since the input doesn't split 401k
95
- // vs cafeteria-plan deductions — matches the more lenient employee view.
96
- const ficaWages = adjustedAnnual;
97
- const ssWageBase = SS_WAGE_BASE[2026] ?? SS_WAGE_BASE[2025];
98
- const ssTaxAnnual = Math.min(ficaWages, ssWageBase) * FICA_RATES.socialSecurityRate;
99
- const medicareAnnual = ficaWages * FICA_RATES.medicareRate;
100
- const addlMedThreshold = ADDITIONAL_MEDICARE_THRESHOLDS_2026[federalFilingStatus];
101
- // MCP-AUDIT-012 fix (v1.1.0): Additional Medicare uses FICA wages base,
102
- // not raw gross. Matches IRS § 3101(b)(2) / Form 8959 rule. Pre-tax
103
- // health/HSA/dep-care deductions DO reduce the Additional Medicare base.
104
- const addlMedAnnual = ficaWages > addlMedThreshold
105
- ? (ficaWages - addlMedThreshold) * FICA_RATES.additionalMedicareRate
106
- : 0;
107
- const ficaTaxAnnual = ssTaxAnnual + medicareAnnual + addlMedAnnual;
108
- // State tax: no-tax states explicit zero; everyone else uses state-aware
109
- // effective-rate lookup (MCP-AUDIT-011 fix, v1.1.0). See stateTax2026.ts.
110
- const stateUpper = state.trim().toUpperCase();
111
- const noStateIncomeTax = NO_TAX_STATES.includes(stateUpper);
112
- const stateEffectiveRate = noStateIncomeTax
113
- ? 0
114
- : getStateEffectiveRate(stateUpper, federalTaxable);
115
- const stateTaxAnnual = federalTaxable * stateEffectiveRate;
116
- const stateEntry = noStateIncomeTax ? undefined : getStateEntry(stateUpper);
117
- const stateTaxNotes = stateEntry?.notes ?? "";
118
- // Net annual + per-paycheck.
119
- const netPayAnnual = grossAnnualSalary -
120
- preTaxDeductionsAnnual -
121
- federalTaxAnnual -
122
- ficaTaxAnnual -
123
- stateTaxAnnual -
124
- postTaxDeductionsAnnual;
125
- return {
126
- grossPerPaycheck: ROUND(grossAnnualSalary / periodsPerYear),
127
- federalTax: ROUND(federalTaxAnnual / periodsPerYear),
128
- ficaTax: ROUND(ficaTaxAnnual / periodsPerYear),
129
- stateTax: ROUND(stateTaxAnnual / periodsPerYear),
130
- netPay: ROUND(netPayAnnual / periodsPerYear),
131
- payPeriodsPerYear: periodsPerYear,
132
- federalTaxAnnual: ROUND(federalTaxAnnual),
133
- ficaTaxAnnual: ROUND(ficaTaxAnnual),
134
- stateTaxAnnual: ROUND(stateTaxAnnual),
135
- netPayAnnual: ROUND(netPayAnnual),
136
- noStateIncomeTax,
137
- stateTaxSource: STATE_TAX_2026_META.source,
138
- stateTaxNotes,
139
- stateEffectiveRate,
140
- };
141
- }
142
- //# sourceMappingURL=paycheck.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paycheck.js","sourceRoot":"","sources":["../../src/engines/paycheck.ts"],"names":[],"mappings":"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"}
@@ -1,109 +0,0 @@
1
- /**
2
- * 401(k) projection engine — lifted from
3
- * site/src/pages/401k-retirement-calculator/401k-retirement-calculator.js
4
- * (functions `calculateEmployerMatch`, `calculateFutureValue`,
5
- * `generateYearlyBreakdown`, `getIRSLimit`, `getCatchUpAmount`,
6
- * `calculate401kResults`).
7
- *
8
- * Per ADR-0039 § 5 (Calc-Engine Lift Pattern):
9
- * - Pure synchronous functions of inputs → results. No DOM, no fetch.
10
- * - ENGINE_VERSION bumps when math changes.
11
- * - Parity tests at packages/mcp/test/parity/retirement401k.test.ts gate this
12
- * engine against the source site calculator JS.
13
- *
14
- * MCP-side enhancement on top of the lift: the kickoff-defined input
15
- * `annualSalaryGrowthPercent` is honored in this engine. The site engine
16
- * applies a *flat* annual contribution; here we step year-by-year so each
17
- * year's employee contribution + employer match scales with the cumulative
18
- * salary growth. When `annualSalaryGrowthPercent === 0` the math is identical
19
- * to the site engine (parity test "happy path" covers this).
20
- *
21
- * Math reference (year-by-year, mirroring the site's Math.pow form when growth=0):
22
- * contrib_year_i = annualSalary * (1 + g)^i * (employeePct/100)
23
- * (capped per IRS limit)
24
- * match_year_i = annualSalary * (1 + g)^i * (matchedPct/100) * (employerMatchPct/100)
25
- * balance_year_i = balance_year_{i-1} * (1 + r) + contrib_year_i + match_year_i
26
- * balance_year_0 = currentBalance
27
- *
28
- * IRS limits: per IRS Notice 2025-67 (2026) — see engines/data/irs2026.ts.
29
- */
30
- /**
31
- * SemVer of the 401(k) projection engine. Per ADR-0039 § 5 (reaffirmed in
32
- * ADR-0041 Position #4a): major bump = math change; minor = additive output;
33
- * patch = numerical correction. NOT bumped for cosmetic refactors.
34
- * - 0.2.0 (v0.1.0 publish): initial port (S136), shipped under out-of-policy package-surface version.
35
- * - 1.0.0 (v0.2.0 publish): one-time reset to align with ADR-0039 § 5 per ADR-0041 D4a.
36
- * Math unchanged.
37
- */
38
- export declare const ENGINE_VERSION = "1.0.0";
39
- /** Inputs to the 401(k) projection engine. */
40
- export interface Retirement401kProjectionInput {
41
- /** Current 401(k) balance, USD. */
42
- currentBalance: number;
43
- /** Current annual gross salary, USD. */
44
- annualSalary: number;
45
- /** Employee contribution as percent of salary (0-100). */
46
- contributionPercent: number;
47
- /**
48
- * Employer match percent (0-100). Example: 50 means employer contributes
49
- * $0.50 for each $1 the employee contributes, up to the match cap.
50
- */
51
- employerMatchPercent: number;
52
- /**
53
- * Cap on how much of the employee's contribution percent the employer
54
- * matches. Example: 6 means the employer matches up to 6% of salary.
55
- */
56
- employerMatchLimitPercent: number;
57
- /** Annual salary growth percent (0-20). 0 mirrors the site engine's flat-salary path. */
58
- annualSalaryGrowthPercent: number;
59
- /** Annual investment return percent (0-20). */
60
- annualReturnPercent: number;
61
- /** Current age (used for catch-up eligibility). */
62
- currentAge: number;
63
- /** Target retirement age (must be > currentAge). */
64
- retirementAge: number;
65
- /**
66
- * Whether to enable catch-up contributions when eligible. Default true:
67
- * if the user's age is in a catch-up window, apply the catch-up cap.
68
- * Mirrors the site `catchUpToggle` form field semantics.
69
- */
70
- catchUpEnabled?: boolean;
71
- }
72
- /** One row of the year-by-year projection table. */
73
- export interface Retirement401kYearRow {
74
- /** Years from start (1..yearsToRetirement). */
75
- year: number;
76
- /** Age at end of this year. */
77
- age: number;
78
- /** Employee contribution this year (after IRS cap), USD. */
79
- employeeContribution: number;
80
- /** Employer match this year, USD. */
81
- employerMatch: number;
82
- /** Investment growth credited this year, USD. */
83
- growth: number;
84
- /** Ending balance for this year, USD. */
85
- endingBalance: number;
86
- }
87
- /** Result payload returned by the engine. */
88
- export interface Retirement401kProjectionResult {
89
- /** Final 401(k) balance at retirement age, USD. */
90
- futureBalance: number;
91
- /** Sum of all employee contributions over the projection, USD. */
92
- totalContributions: number;
93
- /** Sum of all employer match contributions over the projection, USD. */
94
- employerContribTotal: number;
95
- /** futureBalance − (currentBalance + totalContributions + employerContribTotal). */
96
- growthEarned: number;
97
- /** Year-by-year rows from year 1 to year yearsToRetirement. */
98
- yearByYear: Retirement401kYearRow[];
99
- }
100
- /**
101
- * Project a 401(k) balance year by year through retirement.
102
- *
103
- * Uses the same per-year accumulation pattern as the site's
104
- * `generateYearlyBreakdown` / `calculateFutureValue` (compounded annual return,
105
- * end-of-year contributions). Differs from the site only in honoring
106
- * `annualSalaryGrowthPercent` per kickoff input list.
107
- */
108
- export declare function projection(input: Retirement401kProjectionInput): Retirement401kProjectionResult;
109
- //# sourceMappingURL=retirement401k.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"retirement401k.d.ts","sourceRoot":"","sources":["../../src/engines/retirement401k.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,8CAA8C;AAC9C,MAAM,WAAW,6BAA6B;IAC5C,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,yBAAyB,EAAE,MAAM,CAAC;IAClC,yFAAyF;IACzF,yBAAyB,EAAE,MAAM,CAAC;IAClC,+CAA+C;IAC/C,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,oDAAoD;AACpD,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,4DAA4D;IAC5D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,qCAAqC;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,6CAA6C;AAC7C,MAAM,WAAW,8BAA8B;IAC7C,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,UAAU,EAAE,qBAAqB,EAAE,CAAC;CACrC;AA4CD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,6BAA6B,GACnC,8BAA8B,CA2EhC"}
@@ -1,130 +0,0 @@
1
- /**
2
- * 401(k) projection engine — lifted from
3
- * site/src/pages/401k-retirement-calculator/401k-retirement-calculator.js
4
- * (functions `calculateEmployerMatch`, `calculateFutureValue`,
5
- * `generateYearlyBreakdown`, `getIRSLimit`, `getCatchUpAmount`,
6
- * `calculate401kResults`).
7
- *
8
- * Per ADR-0039 § 5 (Calc-Engine Lift Pattern):
9
- * - Pure synchronous functions of inputs → results. No DOM, no fetch.
10
- * - ENGINE_VERSION bumps when math changes.
11
- * - Parity tests at packages/mcp/test/parity/retirement401k.test.ts gate this
12
- * engine against the source site calculator JS.
13
- *
14
- * MCP-side enhancement on top of the lift: the kickoff-defined input
15
- * `annualSalaryGrowthPercent` is honored in this engine. The site engine
16
- * applies a *flat* annual contribution; here we step year-by-year so each
17
- * year's employee contribution + employer match scales with the cumulative
18
- * salary growth. When `annualSalaryGrowthPercent === 0` the math is identical
19
- * to the site engine (parity test "happy path" covers this).
20
- *
21
- * Math reference (year-by-year, mirroring the site's Math.pow form when growth=0):
22
- * contrib_year_i = annualSalary * (1 + g)^i * (employeePct/100)
23
- * (capped per IRS limit)
24
- * match_year_i = annualSalary * (1 + g)^i * (matchedPct/100) * (employerMatchPct/100)
25
- * balance_year_i = balance_year_{i-1} * (1 + r) + contrib_year_i + match_year_i
26
- * balance_year_0 = currentBalance
27
- *
28
- * IRS limits: per IRS Notice 2025-67 (2026) — see engines/data/irs2026.ts.
29
- */
30
- import { LIMITS_401K_2026 } from "./data/irs2026.js";
31
- /**
32
- * SemVer of the 401(k) projection engine. Per ADR-0039 § 5 (reaffirmed in
33
- * ADR-0041 Position #4a): major bump = math change; minor = additive output;
34
- * patch = numerical correction. NOT bumped for cosmetic refactors.
35
- * - 0.2.0 (v0.1.0 publish): initial port (S136), shipped under out-of-policy package-surface version.
36
- * - 1.0.0 (v0.2.0 publish): one-time reset to align with ADR-0039 § 5 per ADR-0041 D4a.
37
- * Math unchanged.
38
- */
39
- export const ENGINE_VERSION = "1.0.0";
40
- const ROUND = (v) => Math.round(v * 100) / 100;
41
- /**
42
- * IRS contribution cap for a given age, mirroring `getIRSLimit` in the site engine.
43
- */
44
- function irsLimitForAge(age, catchUpEnabled) {
45
- if (!catchUpEnabled ||
46
- !Number.isFinite(age) ||
47
- age < LIMITS_401K_2026.catchUpAge) {
48
- return LIMITS_401K_2026.base;
49
- }
50
- if (age >= LIMITS_401K_2026.superCatchUpAgeStart &&
51
- age <= LIMITS_401K_2026.superCatchUpAgeEnd) {
52
- return LIMITS_401K_2026.totalWithSuperCatchUp;
53
- }
54
- return LIMITS_401K_2026.totalWithCatchUp;
55
- }
56
- /**
57
- * Catch-up dollar amount for a given age, mirroring `getCatchUpAmount` in site engine.
58
- */
59
- function catchUpForAge(age, catchUpEnabled) {
60
- if (!catchUpEnabled ||
61
- !Number.isFinite(age) ||
62
- age < LIMITS_401K_2026.catchUpAge) {
63
- return 0;
64
- }
65
- if (age >= LIMITS_401K_2026.superCatchUpAgeStart &&
66
- age <= LIMITS_401K_2026.superCatchUpAgeEnd) {
67
- return LIMITS_401K_2026.superCatchUp;
68
- }
69
- return LIMITS_401K_2026.catchUp;
70
- }
71
- /**
72
- * Project a 401(k) balance year by year through retirement.
73
- *
74
- * Uses the same per-year accumulation pattern as the site's
75
- * `generateYearlyBreakdown` / `calculateFutureValue` (compounded annual return,
76
- * end-of-year contributions). Differs from the site only in honoring
77
- * `annualSalaryGrowthPercent` per kickoff input list.
78
- */
79
- export function projection(input) {
80
- const { currentBalance, annualSalary, contributionPercent, employerMatchPercent, employerMatchLimitPercent, annualSalaryGrowthPercent, annualReturnPercent, currentAge, retirementAge, catchUpEnabled = true, } = input;
81
- const years = Math.max(0, Math.floor(retirementAge - currentAge));
82
- const r = annualReturnPercent / 100;
83
- const g = annualSalaryGrowthPercent / 100;
84
- // matchedPct = min(employee contribution %, employer cap %)
85
- const matchedPct = Math.min(contributionPercent, employerMatchLimitPercent);
86
- let balance = currentBalance;
87
- let totalContributions = 0;
88
- let employerContribTotal = 0;
89
- const rows = [];
90
- for (let i = 1; i <= years; i++) {
91
- const ageThisYear = currentAge + i;
92
- const salaryThisYear = annualSalary * Math.pow(1 + g, i - 1);
93
- // Base employee contribution from salary %, plus catch-up if eligible.
94
- let employeeContrib = salaryThisYear * (contributionPercent / 100) +
95
- catchUpForAge(ageThisYear, catchUpEnabled);
96
- // Cap at IRS limit for this year's age (catch-up windows shift over time).
97
- const cap = irsLimitForAge(ageThisYear, catchUpEnabled);
98
- if (employeeContrib > cap)
99
- employeeContrib = cap;
100
- // Employer match scales with salary, capped by employer-match limit %.
101
- const employerMatch = salaryThisYear *
102
- (matchedPct / 100) *
103
- (employerMatchPercent / 100);
104
- // End-of-year compounding: prior balance grows, then this year's
105
- // contributions land. (Matches site `calculateFutureValue` for flat salary.)
106
- const grownBalance = balance * (1 + r);
107
- const growthThisYear = grownBalance - balance;
108
- balance = grownBalance + employeeContrib + employerMatch;
109
- totalContributions += employeeContrib;
110
- employerContribTotal += employerMatch;
111
- rows.push({
112
- year: i,
113
- age: ageThisYear,
114
- employeeContribution: ROUND(employeeContrib),
115
- employerMatch: ROUND(employerMatch),
116
- growth: ROUND(growthThisYear),
117
- endingBalance: ROUND(balance),
118
- });
119
- }
120
- const principalPlusContribs = currentBalance + totalContributions + employerContribTotal;
121
- const growthEarned = balance - principalPlusContribs;
122
- return {
123
- futureBalance: ROUND(balance),
124
- totalContributions: ROUND(totalContributions),
125
- employerContribTotal: ROUND(employerContribTotal),
126
- growthEarned: ROUND(growthEarned),
127
- yearByYear: rows,
128
- };
129
- }
130
- //# sourceMappingURL=retirement401k.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"retirement401k.js","sourceRoot":"","sources":["../../src/engines/retirement401k.ts"],"names":[],"mappings":"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"}
@@ -1,107 +0,0 @@
1
- /**
2
- * RMD (Required Minimum Distribution) engine — lifted from
3
- * site/src/utils/rmd-engine.js (functions `calculateRMD`,
4
- * `getDistributionPeriod`, `getRMDStartAge`).
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): SINGLE-YEAR RMD distribution-amount
10
- * calculation only. The site calculator's multi-year projection
11
- * (`generateRMDProjection`) and pre-RMD age-projection path are OUT of
12
- * scope for v1 — callers needing year-by-year projections should call the
13
- * tool repeatedly with the projected balance for each year.
14
- *
15
- * Table coverage: ONLY the Uniform Lifetime Table (Pub. 590-B Table III,
16
- * post-2022 version) is implemented, mirroring the site source which uses
17
- * `UNIFORM_LIFETIME_TABLE` exclusively. The Joint Life Expectancy Table
18
- * (Table II, applied when spouse is sole beneficiary AND 10+ years younger)
19
- * is NOT in the site engine and is therefore NOT in this tool — adding it
20
- * here would create a parity gap with the site calculator. The `tableUsed`
21
- * field is always `"uniform-lifetime"` for v1; the union type leaves room
22
- * for `"joint-life-expectancy"` in a future minor bump when the site adds it.
23
- *
24
- * Math reference (per IRC §401(a)(9) + Pub. 590-B):
25
- * distributionPeriod = UNIFORM_LIFETIME_TABLE[ownerAge]
26
- * rmdAmount = accountBalance / distributionPeriod
27
- *
28
- * Missed-RMD penalty (SECURE 2.0 §302, effective 2023+):
29
- * penaltyIfMissed = rmdAmount × 0.25 (default 25% excise tax)
30
- * reduced to 10% if corrected within IRS correction window (typically 2 years)
31
- * (down from 50% pre-SECURE-2.0)
32
- *
33
- * Source: IRS Publication 590-B (Uniform Lifetime Table III, post-2022) +
34
- * SECURE 2.0 Act §107 (RMD age tiers) + §302 (25% excise tax).
35
- * Last verified: 2026-05-27.
36
- */
37
- /**
38
- * SemVer of the RMD 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 rmd-engine.js (S141 Wave 1B).
42
- */
43
- export declare const ENGINE_VERSION = "1.0.0";
44
- /**
45
- * Which IRS RMD distribution-period table was applied. For v1 always
46
- * `"uniform-lifetime"` (mirrors the site source). The `"joint-life-expectancy"`
47
- * variant is reserved for a future minor when the site engine adds Table II.
48
- */
49
- export type RmdTableUsed = "uniform-lifetime" | "joint-life-expectancy";
50
- /** Inputs to the RMD distribution-amount engine. */
51
- export interface RmdDistributionAmountInput {
52
- /** Prior year-end account balance, USD. */
53
- accountBalance: number;
54
- /** Owner's age this calendar year (must be ≥ SECURE 2.0 RMD age, typically 73). */
55
- ownerAge: number;
56
- /**
57
- * Spouse's age (optional). RESERVED FOR FUTURE Joint Life Expectancy Table
58
- * support. v1 ignores this input — the Uniform Lifetime Table is always
59
- * applied (matches site parity). Documented in tool description so callers
60
- * know not to rely on it for v1.
61
- */
62
- spouseAge?: number;
63
- /**
64
- * Whether the spouse is the sole IRA beneficiary (optional). RESERVED FOR
65
- * FUTURE Joint Life Expectancy Table support. v1 ignores this input.
66
- */
67
- isSpouseSoleBeneficiary?: boolean;
68
- }
69
- /** Result payload returned by the engine. */
70
- export interface RmdDistributionAmountResult {
71
- /** Required minimum distribution this year, USD. */
72
- rmdAmount: number;
73
- /** Years (life-expectancy factor from the applied IRS table). */
74
- distributionPeriod: number;
75
- /** Duplicates distributionPeriod under a more semantic name. */
76
- lifeExpectancyFactor: number;
77
- /** Which IRS table was applied. Always `"uniform-lifetime"` for v1. */
78
- tableUsed: RmdTableUsed;
79
- /**
80
- * Default excise tax owed if the RMD is missed (SECURE 2.0 §302, 25%).
81
- * Reduced to 10% if corrected within the IRS correction window (typically
82
- * 2 years) — callers should surface this nuance in the UI; the field
83
- * itself reports the 25% default.
84
- */
85
- penaltyIfMissed: number;
86
- /** Provenance metadata. */
87
- meta: {
88
- /** IRS table edition / tax year. */
89
- tableYear: number;
90
- /** Source authority (IRS publication / SECURE 2.0 citation). */
91
- source: string;
92
- };
93
- }
94
- /**
95
- * Compute the required minimum distribution for the given inputs.
96
- *
97
- * 1-to-1 logic port of site/src/utils/rmd-engine.js `calculateRMD` +
98
- * `getDistributionPeriod` (single-year path; multi-year projection out of
99
- * scope). The site engine clamps lookups to [72, 120]; we additionally
100
- * require ownerAge ≥ 73 (SECURE 2.0 floor for the 1951-1959 cohort, the
101
- * common case in 2026) at the tool boundary via RMD_BOUNDS.
102
- *
103
- * Throws on undefined-period lookup — should be unreachable because bounds
104
- * validation in the tool wrapper rejects out-of-range ages first.
105
- */
106
- export declare function distributionAmount(input: RmdDistributionAmountInput): RmdDistributionAmountResult;
107
- //# sourceMappingURL=rmd.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rmd.d.ts","sourceRoot":"","sources":["../../src/engines/rmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAUH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG,uBAAuB,CAAC;AAExE,oDAAoD;AACpD,MAAM,WAAW,0BAA0B;IACzC,2CAA2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,6CAA6C;AAC7C,MAAM,WAAW,2BAA2B;IAC1C,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,SAAS,EAAE,YAAY,CAAC;IACxB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,IAAI,EAAE;QACJ,oCAAoC;QACpC,SAAS,EAAE,MAAM,CAAC;QAClB,gEAAgE;QAChE,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,0BAA0B,GAChC,2BAA2B,CAyC7B"}