← Back to RetIQ · Features · Manual · Security

RetIQ Financial Validation Report

Independent verification of all financial calculations against authoritative sources

100.0%

pass rate

3649
Total Tests
3649
Passed
0
Failed
165
Categories

Methodology

Every financial calculation in RetIQ's projection engine is tested against authoritative sources: IRS publications and revenue procedures, Social Security Administration actuarial tables, CMS Medicare data, HHS Federal Poverty Level guidelines, ACA Premium Tax Credit tables, and enacted legislation (SECURE 2.0, OBBB Act, ARPA/IRA enhanced subsidies). Tests use exact bracket boundaries, known-answer scenarios from IRS worksheets, and complete lookup tables verified entry-by-entry. Tolerance is $1 for rounding unless otherwise noted.

Authoritative Sources

Federal Income Tax Brackets (2026)

Internal Revenue Service
Source →

Standard Deduction & Senior Additions (2025)

Internal Revenue Service
Source →

Social Security Benefit Taxation (IRS Section 86)

Internal Revenue Service
Source →

Social Security PIA & Benefit Calculation

Social Security Administration
Source →

Required Minimum Distributions

Internal Revenue Service
Source →

Long-Term Capital Gains Tax Rates

Internal Revenue Service
Source →

Medicare IRMAA Surcharges (2025)

Centers for Medicare & Medicaid Services
Source →

Retirement Contribution Limits (2025)

Internal Revenue Service
Source →

ACA Premium Tax Credit

IRS / HHS / CMS
Source →

Pension Enhancements (v2.0)

RetIQ Engine

Test Results by Category

Federal Tax (MFJ) 10/10

Formula
Taxable Income (TI) = Gross Income − Standard Deduction
Tax = Σ [ min(TI, bracket_top) − bracket_bottom ] × rate
    for each bracket where TI > bracket_bottom
IRC §1 • IRS Rev. Proc. 2025-32, §4.01 • OBBB Act P.L. 119-21 §101 • IRS source →
Authority: Internal Revenue Service
Documents:
• IRS Revenue Procedure 2025-32, Section 4.01 — Tax Rate Tables
• One Big Beautiful Bill Act (P.L. 119-21), signed July 4, 2025 — Permanent extension of TCJA brackets
Method: Seven marginal tax brackets verified at exact boundary amounts for both MFJ and Single filing status. Cumulative tax computed manually at each bracket top and compared against engine output.
TestExpectedActualResult
Top of 10% bracket ($24,800)2,4802,480
Top of 12% bracket ($100,800)11,60011,600
Top of 22% bracket ($211,400)35,93235,932
Top of 24% bracket ($403,550)82,04882,048
Top of 32% bracket ($512,450)116,896116,896
Top of 35% bracket ($768,700)206,584206,584
In 37% bracket ($1,000,000)292,165292,165
Zero income00
Mid-bracket $50,0005,5045,504
Mid-bracket $150,00022,42422,424

Federal Tax (Single) 6/6

Formula
Taxable Income (TI) = Gross Income − Standard Deduction
Tax = Σ [ min(TI, bracket_top) − bracket_bottom ] × rate
    for each bracket where TI > bracket_bottom
IRC §1 • IRS Rev. Proc. 2025-32, §4.01 • OBBB Act P.L. 119-21 §101 • IRS source →
Authority: Internal Revenue Service
Documents:
• IRS Revenue Procedure 2025-32, Section 4.01 — Tax Rate Tables
• One Big Beautiful Bill Act (P.L. 119-21), signed July 4, 2025 — Permanent extension of TCJA brackets
Method: Seven marginal tax brackets verified at exact boundary amounts for both MFJ and Single filing status. Cumulative tax computed manually at each bracket top and compared against engine output.
TestExpectedActualResult
Top of 10% bracket ($12,400)1,2401,240
Top of 12% bracket ($50,400)5,8005,800
Top of 22% bracket ($105,700)17,96617,966
Top of 24% bracket ($201,775)41,02441,024
Mid-bracket $75,00011,21211,212
$200,000 income40,59840,598

Standard Deduction 8/8

Formula
Deduction = Base + Senior Addition + OBBB Senior Deduction
OBBB = min($6,000/person, $6,000 − 0.06 × max(0, MAGI − threshold))
Threshold: $150,000 MFJ / $75,000 Single • Phases out at 6% per $1,000
IRC §63(c) • IRS Rev. Proc. 2024-40, §3.01 • OBBB Act P.L. 119-21 §102 • IRS source →
Authority: Internal Revenue Service
Documents:
• IRS Revenue Procedure 2024-40, Section 3.01 — Standard Deduction
• One Big Beautiful Bill Act (P.L. 119-21) Section 102 — Additional Senior Deduction
• IRS Fact Sheet FS-2025-03 — Tax deductions for working Americans and seniors
Method: Base standard deduction ($31,500 MFJ / $15,750 Single), existing senior additions ($1,600/$2,000), and new OBBB senior bonus deduction ($6,000/person with 6% phaseout above $150K MFJ / $75K Single).
TestExpectedActualResult
MFJ base deduction32,20032,200
Single base deduction16,10016,100
Senior additional — MFJ (per person)1,6501,650
Senior additional — Single2,0502,050
OBBB Senior Deduction: $6,000 per person6,0006,000
OBBB phaseout threshold — MFJ150,000150,000
OBBB phaseout threshold — Single75,00075,000
OBBB phaseout rate: 6% ($60 per $1,000 over threshold)0.060.06

OBBB Sunset 5/5

TestExpectedActualResult
In-window: MFJ both 65+ with $80K pension gets $12K OBBB3,4043,404
Post-sunset 2029: MFJ both 65+ loses $12K OBBB deduction4,8444,844
Sunset delta = $12K × 12% bracket = $1,4401,4401,440
In-window: Single 65 with $100K MAGI gets partial OBBB ($4.5K)11,72911,729
Post-sunset: Single 65 with $100K MAGI loses the partial $4.5K990990

Senior Std Ded 5/5

TestExpectedActualResult
Bug-reveal: MFJ primary 60 / spouse 67 in-window gets spouse-only seniors4,3224,322
Bug-reveal: MFJ primary 60 / spouse 67 post-sunset 2030 gets §63(f) only5,0425,042
Regression: MFJ both 65+ in-window unchanged3,4043,404
Regression: MFJ both <65 unchanged (no senior, no OBBB)5,2405,240
Regression: Single 65+ in-window with phase-out unchanged11,72911,729

OBBB Smart Fill (F-166) 3/3

TestExpectedActualResult
In-window MFJ with capGains: Smart Fill produces consistent year output11
Below-threshold MFJ regression: capGains=0 leaves Smart Fill unchanged11
Above-cliff MFJ: capGains pushes AGI past $250K → OBBB fully phased out11

F-167 OBBB window 3/3

TestExpectedActualResult
Year-rows for 2028 and 2029 present in projection11
fedTax > 0 in 2028 (plan exercises tax path)11
fedTax 2028→2029 delta = $6,000 × 12% bracket = $720 (OBBB sunset boundary)720720

Phase C §199A 9/9

TestExpectedActualResult
qbiDeduction is state-independent (sanity, equals $15,367 hand-derived)15,36715,367
PA non-conformer + $100K SE: stateTax = $2,853 (gross-base × 3.07%)2,8532,853
CA non-conformer + $100K SE: stateTax = $5,296 (gross-base through CA brackets)5,2965,296
NJ non-conformer + $100K SE: stateTax = $3,794 (gross-base through NJ brackets)3,7943,794
NY AGI-state gross-base + $100K SE: stateTax = $4,915 (§199A absent below AGI line)4,9154,915
ID conformer + $100K SE: stateTax = $4,111 (§199A flows through, flat 5.3%)4,1114,111
IA conformer + $100K SE: stateTax = $2,948 (§199A flows through, flat 3.8%)2,9482,948
ND conformer + $100K SE: stateTax = $567 (§199A flows through, ND brackets)567567
CO conformer + $100K SE (below $500K threshold): stateTax = $3,413 (§199A flows through, flat 4.4%)3,4133,413

State Tax 89/89

Formula
State Tax = Σ [ min(TI_state, bracket_top) − bracket_bottom ] × rate (same marginal structure as federal)
TI_state = Federal AGI − state-specific exemptions (SS, pension, retirement income) subject to age/income gates
State DOR publications (50 states + DC) • IRC §86 state conformity rules • State-specific retirement income exclusions
Sources: State DOR publications — progressive brackets, SS exemptions with age/income gates, retirement income exclusions. IRC §86 state conformity.
TestExpectedActualResult
CO: above $1M MFJ AGI — §199A subtraction suppressed (F-197)52,80052,800
Florida — no income tax00
Texas — no income tax00
California — progressive brackets on $100K3,2463,246
New York — progressive brackets on $100K (2026 rates)5,0685,068
Maryland — progressive brackets only on $100K (local tax tested separately)4,6984,698
Illinois — flat 4.95% on $100K4,9504,950
Pennsylvania — flat 3.07% on $100K3,0703,070
Nevada — no income tax00
Washington — no income tax00
No state selected — zero tax00
MD: $100K MFJ with 3.2% local rate7,8987,898
MD: local rate 0 = state-only (backward compat)4,6984,698
MD: $100K MFJ age 65 with local + retirement exclusion11
FL: mdLocalTaxRate ignored for non-MD state00
FL: SS+IRA income, no tax00
TX: $200K income, no tax00
WA: any income, no tax00
NH: IRA distribution, no tax00
none: federal only, no state tax00
IL: SS+IRA both fully exempt00
IL: earned income taxable (4.95%)4,9504,950
IL: mixed — wages taxable, IRA exempt2,4752,475
IL: $100K Roth conversion fully exempt00
IL: $50K TAD fully exempt00
IL: mixed wages + conversion (only conversion exempt)4,9504,950
PA: $40K Roth conversion exempt at 60+00
PA: $40K conversion taxable under 601,2281,228
NY: conversion competes with pension for $20K cap3,9883,988
PA: IRA exempt age 60+00
PA: IRA taxable age 58 (3.07%)1,5351,535
PA: SS always exempt (all ages)00
CA: MFJ $80K — progressive brackets2,0462,046
CA: SS exempt, IRA taxable804804
CA: single filer pays more than MFJ same income11
NY: MFJ $100K with $20K pension exclusion3,9883,988
NY: SS exempt from state tax11
KS: SS exempt under $75K AGI11
KS: SS taxable above $75K AGI11
CT: SS exempt under $150K MFJ AGI11
RI: SS exempt under $114,900 AGI11
Invalid state code returns $000
Zero income returns $000
PA age gate: $40K IRA age 58 taxable1,2281,228
PA age gate: $40K IRA age 60 exempt00
NC: flat 3.99% on $100K3,9903,990
IN: flat 2.95% on $100K2,9502,950
KY: flat 3.5% on $100K3,5003,500
MS: flat 4.0% on $100K4,0004,000
ID: flat 5.3% on $100K5,3005,300
GA: flat 5.19% on $100K5,1905,190
CO: flat 4.4% on $100K4,4004,400
UT: flat 4.5% on $100K4,5004,500
OH: $100K MFJ — 2.75% above $26,0502,0342,034
OH: $20K income — below $26,050 threshold, $0 tax00
MT: $60K MFJ — all at 4.7% (below $95K threshold)2,8202,820
MT: $120K MFJ — split bracket5,8785,878
MT: single $60K pays more than MFJ $60K (lower threshold)11
NE: $100K MFJ — three brackets (top rate 4.55%)4,2844,284
OK: $20K MFJ — four-bracket structure (HB2764)471471
SC: $100K MFJ — 2026 brackets (top rate 6.0%)5,3445,344
F-052: MD MFJ $100K, mdLocalTaxRate=3.30 adds $3,3007,9987,998
F-052: MD MFJ $100K, mdLocalTaxRate=3.00 (Montgomery)7,6987,698
F-052: MD MFJ $100K, mdLocalTaxRate=0 yields bracket-only result4,6984,698
F-052: VA $100K MFJ passthrough (no localRate field)5,4935,493
F-052: MD MFJ $30K low income, mdLocalTaxRate=3.302,3632,363
F-052: MD MFJ $250K high income, mdLocalTaxRate=3.3020,57320,573
F-055: NJ MFJ $80K gross, $40K pension, age 65 — Tier 1 (full)630630
F-055: NJ MFJ $110K gross, $40K pension, age 65 — Tier 2 (50%)1,2951,295
F-055: NJ MFJ $130K gross, $40K pension, age 65 — Tier 3 (25%)3,0263,026
F-055: NJ MFJ $160K gross, $40K pension, age 65 — Cliff (0%)6,1506,150
F-055: NJ Single $80K gross, $40K pension, age 65 — Tier 1 Single ($75K max)718718
F-055: NJ Single $130K gross, $40K pension, age 65 — Tier 3 Single (25% × $75K)4,9604,960
F-055: NJ MFJ age 60 (under 62) — exclusion ineligible1,6451,645
F-055: NJ MFJ age 62 just-eligible — full exclusion at $80K630630
F-055: NJ MFJ exactly $100K gross — Tier 1 boundary (100%)1,0501,050
F-055: NJ MFJ exactly $150K gross — Tier 3 boundary (25%, not cliff)4,1314,131
Local rate adds flat charge on state base (NC 3.99% + 1.5% local)5,4905,490
localTaxRate default 0 is a no-op (NC flat 3.99% baseline)3,9903,990
MD ignores generic localTaxRate (no double-count with mdLocalTaxRate)11
Local rate respects exemption base (PA all-retirement at 60+ is $0)00
Override replaces the bracket model (NC 5% on gross)5,0005,000
Override bypasses exemptions and the zero-base early return (PA retiree)2,0002,000
Override (state) and local rate stack (NC 5% + 1% local)6,0006,000
Override null is a no-op (NC bracket model unchanged)3,9903,990
OH earned-base: retiree with no wages, local rate is a no-op1,4841,484
OH earned-base: local rate applies to wages (worker)1,6591,659
Untagged state stays broad-base (NC retiree, contrast with OH)3,9923,992
PA earned-base: local rate applies to wages (worker under 60)2,4422,442

SS Taxation (MFJ) 6/6

Formula
Provisional Income (PI) = AGI + Tax-Exempt Interest + 0.5 × SS Gross
If PI ≤ $32,000 MFJ ($25,000 Single): 0% of SS taxable
If PI between thresholds: min(0.50 × (PI − lower), 0.50 × SS Gross)
If PI > $44,000 MFJ ($34,000 Single): min(0.85 × (PI − upper) + 0.50 × $12,000, 0.85 × SS Gross)
IRC §86 • IRS Pub. 915, Worksheet 1 • IRS Pub. 915 →
Authority: Internal Revenue Service
Documents:
• IRC Section 86 — Social Security and Tier 1 Railroad Retirement Benefits
• IRS Publication 915 (2024) — Social Security and Equivalent Railroad Retirement Benefits
• IRS Publication 915, Worksheet 1 — Figuring Your Taxable Benefits
Method: Three-tier taxation: 0% when combined income below base threshold ($32K MFJ / $25K Single), up to 50% between thresholds, up to 85% above upper threshold ($44K MFJ / $34K Single). Verified with hand calculations matching Pub 915 Worksheet 1.
TestExpectedActualResult
Below base threshold: $20K SS, $10K other → 0% taxable00
At base threshold: $24K SS, $20K other → 0% taxable00
Between thresholds: $30K SS, $25K other → partial4,0004,000
Above upper: $30K SS, $60K other → 85% rule25,50025,500
Very high income: $40K SS, $200K other → 85% cap34,00034,000
Zero SS benefit → zero taxable00

SS Taxation (Single) 3/3

Formula
Provisional Income (PI) = AGI + Tax-Exempt Interest + 0.5 × SS Gross
If PI ≤ $32,000 MFJ ($25,000 Single): 0% of SS taxable
If PI between thresholds: min(0.50 × (PI − lower), 0.50 × SS Gross)
If PI > $44,000 MFJ ($34,000 Single): min(0.85 × (PI − upper) + 0.50 × $12,000, 0.85 × SS Gross)
IRC §86 • IRS Pub. 915, Worksheet 1 • IRS Pub. 915 →
Authority: Internal Revenue Service
Documents:
• IRC Section 86 — Social Security and Tier 1 Railroad Retirement Benefits
• IRS Publication 915 (2024) — Social Security and Equivalent Railroad Retirement Benefits
• IRS Publication 915, Worksheet 1 — Figuring Your Taxable Benefits
Method: Three-tier taxation: 0% when combined income below base threshold ($32K MFJ / $25K Single), up to 50% between thresholds, up to 85% above upper threshold ($44K MFJ / $34K Single). Verified with hand calculations matching Pub 915 Worksheet 1.
TestExpectedActualResult
Below base: $20K SS, $10K other → 0%00
Between thresholds: $24K SS, $20K other → partial3,5003,500
Above upper: $30K SS, $40K other → 85% rule22,35022,350

SS PIA 4/4

Formula
PIA = 90% × min(AIME, $1,226) + 32% × min(AIME − $1,226, $6,165) + 15% × max(0, AIME − $7,391)
AIME = Average Indexed Monthly Earnings (capped at wage base: $176,100 for 2025)
42 U.S.C. §415 • SSA OACT 2025 Bend Points • SSA POMS RS 00605.900 • SSA source →
Authority: Social Security Administration
Documents:
• SSA 2025 Bend Points — Office of the Chief Actuary (OACT)
• SSA POMS RS 00615.003 — Full Retirement Age
• SSA POMS RS 00615.301-304 — Early/Late Claiming Adjustments
• SSA 2025 Contribution and Benefit Base — $176,100
Method: PIA bend points ($1,226 / $7,391 for 2025), replacement rates (90%/32%/15%), wage base cap, FRA table for all birth years 1937-1960+, early claiming reduction (5/9% per month first 36, 5/12% beyond), and delayed retirement credits (8%/year capped at 70).
TestExpectedActualResult
Low earner AIME=$1,000 → PIA=$900900900
Mid earner AIME=$5,000 → PIA≈$2,3462,345.82,345
Max earner AIME=$15,375 → PIA≈$4,3694,369.44,369
Income above wage cap ($200K) capped at $184,5004,3694,369

FRA 16/16

Formula (Full Retirement Age by birth year)
1943-1954: FRA = 66
1955-1959: FRA = 66 + (birthYear - 1954) * 2 months
1960+: FRA = 67
42 U.S.C. §416(l) • SSA full retirement age table
Sources: 42 U.S.C. §416(l) (definition of full retirement age); SSA full retirement age table by year of birth. Applies to both retirement benefits and the earnings test.
TestExpectedActualResult
Born 1937 → FRA 65y 0m780780
Born 1938 → FRA 65y 2m782782
Born 1939 → FRA 65y 4m784784
Born 1940 → FRA 65y 6m786786
Born 1941 → FRA 65y 8m788788
Born 1942 → FRA 65y 10m790790
Born 1943 → FRA 66y 0m792792
Born 1954 → FRA 66y 0m792792
Born 1955 → FRA 66y 2m794794
Born 1956 → FRA 66y 4m796796
Born 1957 → FRA 66y 6m798798
Born 1958 → FRA 66y 8m800800
Born 1959 → FRA 66y 10m802802
Born 1960+ → FRA 67y 0m804804
Born 1975 → FRA 67y 0m804804
Born 1990 → FRA 67y 0m804804

SS Claiming 7/7

Formula (claiming-age adjustments to PIA)
Before FRA: benefit reduced 5/9% per month for first 36 months, then 5/12% per month beyond
After FRA: benefit increased 2/3% per month (8%/year) of delayed retirement credits
Delayed retirement credits stop accruing at age 70.
42 U.S.C. §402(q) (reduction) • §402(w) (delayed credits) • SSA POMS RS 00615
Sources: 42 U.S.C. §402(q) (early-claiming reduction); §402(w) (delayed retirement credits); SSA POMS RS 00615. Engine applies the appropriate adjustment based on claim age relative to FRA.
TestExpectedActualResult
Claim at FRA (67) → 100% of PIA2,0002,000
Claim at 62 (60 months early) → 70% of PIA1,4001,400
Claim at 64 (36 months early) → 80% of PIA1,6001,600
Claim at 65 (24 months early) → ~86.7% of PIA1,7331,733
Claim at 70 (36 months late) → 124% of PIA2,4802,480
Claim at 68 (12 months late) → 108% of PIA2,1602,160
Claim at 72 → same as 70 (DRC capped)2,4802,480

SS Reverse 5/5

TestExpectedActualResult
PIA $3000 → claim 70 → reverse recovers ~$30003,0003,000
PIA $2500 → claim 62 → reverse recovers ~$25002,5002,500
PIA $2000 → claim 67 (FRA) → reverse recovers $2000 exactly2,0002,000
PIA $4000 → claim 65 → reverse recovers ~$40004,0003,999
Zero current monthly returns 000

SS COLA Accumulation 8/8

TestExpectedActualResult
Manual PIA claim at FRA: 5yr pre-claim COLA accumulates39,74739,747
Manual PIA claim at 70: 8yr COLA + 24% DRC52,30352,303
Already collecting: year 0 = entered (no COLA back-application)30,00030,000
Already collecting: year 5 = entered × 1.02^533,12233,122
estimateSS path: 5yr COLA ratio matches 1.02^511,04111,041
Couple manual PIAs: combined y.ss reflects both pre-claim COLAs59,62059,620
Spouse estimateSS path: 5yr COLA ratio matches 1.02^511,04111,041
Cohort-stable manual PIA (birthYear 1980): same COLA accumulation as 1964 cohort39,74739,747

RMD Table 34/34

Formula
RMD = Prior Year-End Account Balance ÷ Distribution Period (age-based divisor)
Divisors from IRS Uniform Lifetime Table III: age 72 → 27.4, age 80 → 20.2, age 90 → 12.2 …
IRC §401(a)(9) • IRS Pub. 590-B, Table III (Uniform Lifetime Table) • SECURE 2.0 Act §107 • IRS Pub. 590-B →
Authority: Internal Revenue Service
Documents:
• IRS Publication 590-B — Distributions from IRAs
• IRS Uniform Lifetime Table (Table III) — updated effective 2022
• SECURE 2.0 Act of 2022, Section 107 — RMD Start Age Changes
Method: All 34 divisors from the Uniform Lifetime Table (ages 72-105) verified to exact decimal. SECURE 2.0 RMD start ages confirmed: 72 (born <=1950), 73 (1951-1959), 75 (1960+).
TestExpectedActualResult
Age 72 divisor = 27.427.427.4
Age 73 divisor = 26.526.526.5
Age 74 divisor = 25.525.525.5
Age 75 divisor = 24.624.624.6
Age 76 divisor = 23.723.723.7
Age 77 divisor = 22.922.922.9
Age 78 divisor = 222222
Age 79 divisor = 21.121.121.1
Age 80 divisor = 20.220.220.2
Age 81 divisor = 19.419.419.4
Age 82 divisor = 18.518.518.5
Age 83 divisor = 17.717.717.7
Age 84 divisor = 16.816.816.8
Age 85 divisor = 161616
Age 86 divisor = 15.215.215.2
Age 87 divisor = 14.414.414.4
Age 88 divisor = 13.713.713.7
Age 89 divisor = 12.912.912.9
Age 90 divisor = 12.212.212.2
Age 91 divisor = 11.511.511.5
Age 92 divisor = 10.810.810.8
Age 93 divisor = 10.110.110.1
Age 94 divisor = 9.59.59.5
Age 95 divisor = 8.98.98.9
Age 96 divisor = 8.48.48.4
Age 97 divisor = 7.87.87.8
Age 98 divisor = 7.37.37.3
Age 99 divisor = 6.86.86.8
Age 100 divisor = 6.46.46.4
Age 101 divisor = 666
Age 102 divisor = 5.65.65.6
Age 103 divisor = 5.25.25.2
Age 104 divisor = 4.94.94.9
Age 105 divisor = 4.64.64.6

RMD Calc 4/4

Formula
RMD = Balance(Dec 31, prior year) ÷ Distribution Period(current age)
Example: $1,000,000 ÷ 26.5 (age 73) = $37,736
IRC §401(a)(9) • IRS Pub. 590-B, Table III • IRS Pub. 590-B →
Authority: Internal Revenue Service
Documents:
• IRS Publication 590-B — Distributions from IRAs
• IRS Uniform Lifetime Table (Table III) — updated effective 2022
• SECURE 2.0 Act of 2022, Section 107 — RMD Start Age Changes
Method: All 34 divisors from the Uniform Lifetime Table (ages 72-105) verified to exact decimal. SECURE 2.0 RMD start ages confirmed: 72 (born <=1950), 73 (1951-1959), 75 (1960+).
TestExpectedActualResult
Age 73, $1M balance → $37,73637,73637,736
Age 80, $1M balance → $49,50549,50549,505
Age 90, $1M balance → $81,96781,96781,967
Age 100, $500K balance → $78,12578,12578,125

RMD Joint Life 13/13

Formula (Joint Life and Last Survivor Expectancy)
Eligibility: ownerAge − spouseAge > 10 AND spouse is sole beneficiary (re-evaluated yearly)
RMD = Prior Year-End Balance ÷ JOINT_LIFE_TABLE[ownerAge][spouseAge]
Fallback: if ineligible (gap ≤ 10, flag off, or spouse deceased), use Uniform Lifetime (Table III)
IRC §401(a)(9) • IRS Pub 590-B Appendix B, Table II • Treas. Reg. §1.401(a)(9)-9(d) • IRS Pub 590-B PDF →
Authority: Internal Revenue Service
Documents:
• IRS Publication 590-B, Appendix B, Table II — Joint and Last Survivor Life Expectancy
• Treasury Regulation §1.401(a)(9)-9(d) — post-2022 divisor tables
• IRC §401(a)(9) — RMD rules
Method: 5 anchor divisors from Pub 590-B Table II verified to exact decimal, including the IRS worked example (owner 75 / spouse 64 = 25.3) and the user-reported 24-year-gap scenario (75 / 51 = 35.8). Boundary cases at exactly 10 years and 11 years verified. Eligibility helper tested for sole-beneficiary flag, spouse age null/zero, and spouse older than owner. 3,234 cells total in the engine; owner ages 72–120, spouse ages 20 through (owner − 11).
TestExpectedActualResult
Table II: owner 75 / spouse 64 = 25.3 (IRS worked example)25.325.3
Table II: owner 73 / spouse 62 = 27.2 (11-yr gap boundary)27.227.2
Table II: owner 75 / spouse 51 = 35.8 (24-yr gap)35.835.8
Table II: owner 100 / spouse 89 = 6.8 (oldest at 11-yr gap)6.86.8
Table II: owner 120 / spouse 109 = 2.0 (table minimum)22
calcRMD uses Table II for 75/51 + sole beneficiary flag27,93327,933
Exactly 10-year gap falls back to Uniform Lifetime40,65040,650
Flag off → Uniform Lifetime even at 24-yr gap40,65040,650
Missing Table II cell falls back to Uniform Lifetime40,65040,650
usesJointLifeTable(75, 51, true) → true (24-yr gap + flag)11
usesJointLifeTable(75, 65, true) → false (exactly 10-yr gap)00
usesJointLifeTable(75, 51, false) → false (flag off)00
usesJointLifeTable(75, 80, true) → false (spouse older)00

RMD Start 5/5

Formula
RMD Start Age = 72 (born ≤ 1950) | 73 (born 1951–1959) | 75 (born ≥ 1960)
SECURE Act of 2019 §114 (age 72) • SECURE 2.0 Act of 2022 §107 (ages 73 and 75) • IRS source →
Authority: Internal Revenue Service
Documents:
• IRS Publication 590-B — Distributions from IRAs
• IRS Uniform Lifetime Table (Table III) — updated effective 2022
• SECURE 2.0 Act of 2022, Section 107 — RMD Start Age Changes
Method: All 34 divisors from the Uniform Lifetime Table (ages 72-105) verified to exact decimal. SECURE 2.0 RMD start ages confirmed: 72 (born <=1950), 73 (1951-1959), 75 (1960+).
TestExpectedActualResult
Born 1950 → RMD starts at 727272
Born 1951 → RMD starts at 737373
Born 1959 → RMD starts at 737373
Born 1960 → RMD starts at 757575
Born 1980 → RMD starts at 757575

NIIT 1/1

Formula (Net Investment Income Tax)
NIIT = 3.8% × min(net_investment_income, MAGI − threshold)
Thresholds (not inflation-adjusted): ,000 MFJ / ,000 Single
Investment income includes capital gains, dividends, interest, royalties, rental.
IRC §1411 • IRS Form 8960
Sources: IRC §1411 (NIIT); IRS Form 8960 (computation). Thresholds are fixed by statute (not indexed). Engine applies NIIT on top of ordinary + CG tax when MAGI exceeds threshold.
TestExpectedActualResult
Tax rate = 3.8%11

IRMAA MAGI 2/2

TestExpectedActualResult
AGI $100K + tax-exempt $5K = $105K105,000105,000
AGI $200K + zero tax-exempt = $200K (regression baseline)200,000200,000

ACA MAGI 3/3

TestExpectedActualResult
AGI $40K + ss $30K + ssTaxable $22K → $48K48,00048,000
AGI $80K + zero SS → $80K (regression baseline)80,00080,000
F-161 hand-computed: AGI $55,350 + ss $30K + ssTaxable $15,350 → ACA MAGI $70K70,00070,000

NIIT MAGI 2/2

TestExpectedActualResult
AGI $300K + foreign earned $0 → $300K300,000300,000
AGI $250K + foreign earned $50K → $300K300,000300,000

F-160 AGI 1/1

TestExpectedActualResult
Couple $200K W2 + $30K 401(k) deferral → year-0 AGI ≈ $170K170,000170,000

F-161 storage 1/1

TestExpectedActualResult
Year output stores ssTaxable < ss for SS-collecting couple11

Tax Brackets 6/6

TestExpectedActualResult
2026 (year-0) MFJ 10% top unchanged: $24,80024,80024,800
2030 MFJ 10% top: $24,800 × 1.03^4 floored = $27,90027,90027,900
2036 MFJ 22% top (10yr): $211,400 × 1.03^10 floored284,100284,100
Top bracket (Infinity) preserved unchanged11
Shared-boundary contract: bracket[N+1].min === bracket[N].max post-index11
inflation=0 invariance: brackets unchanged at year >0201,775201,775

Std Deduction 2/2

TestExpectedActualResult
2026 MFJ year-0: $32,20032,20032,200
2036 MFJ: $32,200 × 1.03^10 floored43,25043,250

Senior Std Deduction 1/1

TestExpectedActualResult
2030 MFJ per-spouse: $1,650 × 1.03^4 floored1,8501,850

OBBB Senior Deduction 4/4

TestExpectedActualResult
2025 base year: $6,000 (year-zero, in-window)6,0006,000
2027 (in-window): $6,000 fixed (no indexing)6,0006,000
2029 (post-sunset): returns 000
2024 (pre-window): returns 000

OBBB Phase-out Threshold 1/1

TestExpectedActualResult
2027 MFJ: $150,000 fixed (no indexing)150,000150,000

CG Breakpoint 2/2

TestExpectedActualResult
2030 MFJ 0% threshold: $98,900 × 1.03^4 floored111,300111,300
2036 Single 0% threshold: $49,450 × 1.03^10 floored66,45066,450

QBI Phase-out 2/2

TestExpectedActualResult
2030 MFJ start: $403,500 × 1.03^4 floored454,100454,100
2036 MFJ end: $553,500 × 1.03^10 floored743,850743,850

Indexing Year-Zero 2/2

TestExpectedActualResult
taxBracketsFor at base year returns same .max as REGS211,400211,400
stdDeductionFor at base year preserves raw value32,20032,200

Indexing Integration 2/2

TestExpectedActualResult
2036 MFJ 22% bracket top > 2026 22% bracket top11
2036 MFJ std deduction > 2026 std deduction11

IRMAA Indexing 16/16

TestExpectedActualResult
2026 (year-0) tier 1 MFJ unchanged: $218,000218,000218,000
2026 (year-0) tier 5 (top) MFJ unchanged: $750,000750,000750,000
inflation=0 returns identical tiers across years274,000274,000
2030 tier 1 MFJ: $218,000 × 1.03^4 round-to-1000245,000245,000
2036 tier 1 MFJ: $218,000 × 1.03^10 round-to-1000293,000293,000
2036 tier 4 MFJ: $410,000 × 1.03^10 round-to-1000551,000551,000
2030 tier 1 Single: $109,000 × 1.03^4 round-to-1000123,000123,000
2027 top tier MFJ stays at $750,000 (frozen pre-2028)750,000750,000
2028 top tier MFJ stays at $750,000 (year-zero for top tier)750,000750,000
2030 top tier MFJ: $750,000 × 1.03^2 round-to-1000796,000796,000
2036 top tier MFJ: $750,000 × 1.03^8 round-to-1000950,000950,000
Tier 0 (magi: 0) baseline preserved across years00
Tier 1 partB surcharge preserved across years3,409.23,409.2
$1,000 round-to-nearest: tier 2 MFJ at 2028291,000291,000
calcIRMAA at 2030 with $230K MFJ uses indexed tier 1 ($245K)2,4352,435
calcIRMAA at 2030 inflation=0 uses 2026 thresholds3,4093,409

IRMAA (MFJ) 12/12

Formula
Surcharge = f(MAGI from 2 years prior, filing status) → 6-tier lookup table
Total Part B Premium = $185.00/mo (base) + IRMAA Part B surcharge
Total Part D Premium = Plan premium + IRMAA Part D surcharge
42 U.S.C. §1395r • CMS 2025 IRMAA Tables • CMS Pub. 100-02, Ch. 15 §40 • CMS source →
Authority: Centers for Medicare & Medicaid Services
Documents:
• CMS 2025 Medicare Parts B and D Income-Related Monthly Adjustment Amounts
• CMS Standard Part B Premium: $185.00/month (2025)
Method: All six IRMAA tiers verified for both MFJ and Single filing status. Part B premiums, Part D surcharges, and MAGI thresholds at each tier. Two-year MAGI lookback implemented.
TestExpectedActualResult
Tier 0: below $218K — Part B annual2,4352,435
Tier 0: below $218K — Part D annual00
Tier 1: $218K–$274K — Part B annual3,4093,409
Tier 1: $218K–$274K — Part D annual174174
Tier 2: $274K–$342K — Part B annual4,8704,870
Tier 2: $274K–$342K — Part D annual450450
Tier 3: $342K–$410K — Part B annual6,3306,330
Tier 3: $342K–$410K — Part D annual725725
Tier 4: $410K–$750K — Part B annual7,7907,790
Tier 4: $410K–$750K — Part D annual1,0001,000
Tier 5: above $750K — Part B annual8,2798,279
Tier 5: above $750K — Part D annual1,0921,092

IRMAA (Single) 3/3

Formula
Surcharge = f(MAGI from 2 years prior, filing status) → 6-tier lookup table
Total Part B Premium = $185.00/mo (base) + IRMAA Part B surcharge
Total Part D Premium = Plan premium + IRMAA Part D surcharge
42 U.S.C. §1395r • CMS 2025 IRMAA Tables • CMS Pub. 100-02, Ch. 15 §40 • CMS source →
Authority: Centers for Medicare & Medicaid Services
Documents:
• CMS 2025 Medicare Parts B and D Income-Related Monthly Adjustment Amounts
• CMS Standard Part B Premium: $185.00/month (2025)
Method: All six IRMAA tiers verified for both MFJ and Single filing status. Part B premiums, Part D surcharges, and MAGI thresholds at each tier. Two-year MAGI lookback implemented.
TestExpectedActualResult
Tier 0: below $109K — Part B annual2,4352,435
Tier 1: $109K–$137K — Part B annual3,4093,409
Tier 5: above $500K — Part B annual8,2798,279

IRMAA 1/1

Formula
Surcharge = f(MAGI from 2 years prior, filing status) → 6-tier lookup table
Total Part B Premium = $185.00/mo (base) + IRMAA Part B surcharge
Total Part D Premium = Plan premium + IRMAA Part D surcharge
42 U.S.C. §1395r • CMS 2025 IRMAA Tables • CMS Pub. 100-02, Ch. 15 §40 • CMS source →
Authority: Centers for Medicare & Medicaid Services
Documents:
• CMS 2025 Medicare Parts B and D Income-Related Monthly Adjustment Amounts
• CMS Standard Part B Premium: $185.00/month (2025)
Method: All six IRMAA tiers verified for both MFJ and Single filing status. Part B premiums, Part D surcharges, and MAGI thresholds at each tier. Two-year MAGI lookback implemented.
TestExpectedActualResult
Base Part B premium = $202.90/month ($2,434.80/year)2,4352,435

Year Object 10/10

TestExpectedActualResult
Couple plan: spAge at year 0 = configured spouseAge6262
Couple plan: spAge increments by year offset6767
Couple plan: primaryDead/spouseDead false while both alive11
Single plan: spAge is null11
Spouse-dies plan: spAge numeric while spouse alive (primary 72)6969
Spouse-dies plan: spAge null after spouse death (primary 75)11
Spouse-dies plan: primaryDead stays false post spouse death11
Primary-dies plan: primaryDead true post primary death11
Primary-dies plan: spAge still numeric (survivor age) post primary death7272
Primary-dies plan: spouseDead stays false while spouse alive11

IRMAA Per-Enrollee 3/3

TestExpectedActualResult
Couple both 65+ in MFJ Tier 1 → IRMAA = 2× per-person surcharge2,2962,296
Couple, only primary 65+ → IRMAA = 1× per-person surcharge1,1481,148
Single filer 65+ in single Tier 1 → IRMAA = 1× per-person surcharge1,1481,148

Medicare/IRMAA Inflation 5/5

TestExpectedActualResult
Post-fix: y.medicareCost + y.irmaa equals authority total at yr=38,2968,296
y.irmaa grows at exactly medicareInflation% nominal year-over-year (same tier)00
y.medicareCost grows at exactly medicareInflation% nominal year-over-year01
Tier 0: y.medicareCost = base × enrollees × (1+m)^yr, y.irmaa = 05,6385,638
Tier 0: y.irmaa = 0 (no surcharge below MFJ Tier 1 threshold)00

Medicare cash flow 3/3

TestExpectedActualResult
Couple both 65+: y.expenses includes Medicare cost (post-65 > pre-65 expenses)11
Single 65+: y.expenses includes 1× Medicare cost11
Pre-65: medicareCost is 0 (no Medicare in expenses)00

F-047 3/3

TestExpectedActualResult
Default Medicare inflation 5%/yr (no param)3,9663,966
Custom Medicare inflation 3%/yr honored3,2723,272
0% Medicare inflation honored (?? not ||)2,4352,435

F-165 IRMAA 5/5

TestExpectedActualResult
Single, priorYearMinus2MAGI=$200K → year 0 surcharge matches Tier 3 per-enrollee from REGS4,6204,620
Single, priorYearMinus2MAGI=$200K → year 0 surcharge > 0 (proxy was 0)11
Single, priorYearMinus2MAGI=0 → year 0 falls to proxy (no surcharge)11
MFJ, priorYearMinus1MAGI alone → year 0 unaffected (no priorYearMinus2 override)11
MFJ both 65+: year 1 surcharge = 2 × per-enrollee Tier surcharge2,2962,296

F-188 IRMAA 5/5

TestExpectedActualResult
Single retired, $150K active stream → year 0 surcharge > 0 (was 0 pre-fix)11
Single retired, $150K active stream → year 0 surcharge matches REGS Tier lookup2,8852,885
Single retired, no incomeStreams → year 0 IRMAA = 0 (Tier 0)11
Single retired, $150K stream startAge=70 (inactive at currentAge=65) → year 0 surcharge = 011
F-165 override precedence — priorYearMinus2MAGI=$50K beats $150K stream proxy11

Contrib Limits 5/5

Formula (2025 contribution limits)
401(k)/403(b)/457(b) employee deferral: ,500 + ,500 catch-up (50+) + ,250 super catch-up (60-63)
IRA (Traditional/Roth): ,000 + ,000 catch-up (50+)
HSA: ,300 self / ,550 family + ,000 catch-up (55+)
IRC §402(g), §414(v), §219, §223 • SECURE 2.0 §109 (super catch-up) • IRS Notice 2024-80
Sources: IRC §402(g) (401(k)); §414(v) (age 50 catch-up); SECURE 2.0 §109 (ages 60-63 enhanced catch-up); §219 (IRA); §223 (HSA); IRS Notice 2024-80 (2025 limits). Engine enforces per-account limits during the contribution phase.
TestExpectedActualResult
401(k) elective deferral: $24,50024,50024,500
IRA contribution limit: $7,5007,5007,500
401(k) catch-up (50–59, 64+): $8,0008,0008,000
SECURE 2.0 enhanced catch-up (60–63): $11,25011,25011,250
IRA catch-up (50+): $1,1001,1001,100

QCD 1/1

Formula (Qualified Charitable Distribution)
QCD = direct transfer from IRA to qualified charity, up to ,000/year (2025)
Counts toward RMD; excluded from AGI/MAGI (vs. itemized charitable deduction which reduces taxable income but keeps MAGI intact).
Eligible at age 70½; inflation-adjusted starting 2024.
IRC §408(d)(8) • SECURE 2.0 Act §307 (indexing) • IRS Rev. Proc. 2024-40
Sources: IRC §408(d)(8) (QCD exclusion); SECURE 2.0 Act §307 (indexed starting 2024); IRS Rev. Proc. 2024-40 (2025 limit K). Engine: QCD reduces RMD-driven taxable withdrawals and MAGI in the same year.
TestExpectedActualResult
Annual limit: $111,000 (2026)111,000111,000

Integration 26/26

TestExpectedActualResult
Projection covers 46 years (age 50–95)4646
Net worth stays positive (no bust)11
Pre-retirement savings accumulate11
RMDs start at age 75 (born 1976)7575
Tax computed for retirement year11
SS benefits start at claim age 676767
Account balances sum to net worth4,736,2804,736,280
Higher income → higher lifetime tax11
Roth conversion increases tax in conversion year11
Roth-first order depletes Roth faster11
California adds state tax vs no-state11
primaryEarned field present in year output11
spouseEarned field present in year output11
primaryEarned + spouseEarned === earned (invariant)180,000180,000
FICA field present in pre-retirement year11
Pre-retirement FICA ≈ 7.65% of gross wages (below SS cap)9,1809,180
Retirement-year FICA = 0 (no wages)00
Non-working spouse: total SS = primary own + spousal floor ($54K)54,00054,000
Low-earning spouse ($700/mo own): total SS top-up to floor ($43,200/yr)43,20043,200
High-earning spouse ($1,200/mo own > floor): no spousal top-up, total $38,40038,40038,400
Spousal benefit = $0 before primary files (primary age 67, files at 70)00
Spousal benefit activates when primary files at 7059,64059,640
spousalTopUp field exists in projection year output11
spousalTopUp value is correct ($18,000 for non-working spouse)18,00018,000
No spousal benefit when spouse not enabled24,00024,000
Spousal benefit stable year-over-year with zero COLA11

Return Rate Independence 5/5

TestExpectedActualResult
netWorth identical when all accounts have explicit rates1,121,9771,121,977
preTax identical across nominalReturn values436,788436,788
roth identical across nominalReturn values685,189685,189
taxable identical across nominalReturn values00
accounts grow at their explicit rates (sanity)11

MC Return Independence 3/3

TestExpectedActualResult
MC netWorth identical despite nominalReturn 5 vs 15744,144744,144
MC preTax identical despite nominalReturn 5 vs 15393,293393,293
MC results differ from deterministic (sanity)11

Edge Case 6/6

TestExpectedActualResult
RMD on $0 balance = $000
RMD at age 110 (beyond table) uses fallback11
SS estimate with $0 income → $0 benefit00
calcTax on negative income → $011
IRMAA at exact $218K MFJ threshold → Tier 111
State tax with invalid code → $000

SS Earnings Test 13/13

Formula (retirement earnings test)
Before FRA year: $1 withheld per $2 earned above annual limit ($23,400 in 2025)
Year of FRA (months before): $1 withheld per $3 earned above higher limit ($62,160 in 2025)
Starting FRA month: no withholding regardless of earnings.
42 U.S.C. §403 • SSA POMS RS 02501.021 • SSA 2025 exempt amounts
Sources: 42 U.S.C. §403 (earnings test); SSA POMS RS 02501.021 (application); SSA 2025 exempt amounts ($23,400 / $62,160). Engine: earnings test logic in src/engine/08-ss-engine.js applies withholding during pre-FRA claiming years.
TestExpectedActualResult
Under FRA: $20K earnings (below $24,480 limit) → $000
Under FRA: $50K earnings → $12,760 withheld12,76012,760
Under FRA: $100K earnings, $16,800 benefit → capped at $16,80016,80016,800
At FRA (age 67, born 1960+): $200K earnings → $000
After FRA (age 70): $200K earnings → $000
Zero earnings → $000
FRA year (66.5): $70K earnings → $1,6131,6131,613
SSDI: exempt from earnings test00
Zero SS benefit → $000
Earnings at exact $24,480 limit → $000
Inflation indexing: 2030 under-FRA limit10,90010,900
Integration: age 62 (working + SS) has withholding11
Integration: age 67 (FRA, retired) no withholding00

F-205 ARF 5/5

TestExpectedActualResult
No withholding control: claim 64, 0 months → $16001,6001,600
Amy's example: claim 64, 18 months withheld → $18001,8001,800
Partial credit: claim 64, 12 months → $17331,7331,733
Over-credit cap: claim 64, 50 months → $2000 (capped)2,0002,000
Beyond-36: claim 62, 12 months → $15001,5001,500

F-205 ARF Integration 3/3

TestExpectedActualResult
Single claim-64: age 64 ssWithheld = 1920019,20019,200
Single claim-64: age 67 ss = 24000 (post-ARF restored)24,00024,000
Already-collecting: age 67 ss = 18000 (no ARF jump)18,00018,000

Wage Base Indexing 6/6

TestExpectedActualResult
2026 baseline → $184,500 unchanged184,500184,500
2030 (4yr forward) → $212,400212,400212,400
2036 (10yr forward) → $262,800262,800262,800
2046 (20yr forward) → $374,400374,400374,400
$150-tie rounding → rounds UP per §430(b)(2)248,100248,100
FICA at 2026 → identical to pre-fix (year-zero invariance)11,43911,439

ACA FPL 5/5

Formula
FPL(size) = $15,650 + $5,500 × (size − 1) for household size ≥ 2
FPL% = MAGI ÷ FPL(household size) × 100
42 U.S.C. §9902(2) • HHS 2025 Poverty Guidelines (48 contiguous states + DC) • HHS source →
Authority: U.S. Department of Health and Human Services
Documents:
• HHS 2025 Federal Poverty Level Guidelines — 48 contiguous states + DC
Method: Base FPL for household sizes 1–4 verified against published guidelines ($15,650 / $21,150 / $26,650 / $32,150). Size 5+ uses incremental $5,500 per additional person. Annual 2% FPL inflation applied for projection years.
TestExpectedActualResult
Household of 1 base FPL = $15,65015,65015,650
Household of 2 base FPL = $21,15021,15021,150
Household of 3 base FPL = $26,65026,65026,650
Household of 4 base FPL = $32,15032,15032,150
Household of 5 base FPL = $37,65037,65037,650

ACA Subsidy 13/13

Formula
Max Contribution = MAGI × Applicable Percentage (AP)
PTC = max(0, Benchmark Premium − Max Contribution)
AP = f(FPL%) via 6-tier table; interpolated within tiers. No cliff through 2025 (ARPA/IRA enhanced rules)
IRC §36B • 26 CFR §1.36B-3 • IRS Rev. Proc. 2024-35 (enhanced 2025) • IRS Rev. Proc. 2025-25 (original 2026+) • IRS source →
Authority: Internal Revenue Service
Documents:
• IRS Rev. Proc. 2024-35 — Enhanced Applicable Percentage Table (2021–2025)
• IRS Rev. Proc. 2025-25 — Original ACA Applicable Percentages (2026+)
• ARPA/IRA — Enhanced PTC removes 400% FPL cliff through 2025
• ACA Section 36B — Premium Tax Credit eligibility (100–400% FPL under original rules)
Method: Applicable percentage verified at each FPL tier boundary under both enhanced (2025) and original (2026+) rules. Linear interpolation within tiers confirmed. Subsidy = benchmark premium minus expected contribution (MAGI × applicable %). Cliff behavior at 400% FPL tested for both rule sets.
TestExpectedActualResult
150% FPL enhanced (2025) → 0% contribution, full subsidy00
200% FPL enhanced (2025) → 2% applicable22
300% FPL enhanced (2025) → 6% applicable66
400% FPL enhanced (2025) → 8.5% applicable8.58.5
500% FPL enhanced (2025) → still eligible (no cliff)11
Below 100% FPL → not eligible for subsidy00
400%+ FPL original (2026) → no subsidy (cliff)00
300% FPL original (2026) → 9.96% applicable9.969.96
130% FPL original (2026) → 2.10% applicable2.12.1
Full subsidy at 150% FPL enhanced = benchmark premium20,00020,000
175% FPL enhanced → 1.0% applicable (interpolation)11
Couple at $44k expenses, 2026 original rules → positive subsidy11
Couple at $44k expenses, 2026 original rules → FPL ≈ 208%208208

ACA SLCSP 2/2

Formula (Estimator)
SLCSP ≈ $7,500 (age-40 base) × 1.04^(age − 40) × 1.05^(years from 2025)
Couple ≈ 1.9× single. Users can override with actual local marketplace quotes.
CMS Marketplace benchmark premium data • Planning estimate only — actual premiums vary by state and plan • CMS source →
Authority: RetIQ Estimator (national average)
Documents:
• CMS Marketplace average benchmark premium data
Method: Second Lowest Cost Silver Plan (SLCSP) estimated from national average ($7,500 base at age 40) with 4% per year age adjustment and 5% annual medical inflation. Couple rate ~1.9× single. Values are planning estimates; users can override with actual local quotes.
TestExpectedActualResult
Age 55 single base → ~$9,0009,0009,000
Age 60 couple > age 55 single11

ACA Actual Plan 8/8

TestExpectedActualResult
No actual plan arg → netPremium = benchmark-based (regression)3,8073,807
actualPlanPremium = 0 → same as benchmark (sentinel)3,8073,807
Gold plan above benchmark → net = plan − full credit5,8075,807
Bronze plan below credit → net premium floored at $000
Bronze plan below credit → subsidy capped at plan premium7,0007,000
Over-cliff ineligible with actual plan → net = actual plan7,0007,000
Over-cliff ineligible, no actual plan → net = benchmark12,00012,000
Below-100%-FPL ineligible with actual plan → net = actual plan7,0007,000

Pension 15/15

Formula
Annual Pension = Base × (1 + COLA)^years_since_start × taxable_pct (for tax purposes)
Survivor Benefit = Pension × survivor_fraction (50% / 75% / 100%) after primary death
IRC §72 (annuity taxation) • Pension COLA and survivor election terms set by plan document — no single federal statute
Authority: RetIQ Engine v2.0
Features:
• Per-pension COLA (independent rate per pension)
• Survivor benefits: single life, joint & 50/75/100%
• Taxable percentage (military disability, after-tax contributions)
Method: Verify pension income starts at correct age, COLA compounds correctly, survivor benefits pay the correct fraction after primary death, taxable percentage reduces tax liability appropriately. Mortality scenarios test single-life (pension stops) vs joint-and-survivor (pension continues at reduced rate).
TestExpectedActualResult
Pension starts at age 65 with $24,000/yr24,00024,000
Pension COLA: $24K at 2% after 5yr ≈ $26,49726,49726,498
Taxable 100%: pensionTaxable = pension24,00024,000
Taxable 60%: pensionTaxable ≈ 60% of pension14,40014,400
Taxable 0%: pensionTaxable = 0 (fully exempt)00
Single-life: pension = 0 after pensioner dies00
Joint & 50%: survivor gets 50% of pension12,00012,000
Joint & 75%: survivor gets 75% of pension18,00018,000
Joint & 100%: survivor gets 100% of pension24,00024,000
J&50% + 60% taxable: survivor taxable = 50%*60%*24000 = 72007,2007,200
Migration shim: legacy pension scalar produces correct income18,00018,000
Two primary pensions sum: 12000 + 18000 = 3000030,00030,000
Staggered start ages: only first pension active at age 6612,00012,000
Staggered start ages: both active at age 6730,00030,000
Mixed-owner two pensions: primary 12000 + spouse 8000 = 2000020,00020,000

Pension Partial Year 11/11

TestExpectedActualResult
Integer startAge=65, cola=0 → full $24K at age 65 (regression)24,00024,000
Integer startAge=65, cola=0 → full $24K at age 70 (regression)24,00024,000
startAge=65.5 → 50% prorated ($12K) at age 6512,00012,000
startAge=65.5 → full $24K at age 6624,00024,000
startAge=65.25 → 75% prorated ($18K) at age 6518,00018,000
startAge=65.75 → 25% prorated ($6K) at age 656,0006,000
startAge=65.5 → $0 at age 64 (before activation)00
Lifetime total: fractional pension = integer total - half-year12,00012,000
Spouse startAge=65.5 → 50% prorated ($6K) at spouse age 656,0006,000
COLA compounds with fractional penYrs (age 70, startAge 65.5, 2% COLA)26,23726,237
taxablePercent applies post-proration (60% of $12K = $7,200)7,2007,200

Additional Income 21/21

TestExpectedActualResult
Other income shows in projection at age 6530,00030,000
$30K additional income increases lifetime tax11
Tax increase is meaningful (>$10K lifetime)11
Default window: other income at retirement age30,00030,000
Default window: other income at end age30,00030,000
Late start (70): no other income at 6500
Late start (70): no other income at 6900
Late start (70): other income begins at 7030,00030,000
Early end (72): other income at 7230,00030,000
Early end (72): no other income at 7300
Pre-retirement start (60): other income while working30,00030,000
Window end (75): last year of other income30,00030,000
After window (76): no other income00
$100K additional income raises IRMAA surcharges11
FillBracket: $50K other income reduces Roth conversion amount11
FillBracket: conversion reduced by ~$50K with other income10
SmartFill: $50K other income reduces Roth conversion11
TargetMAGI: $50K other income reduces Roth conversion11
Stuck state: empty incomeStreams + legacy additionalIncome → other = 000
Legacy plan: incomeStreams undefined + additionalIncome → other = 50005,0005,000
Populated incomeStreams: additionalIncome ignored, other = stream amount12,00012,000

Life Insurance 12/12

Formula
Death Benefit: excluded from gross income; deposited to brokerage at death_age
Term: benefit paid only if death_age < expires_age. Permanent: benefit paid at any death_age.
Premiums: deducted from cash flow while policy is active; stop at death or term expiry.
IRC §101(a) (death benefit exclusion from gross income) • IRC §101 →
Sources: IRC §101 (death benefit exclusion from gross income); engine logic: premium collection, term expiry, death benefit payout to taxable account
TestExpectedActualResult
Term premiums active before expiry (age 74)2,4002,400
Term premiums stop at expiresAge (age 75)00
Term: no benefit if insured outlives term (death 80, expires 75)00
Term: benefit pays when death before expiry (death 72, expires 75)500,000500,000
Permanent: premiums active before death (age 84)5,0005,000
Permanent: premiums stop at death (age 85)00
Permanent: benefit pays at death age 85500,000500,000
Death benefit does NOT inflate MAGI by benefit amount (IRC §101)11
Death benefit increases brokerage balance11
No benefit when no death age configured00
Multiple policies: both pay out at death750,000750,000
Spouse policy: benefit triggers at spouse death300,000300,000

REGS 13/13

Schema validation
REGS = { version, federal, ss, irmaa, aca, retirement_accounts }
federal.brackets_mfj.length === 7, federal.brackets_single.length === 7
irmaa.brackets_mfj.length === 6, aca.pct_enhanced.length === 6
Engine regulatory constants structure (v4.0 schema)
Sources: Engine regulatory constants structure (src/engine/07-regulatory.js). Validates that the aliases (TAX_BRACKETS_MFJ, IRMAA_BRACKETS_MFJ, ACA_PCT_ENHANCED) reference the same underlying REGS objects, preventing silent schema drift after KV updates.
TestExpectedActualResult
REGS object exists11
REGS.version is 202511
REGS has 5 data sections55
federal.brackets_mfj has 7 brackets77
federal.brackets_single has 7 brackets77
irmaa.brackets_mfj has 6 tiers66
aca.pct_enhanced has 6 tiers66
TAX_BRACKETS_MFJ === REGS.federal.brackets_mfj11
IRMAA_BRACKETS_MFJ === REGS.irmaa.brackets_mfj11
ACA_PCT_ENHANCED === REGS.aca.pct_enhanced11
SS_WAGE_BASE matches REGS184,500184,500
CONTRIB_401K matches REGS24,50024,500
STD_DEDUCTION matches REGS32,20032,200

HSA 16/16

Formula
Contribution limit (2025): $4,300 self / $8,550 family + $1,000 catch-up (55+)
Qualified medical withdrawals: tax-free. Non-medical withdrawals after 65: ordinary income (no penalty).
Contributions: above-the-line deduction, reduce AGI. Growth: tax-free.
IRC §223 • IRS Rev. Proc. 2024-25 • IRS Pub 969
Sources: IRC §223 (HSA rules); IRS Rev. Proc. 2024-25 (2025 limits $4,300/$8,550); IRS Pub 969 (HSA treatment, medical withdrawal fraction, age 65 rule). Engine: src/engine/09-engine.js HSA contribution/growth/withdrawal logic.
TestExpectedActualResult
HSA contribution reduces federal taxable income11
HSA contribution does NOT reduce CA state income6,6976,697
HSA contribution DOES reduce OR state income11
HSA balance grows at configured rate tax-free53,00053,000
HSA medical withdrawal at age 60: tax-free00
HSA non-medical withdrawal at age 60: taxed + 20% penalty11
HSA withdrawal at age 67 (100% medical): tax-free00
HSA medical withdrawal at 67: zero MAGI impact00
HSA withdrawal at age 67 (50% medical): 50% taxed16,21816,224
HSA: no RMD generated at any age00
Contribution limits enforced: self, age 56 = $5,400 max5,4005,400
Contribution limits enforced: family, age 58 = $9,750 max9,7509,750
Contributions stop at hsaContributionStopAge11
SSDI early Medicare (age 62) stops HSA contributions11
ACA MAGI reduced by HSA contribution11
Net worth includes HSA balance195,000195,000

Medicare Transition 2/2

TestExpectedActualResult
birthMonth=6 → healthcare ≈ full × 6/12 in transition year6,0006,000
birthMonth=6 → medicareCost ≈ full × 6/12 in transition year1,2181,218

Catch-Up Static 5/5

TestExpectedActualResult
HSA self year 5, age 60, 3% inflation → $6,1016,1016,101
HSA family year 9, age 64, 3% inflation → $12,41712,41712,417
HSA year-zero invariance: self age 56 = $5,400 (regression of Test 10)5,4005,400
IRA cumulative roth at year 5 (age 50 vs 44, 3% inflation) → delta $6,6006,6006,600
IRA year-zero invariance: roth[0] delta = $1,100 (age 50 vs 44)1,1001,100

Inherited IRA 16/16

Formula (post-2019 SECURE 10-year rule)
Forced annual distribution = remaining_balance ÷ years_remaining_in_window
10-year clock starts year of original owner's death; balance must reach zero by year 10.
Excluded from Roth conversion and Tax-Aware Drawdown. Traditional: ordinary income. Roth: tax-free.
SECURE Act 2019 • SECURE 2.0 Act §401 • IRS Pub 590-B
Sources: SECURE Act 2019 — 10-year distribution requirement for non-spouse beneficiaries; IRS Pub 590-B (distribution rules); SECURE 2.0 §401 (final regulations 2024). Engine: pooled post-2019 distribution logic in src/engine/09-engine.js.
TestExpectedActualResult
$0 balance returns null (truthy check)11
$1M at 0% return, 22% bracket → net ~$780K780,000780,000
Balance fully depleted after 10 years00
Year 1 dist at 0% return = balance/10100,000100,000
Higher bracket (24%) yields less net than 22%11
7% growth: total distributed > initial balance11
Post-2019: $100K, 10 yrs left → $10,00010,00010,000
Post-2019: $100K, 1 yr left → full balance100,000100,000
Post-2019: $0 balance → $000
Post-2019: $250K, 5 yrs left → $50,00050,00050,000
Pre-2020 stretch: age 50 yr 1, $1M → $27,62427,624.30927,624
Pre-2020 stretch: age 50 yr 5 (divisor 32.2), $1M → $31,05631,055.90131,056
Pre-2020 stretch: age 65 yr 1, $500K → $21,83421,834.06121,834
Pre-2020 stretch: divisor floor at 1.0 (divisor would go negative)500,000500,000
Distribution never exceeds balance1,0001,000
Unknown regime returns 000

Inherited Acct 13/13

Formula (inherited account integration with plan)
Forced distributions flow through ordinary income → SS taxation, MAGI, IRMAA, NIIT calculations
Balance continues to grow at nominal return between distributions.
Explicitly excluded from Roth conversion math (not eligible for conversion under SECURE).
SECURE Act • IRC §86 (SS taxation) • 42 U.S.C. §1395r (IRMAA)
Sources: SECURE Act (10-year rule); IRC §86 (SS taxation interaction); 42 U.S.C. §1395r (IRMAA MAGI). Engine: inherited distributions integrated with tax and MAGI pipelines in src/engine/09-engine.js.
TestExpectedActualResult
Year 0: regular pretax balance = 500K (untouched)500,000500,000
Year 0: inherited pretax = 450K after first distribution450,000450,000
Year 0: inherited distribution = 50K50,00050,000
Year 9 (age 69): inherited balance = 0 (fully distributed)00
Year 10 (age 70): inherited dist = 0 (nothing left)00
Net worth = sum of all buckets including inherited1,266,1801,266,180
Inherited pretax distributions increase lifetime taxes11
Inherited distributions preserve pretax (less drawdown needed)11
Roth conversion pulls from pretax only (not inherited)460,000460,000
Inherited balance unchanged by Roth conversion (still 450K)450,000450,000
No standard RMD when only inherited pretax exists00
Inherited Roth has lower lifetime tax than inherited traditional11
Inherited Roth depleted by year 900

Inherited Stretch 8/8

Formula (pre-2020 grandfathered stretch + EDB exceptions)
RMD = balance ÷ Single Life Expectancy divisor (IRS Pub 590-B Table I)
Subtract-1 method: divisoryear_n = initial_divisor − (n − 1)
Four regimes: pre-2020 stretch, EDB-disabled, EDB-chronically-ill, EDB-not-more-than-10-yr-younger
SECURE Act §401(a)(9)(H)(ii) (EDB exceptions) • IRC §72(m)(7) • IRC §7702B(c)(2) • IRS Pub 590-B Table I
Sources: SECURE Act §401(a)(9)(H)(ii) (Eligible Designated Beneficiary exceptions to 10-year rule); IRC §72(m)(7) (disabled); IRC §7702B(c)(2) (chronically ill); IRS Pub 590-B Table I (Single Life Expectancy divisors). Engine: per-account stretch IRA logic in src/engine/09-engine.js.
TestExpectedActualResult
Yr 1: age 55, $500K → ~$15,82315,82315,823
Stretch balance adds to netWorth yr 111
Inherited Roth stretch: tax-free distributions never raise tax11
Traditional stretch yr 1 inheritedDist recorded12,65812,658
No regime field: v5.4 pooled behavior preserved9,0919,091
Mixed stretch + post-2019: both distribute29,25229,252
Stretch balance decreases year-over-year at 0% return11
EDB Disabled: yr 1 uses stretch math (100K / 31.6 age 55)3,1653,165

Inherited Per-Account 3/3

TestExpectedActualResult
Two post-2019 with different inheritedYear: independent schedules25,75825,758
Earlier-inherited account depletes first11
Per-account distributionTiming respected (Roth)9,0919,091

CG Harvesting 5/5

Formula (0% capital gains harvesting)
If ordinary_income + projected_gains ≤ 0% CG threshold (2025: $96,700 MFJ / $48,350 single):
  harvest = min(remaining_room, unrealized_gains)
Basis steps up by harvested amount. IRMAA-aware: capped at next Medicare surcharge threshold.
IRC §1(h) (CG brackets) • IRS Rev. Proc. 2024-40 (2025 thresholds)
Sources: IRC §1(h) (preferential capital gains brackets); IRS Rev. Proc. 2024-40 (2025 0% CG threshold). Engine: CG harvesting logic in src/engine/09-engine.js, IRMAA-aware via same logic as Roth Smart Fill.
TestExpectedActualResult
Disabled: zero harvested11
Enabled with basis: harvests in low-income year11
No unrealized gains: zero harvested10
Harvested amount ≤ unrealized gains11
SS-feedback: harvesting raises fedTax via SS provisional income11

F-217 MAGI Components 3/3

TestExpectedActualResult
earnedFederalTaxable exposed on year-row11
taxableWd exposed on year-row11
taxableRothConv exposed on year-row11

TLH 4/4

Formula (tax-loss harvesting)
Realized losses first offset realized capital gains dollar-for-dollar.
Excess losses offset up to $3,000/year of ordinary income (IRC §1211(b)).
Remaining unused losses carry forward indefinitely (IRC §1212(b)).
IRC §1211 • IRC §1212 • IRS Schedule D
Sources: IRC §1211 (loss limitation); IRC §1212(b) (capital loss carryover); IRS Schedule D (Form 1040). Engine: TLH offset and carry-forward in src/engine/09-engine.js.
TestExpectedActualResult
Disabled: zero offset11
$5K losses: offset applied11
$3K ordinary offset when minimal CG11
Carry-forward accumulates across years11

Itemized Deductions 4/4

Formula (itemized vs standard)
Itemized total = SALT (OBBB cap: $40K 2025-2029 phasing down above $500K MAGI, $10K from 2030) + medical above 7.5% AGI + non-QCD charity (≤60% AGI)
Engine uses max(standard + senior + OBBB, itemized) each year.
Senior additions and OBBB senior deduction apply to the standard deduction only.
IRC §63 • IRC §164(b)(6) as amended by OBBB Act P.L. 119-21 • IRC §213 (medical) • IRC §170 (charity) • OBBB Act §102
Sources: IRC §63 (standard vs itemized); IRC §164(b)(6) as amended by OBBB Act P.L. 119-21 (2025); IRC §213 (medical, 7.5% AGI floor); IRC §170 (charitable, 60% AGI cap). Engine: deduction comparison logic in src/engine/09-engine.js.
TestExpectedActualResult
Disabled: uses standard deduction11
SALT $10K + charity $25K beats standard for single filer11
Low SALT, no charity: standard wins for MFJ senior11
Medical 7.5% AGI floor applied correctly11

SALT Cap (OBBB) 6/6

Formula (OBBB SALT cap, year-aware)
2025 base cap = $40,000 (MFJ/Single). Grows 1% per year 2026-2029.
Phase-down: cap reduced by 30% of MAGI excess above $500,000 threshold (also grows 1%/yr).
Floor: cap cannot drop below $10,000 in any year. Reverts to $10,000 flat in 2030+.
OBBB Act P.L. 119-21 (2025) amending IRC §164(b)(6)
Sources: One Big Beautiful Bill Act, P.L. 119-21, enacted July 4, 2025, amending IRC §164(b)(6). Effective 2025-2029 with annual growth, phase-down above $500K MAGI, floor $10K; reverts to TCJA $10K baseline in 2030. Engine: saltCapFor(year, magi) helper in src/engine/07-regulatory.js, called from three sites in src/engine/09-engine.js (main itemized flow, Smart Fill bracket-room calc, and Tax-Aware Drawdown scenario).
TestExpectedActualResult
2025 base cap $40,000 MFJ/Single40,00040,000
2026 cap with 1% growth: $40,40040,40040,400
2030 reversion to $10,000 TCJA baseline10,00010,000
2025 phase-down at MAGI $550K: cap $25,00025,00025,000
2025 phase-down floor at MAGI $700K: cap $10,00010,00010,000
2026 phase-down threshold also grows: MAGI $505K → full cap40,40040,400

DAF Bunching 4/4

Formula (charitable bunching)
Bunch N years of charitable giving into one year (typically 2–3).
In bunch year: itemized deduction dominates standard; claim full bunched amount.
In off years: standard deduction applies; charitable = 0. Total giving unchanged.
IRC §170 (charitable contributions) • DAF regulations (IRS Notice 2006-109)
Sources: IRC §170 (charitable contribution deduction); IRS Notice 2006-109 (DAF rules); IRC §63 (standard vs itemized comparison). Engine: bunching logic in src/engine/09-engine.js routes charitable giving by year.
TestExpectedActualResult
Disabled: charity same every year11
Every-2yr: bunch year has 2x charity11
Every-2yr: off year has zero charity11
Lifetime charity total unchanged vs no bunching11

QLAC 13/13

Formula (Qualified Longevity Annuity Contract)
Purchase from pre-tax account; excluded from RMD base until payments begin.
Max purchase (2026): $210,000 (SECURE 2.0 §202; IRS Notice 2025-67).
Payments begin by age 85; taxed as ordinary income when received.
SECURE 2.0 Act §202 • Treas. Reg. §1.401(a)(9)-6
Sources: SECURE 2.0 Act §202 ($200K cap effective 2024, inflation-adjusted to $210K for 2026 per IRS Notice 2025-67); Treas. Reg. §1.401(a)(9)-6 (QLAC exclusion from RMD base). Engine: QLAC purchase and payment logic in src/engine/09-engine.js.
TestExpectedActualResult
Disabled: no QLAC payout or balance11
Purchase reduces pre-tax balance at purchase age11
RMD lower with QLAC than without11
Payout starts at payoutStartAge as ordinary income11
2026 QLAC limit: $210,000210,000210,000
Engine caps purchase at QLAC_LIMIT when user requests more210,000210,000
Dual disabled: per-owner balances both 011
Primary-only QLAC: primary balance = 200K, spouse balance = 0200,000200,000
Primary-only QLAC: spouse balance unchanged00
Dual QLAC: per-owner balances both = 200K at purchase age400,000400,000
Dual QLAC: qlacBalance backward-compat = primary + spouse00
Dual QLAC: netWorth includes both owners QLAC balance1,604,8571,604,857
Spouse-only QLAC: payout active when spouse reaches payoutStartAge11

Retire Year 11/11

TestExpectedActualResult
Not-passed birthday, retireMonth before birthMonth: partial in yr060,00060,000
Not-passed birthday, retireMonth before birthMonth: zero in yr100
Passed birthday, retireMonth after birthMonth: partial in yr060,00060,000
Passed birthday, retireMonth after birthMonth: zero in yr100
Passed birthday, future retireMonth before birthMonth: full in yr5120,000120,000
Passed birthday, future retireMonth before birthMonth: partial in yr610,00010,000
Passed birthday, future retireMonth before birthMonth: zero in yr700
Not-passed birthday, retireMonth after birthMonth: partial in yr0100,000100,000
Not-passed birthday, retireMonth after birthMonth: zero in yr100
Spouse not-passed birthday, retireMonth before birthMonth: spouse partial in yr060,00060,000
Spouse not-passed birthday, retireMonth before birthMonth: spouse zero in yr100

Roth Conversion Gate 12/12

Formula
preTax = preTaxConvertible + Σ(preTaxGatedTranches[].balance)
Conversion cap = preTaxConvertible   // never the full preTax pool
At year start: for each tranche, if age ≥ unlockAge then convertible ←← tranche (and tranche removed)
Unlock age (primary frame): primaryRetires→retirementAge; spouseRetires→spouseRetirementAge + (currentAge - spouseAge); specificAge→conversionGateAge
Engine: src/engine/09-engine.js (v5.7). Per-account field: account.conversionGate. Spouse-gated coerces to always when spouseEnabled is false.
Sources: Engine logic in src/engine/09-engine.js — split-pool model ensures employer plans without in-service in-plan Roth rollover (IRR) are excluded from conversions until the account's gate opens. RMDs, QCDs, QLAC, and regular withdrawals continue to act on the full pre-tax pool (reducing gated tranches proportionally) — the gate restricts conversions only. Backward compatible: absent conversionGate defaults to 'always'.
TestExpectedActualResult
Before primary retires: conversion caps at IRA (convertible) balance only50,00050,000
After convertible pool drained, conversions stop even with gated balance remaining00
At primaryRetires age, gated 401k unlocks and permits conversion again11
Without gate, conversions continue at age 62 from full pretax pool100,000100,000
Absent conversionGate field = always convertible (backward compat)100,000100,000
Spouse-gated account: still locked when spouse < spouseRetirementAge00
Spouse-gated account: unlocks when spouse reaches spouseRetirementAge11
spouseRetires gate with spouseEnabled=false coerces to always-convertible50,00050,000
specificAge gate: still locked before the specified age00
specificAge gate: unlocks at the specified primary age11
Account identity holds with gated tranches in pool12,64112,641
RMDs draw proportionally from full pool including gated tranches11

F-215 Mixed-Retirement Spouse Deferral 5/5

TestExpectedActualResult
Fix path AGI matches gate path AGI at Y3 (spouse age 60, working)238,000238,000
Fix path rothConv matches gate path rothConv at Y3163,919163,919
Fix path fedTax matches gate path fedTax at Y333,07633,076
Fix path earned matches gate path earned at Y397,63197,631
Pre-retirement year Y1: both paths produce same AGI (gate runs in both)70,29070,290

Dual-Owner RMD 9/9

TestExpectedActualResult
Spouse RMD fires at spAge 73 (projection yr 4)11
Primary RMD = 0 at primary age 69 (below RMD start)00
Total rmd = rmdSpouse when only spouse at RMD age22,48722,487
Spouse RMD amount ≈ balance ÷ 26.5 at age 7322,48722,487
Primary RMD fires at primary age 75 (projection yr 10)11
Spouse RMD still firing at spAge 79 (yr 10)11
Total rmd = rmdPrimary + rmdSpouse when both at RMD age61,81461,814
Invariant: preTax = preTaxPrimary + preTaxSpouse every year11
Opt-out: no owner:spouse account → preTaxSpouse stays 011

Dual-Owner Growth 2/2

TestExpectedActualResult
Primary bucket grows at 5% (per-owner rate)638,141638,141
Spouse bucket grows at 7% (per-owner rate)701,276701,276

Dual-Owner Rollover 2/2

TestExpectedActualResult
Primary death → spouse absorbs pool (preTaxPrimary = 0)00
Spouse death → primary absorbs pool (preTaxSpouse = 0)00

Debt Amortization 11/11

TestExpectedActualResult
Year 1 interest: $200K @ 6% / $1,199.10/mo11,93311,933
Year 1 principal: $200K @ 6% / $1,199.10/mo2,4562,456
Year 1 ending balance: $200K @ 6% / $1,199.10/mo197,544197,544
Year 1 total paid: 12 × $1,199.10/mo14,38914,389
$200K @ 6% / $1,199.10/mo pays off in 30 years3031
Zero-rate loan: $12K @ 0% / $1,000/mo — no interest00
Zero-rate loan: $12K @ 0% / $1,000/mo — paid off in year 111
Zero balance: no payment, no interest00
Payment < monthly interest: balance unchanged200,000200,000
Engine integration: year-1 interest matches helper11,93311,933
Engine integration: year-1 payments matches helper14,38914,389

Relocation Scenario 7/7

TestExpectedActualResult
No relocation params: CA tax non-zero pre-retirement (age 60)11
Move at 70: pre-move year (age 65) uses original state11
Move at 70: post-move year (age 75) uses target state00
Move at 70: cutover year (age 70 itself) uses target state00
Move at currentAge: target state for entire projection00
Move beyond endAge: original state for entire projection11
Pre-retirement move at 55: working year (age 60) uses target state00

Roth Multi-Phase 6/6

TestExpectedActualResult
Empty phases array: identical to absent phases (regression)87,55787,557
Single phase = single-target (full-window 12% phase)1,4071,407
Two-phase: 24% phase produces larger conv than 12% phase11
Gap year (age 68): zero conversion00
Phase boundary: endAge is inclusive (age 67 is in phase 1)11
Outer rc.startAge gates phases: age 60 outside outer window → 000

Account Canon 13/13

TestExpectedActualResult
Legacy type:cash → type:taxable11
Legacy type:cash → subtype:cash11
Legacy type:cash preserves balance65,00065,000
Legacy type:cash preserves returnRate4.54.5
Canonical taxable (no subtype) unchanged11
Type pretax passes through unchanged11
Type roth passes through unchanged11
Type hsa passes through unchanged11
Type inherited-pretax passes through unchanged11
Type inherited-roth passes through unchanged11
canonicalizeAccount is idempotent11
Legacy type:cash without returnRate → default 444
Legacy cash account → engine cash bucket > 0 in year 011

Optimizer Blend 8/8

TestExpectedActualResult
Pre-tax overridden to nominalReturn77
Roth overridden to nominalReturn77
Taxable-investment overridden77
Cash subtype keeps its rate4.54.5
HSA overridden to nominalReturn77
Input array not mutated55
blendedAccountsForOptimizer is idempotent77
Integration: real Roth 10% > blended Roth 7% by year 3011

Divergence 8/8

TestExpectedActualResult
pre-tax 5% vs Roth 9% → shouldWarn:true11
pre-tax 5% vs Roth 9% → divergence == 444
pre-tax 6% vs Roth 7.5% (1.5pp) → shouldWarn:false00
Exactly 2.0pp → shouldWarn:true11
Roth < $10K → shouldWarn:false00
No Roth → shouldWarn:false00
Multi-account pre-tax: weighted avg 5.4%5.45.4
Multi-account divergence 2.6pp → shouldWarn:true11

Tax Payment v6.8 11/11

TestExpectedActualResult
Single retiree FL: tax > 0 in year 111
Single retiree FL: withdrawal exceeds raw expense gap11
Couple MFJ GA: state tax > 0 with $50K taxable pension11
Couple MFJ GA: withdrawal covers fed+state tax bill11
Stable-income retiree: iteration converges from year 1+ (warm-start)11
Year record exposes taxConvergenceFlag as boolean11
NIIT triggers for high-MAGI single via iteration11
SS taxation propagates through iteration (couple MFJ)11
wdOrder honored: roth untouched when earlier sources suffice11
Pre-retirement: taxConvergenceFlag stays false (no iteration)11
Pre-retirement: withdrawal stays 0 (no fillGap path)11

Roth 5-year 7/7

TestExpectedActualResult
Age 58 (yr 3 post-conv): $5K Roth wd → ~$500 penalty (iter cascade adds slight overshoot)530556
Age 60: Roth wd → no penalty (age >59.5 exemption)00
Age 61: Roth wd → no penalty (age + 5-yr both clear)00
Two conversions, $15K wd at age 54 → penalty oldest-first ≈ $1500-$17001,6001,611
Age 56 ($5K wd, 1yr post-conv) → ~$500 penalty530500
Age 60 ($10K wd, 5yr post-conv but >59.5) → no penalty00
No conversions, age 55 Roth wd → no penalty (empty tranches)00

Inherited Roth Backload 7/7

TestExpectedActualResult
Default even-spread: year 2026 has non-zero inherited Roth dist11
Back-load: zero distribution in 2026 (year 4 of 10)11
Back-load: zero distribution in 2032 (year 9 of 10)11
Back-load: full balance distributed in deadline year 203311
Back-load total distributions > even-spread total (extra compounding)11
Back-load: inherited Roth balance = 0 after year 1011
Back-load: lifetime federal tax not increased by inherited Roth timing11

Brokerage Dividend Yield 9/9

TestExpectedActualResult
4% × $1M brokerage = $40K dividend income (year 0)40,00040,000
$40K brokerage QD reflected in MAGI11
Ordinary dividend yield produces higher fed tax than qualified11
Account without dividendYield: zero dividend income00
Multi-account: dividends sum correctly40,00040,000
Mixed qualified + ordinary: brokerageDividendIncome sums both40,00040,000
Untouched brokerage: dividend income grows with balance over 10 years11
Drained brokerage: dividend income shrinks as balance is withdrawn11
No brokerage accounts: zero div income, no NaN11

QD Pipeline Regression 8/8

TestExpectedActualResult
$50K QD stream raises lifetime fed tax11
$50K QD stream reflected in MAGI11
High-MAGI single filer: NIIT > 0 on QD11
$30K QD alone < $48,350 single 0% LTCG threshold → $0 fed tax00
F-037: high-MAGI single with non-QD stream pays NIIT > 011
F-037: nonqualifiedDividends field exposed in year output250,000250,000
F-037: high-MAGI single with ordinary brokerage div pays NIIT > 011
F-037: $250K QD and $250K non-QD produce equal NIIT (same NII base)2,9212,921

Monte Carlo Envelopes 6/6

TestExpectedActualResult
p10/median/p90 returned and equal-length11
p10 <= median <= p90 at EVERY age (the fan-chart property)11
Envelope entry has age/year/retired/netWorth fields11
Final-year p10 < final-year p90 (non-degenerate)11
Final-year envelope spread > year-0 spread (variance grows)11
successRate is integer 0-10011

yearEndAge 6/6

TestExpectedActualResult
born March 1961, projYear 2026 → year-end age 656565
born December 1961, projYear 2026 → year-end age 656565
born January 1962, projYear 2026 → year-end age 646464
born March 1961, projYear 2025 → year-end age 646464
born March 1961, projYear 2030 → year-end age 696969
born 1961, projYear 1961 → age 0 (newborn)00

OBBB senior deduction 6/6

TestExpectedActualResult
F-213: obbbSeniorDeductionFor returns 6000 in 20256,0006,000
F-213: obbbSeniorDeductionFor returns 6000 in 20266,0006,000
F-213: obbbSeniorDeductionFor returns 6000 in 20276,0006,000
F-213: obbbSeniorDeductionFor returns 6000 in 20286,0006,000
F-213: obbbSeniorDeductionFor returns 0 in 2024 (pre-window)00
F-213: obbbSeniorDeductionFor returns 0 in 2029 (post-sunset)00

OBBB phase-out threshold 4/4

TestExpectedActualResult
F-213: obbbPhaseoutThresholdFor MFJ returns 150000 in 2025150,000150,000
F-213: obbbPhaseoutThresholdFor MFJ returns 150000 in 2026150,000150,000
F-213: obbbPhaseoutThresholdFor MFJ returns 150000 in 2027150,000150,000
F-213: obbbPhaseoutThresholdFor MFJ returns 150000 in 2028150,000150,000

F-214 401(k) AGI 4/4

TestExpectedActualResult
Trad-only: AGI = $100k+$80k − $23.5k(Trad) − $15k(Trad) = $141,500141,500141,500
Roth-only: AGI = $100k+$80k = $180,000 (no Box-1 reduction)180,000180,000
Mixed P-Roth/S-Trad: AGI = $100k + ($80k − $15k) = $165,000165,000165,000
Mixed P-Trad/S-Roth: AGI = ($100k − $23.5k) + $80k = $156,500156,500156,500

v6.47 RMD 17/17

TestExpectedActualResult
Legacy default: rmd > 0 in age-74 row11
Legacy default: rmdReinvested > 0 (cash funds gap, RMD reinvests)11
Legacy default: withdrawalForSpending + rmdReinvested === withdrawal127,565127,565
Legacy default: rmdReinvested ≈ rmd (entire RMD reinvested when cash funds gap)78,43178,431
spendFirst Case A (RMD < gap): rmdReinvested === 000
spendFirst Case A: withdrawalForSpending + rmdReinvested === withdrawal42,43542,435
spendFirst Case A: withdrawalForSpending >= rmd (RMD fully went to spending)11
spendFirst Case B (RMD > gap): rmdReinvested > 0 AND < rmd11
spendFirst Case B: withdrawalForSpending + rmdReinvested === withdrawal78,43178,431
spendFirst Case B: rmdReinvested === rmd − (gap-from-rmd)29,29729,297
cash dest: cash[cash-dest] − cash[brok-dest] === rmdReinvested11
cash dest: taxableInv[brok-dest] − taxableInv[cash-dest] === rmdReinvested11
cash dest: total cash + brokerage equals brokerage-dest equivalent11
invariant: withdrawalForSpending + rmdReinvested === withdrawal in EVERY year11
invariant: no violating year in projection (loop diagnostic)-1-1
migration equivalence: missing rmdHandling === explicit legacy default (withdrawal[0])127,565127,565
migration equivalence: missing rmdHandling === explicit legacy default (rmdReinvested[0])78,43178,431

Per-Spouse HC 16/16

TestExpectedActualResult
ACA primary older: healthcare > 0 at primary age 67 (spouse 62)11
ACA primary older: healthcarePhase = split at primary 6711
ACA primary older: healthcarePhase = couple at primary 6311
ACA primary older: healthcare = 0 at primary 71 (both on Medicare)00
ACA primary older: enrollees = 2 at primary 63, 1 at primary 6711
ACA split benchmark < couple benchmark11
ACA spouse older: healthcare > 0 at primary 62 (split phase)11
ACA spouse older: healthcarePhase = couple at primary 5811
Same-age couple regression: healthcare = 0 at 66 (both on Medicare at 65)00
Single filer regression: healthcare = 0 at 6600
SSDI primary: healthcare > 0 at primary 60 (spouse still pre-Medicare)11
SSDI primary: healthcarePhase = split at primary 6011
Retiree plan split: cost at 67 < cost at 63 (single < couple)11
Retiree plan fallback ratio: split cost ≈ annualCost × 0.5 × inflation9,8509,850
spouse_plan: primary on Medicare + spouse still working → $000
survivor: healthcare active for younger spouse before their Medicare11

F-225 per-source W/D 204/204

TestExpectedActualResult
Clarks age 64: per-source sum == withdrawal00
Clarks age 64: wdPretaxRMD == rmd - qcd00
Clarks age 65: per-source sum == withdrawal19,80719,807
Clarks age 65: wdPretaxRMD == rmd - qcd00
Clarks age 66: per-source sum == withdrawal21,17421,174
Clarks age 66: wdPretaxRMD == rmd - qcd00
Clarks age 67: per-source sum == withdrawal59,94659,946
Clarks age 67: wdPretaxRMD == rmd - qcd00
Clarks age 68: per-source sum == withdrawal65,16665,166
Clarks age 68: wdPretaxRMD == rmd - qcd00
Clarks age 69: per-source sum == withdrawal42,53842,538
Clarks age 69: wdPretaxRMD == rmd - qcd00
Clarks age 70: per-source sum == withdrawal44,85744,857
Clarks age 70: wdPretaxRMD == rmd - qcd00
Clarks age 71: per-source sum == withdrawal47,25447,254
Clarks age 71: wdPretaxRMD == rmd - qcd00
Clarks age 72: per-source sum == withdrawal49,75849,758
Clarks age 72: wdPretaxRMD == rmd - qcd00
Clarks age 73: per-source sum == withdrawal52,33752,337
Clarks age 73: wdPretaxRMD == rmd - qcd00
Clarks age 74: per-source sum == withdrawal55,04055,040
Clarks age 74: wdPretaxRMD == rmd - qcd00
Clarks age 75: per-source sum == withdrawal57,84857,848
Clarks age 75: wdPretaxRMD == rmd - qcd52,21852,218
Clarks age 76: per-source sum == withdrawal60,75060,750
Clarks age 76: wdPretaxRMD == rmd - qcd55,38455,384
Clarks age 77: per-source sum == withdrawal63,78763,787
Clarks age 77: wdPretaxRMD == rmd - qcd58,49258,492
Clarks age 78: per-source sum == withdrawal66,93666,936
Clarks age 78: wdPretaxRMD == rmd - qcd62,04562,045
Clarks age 79: per-source sum == withdrawal70,20170,201
Clarks age 79: wdPretaxRMD == rmd - qcd65,82565,825
Clarks age 80: per-source sum == withdrawal73,60873,608
Clarks age 80: wdPretaxRMD == rmd - qcd69,85369,853
Clarks age 81: per-source sum == withdrawal76,85676,856
Clarks age 81: wdPretaxRMD == rmd - qcd73,76573,765
Clarks age 82: per-source sum == withdrawal80,18280,182
Clarks age 82: wdPretaxRMD == rmd - qcd78,32378,323
Clarks age 83: per-source sum == withdrawal83,64983,649
Clarks age 83: wdPretaxRMD == rmd - qcd82,74682,746
Clarks age 84: per-source sum == withdrawal87,95487,954
Clarks age 84: wdPretaxRMD == rmd - qcd87,95487,954
Clarks age 85: per-source sum == withdrawal93,60593,605
Clarks age 85: wdPretaxRMD == rmd - qcd92,93492,934
Clarks age 86: per-source sum == withdrawal100,700100,700
Clarks age 86: wdPretaxRMD == rmd - qcd98,13198,131
Clarks age 87: per-source sum == withdrawal109,386109,386
Clarks age 87: wdPretaxRMD == rmd - qcd103,542103,542
Clarks age 88: per-source sum == withdrawal119,022119,022
Clarks age 88: wdPretaxRMD == rmd - qcd108,364108,364
Clarks age 89: per-source sum == withdrawal130,576130,576
Clarks age 89: wdPretaxRMD == rmd - qcd114,151114,151
Clarks age 90: per-source sum == withdrawal143,101143,101
Clarks age 90: wdPretaxRMD == rmd - qcd119,139119,139
Clarks age 91: per-source sum == withdrawal156,635156,635
Clarks age 91: wdPretaxRMD == rmd - qcd124,153124,153
Clarks age 92: per-source sum == withdrawal171,075171,075
Clarks age 92: wdPretaxRMD == rmd - qcd129,153129,153
Clarks age 93: per-source sum == withdrawal186,250186,250
Clarks age 93: wdPretaxRMD == rmd - qcd134,089134,089
Clarks age 94: per-source sum == withdrawal200,453200,453
Clarks age 94: wdPretaxRMD == rmd - qcd137,434137,434
Clarks age 95: per-source sum == withdrawal213,238213,238
Clarks age 95: wdPretaxRMD == rmd - qcd140,446140,446
Lees age 59: per-source sum == withdrawal00
Lees age 59: wdPretaxRMD == rmd - qcd00
Lees age 60: per-source sum == withdrawal00
Lees age 60: wdPretaxRMD == rmd - qcd00
Lees age 61: per-source sum == withdrawal00
Lees age 61: wdPretaxRMD == rmd - qcd00
Lees age 62: per-source sum == withdrawal48,93948,939
Lees age 62: wdPretaxRMD == rmd - qcd00
Lees age 63: per-source sum == withdrawal52,56752,567
Lees age 63: wdPretaxRMD == rmd - qcd00
Lees age 64: per-source sum == withdrawal149,180149,180
Lees age 64: wdPretaxRMD == rmd - qcd00
Lees age 65: per-source sum == withdrawal149,883149,883
Lees age 65: wdPretaxRMD == rmd - qcd00
Lees age 66: per-source sum == withdrawal153,990153,989
Lees age 66: wdPretaxRMD == rmd - qcd00
Lees age 67: per-source sum == withdrawal144,976144,976
Lees age 67: wdPretaxRMD == rmd - qcd00
Lees age 68: per-source sum == withdrawal149,493149,493
Lees age 68: wdPretaxRMD == rmd - qcd00
Lees age 69: per-source sum == withdrawal120,869120,869
Lees age 69: wdPretaxRMD == rmd - qcd00
Lees age 70: per-source sum == withdrawal39,60439,604
Lees age 70: wdPretaxRMD == rmd - qcd00
Lees age 71: per-source sum == withdrawal41,86441,864
Lees age 71: wdPretaxRMD == rmd - qcd00
Lees age 72: per-source sum == withdrawal44,21944,219
Lees age 72: wdPretaxRMD == rmd - qcd00
Lees age 73: per-source sum == withdrawal46,67146,671
Lees age 73: wdPretaxRMD == rmd - qcd00
Lees age 74: per-source sum == withdrawal49,22449,224
Lees age 74: wdPretaxRMD == rmd - qcd00
Lees age 75: per-source sum == withdrawal51,88451,884
Lees age 75: wdPretaxRMD == rmd - qcd00
Lees age 76: per-source sum == withdrawal54,65354,653
Lees age 76: wdPretaxRMD == rmd - qcd00
Lees age 77: per-source sum == withdrawal57,53557,535
Lees age 77: wdPretaxRMD == rmd - qcd00
Lees age 78: per-source sum == withdrawal60,53560,535
Lees age 78: wdPretaxRMD == rmd - qcd00
Lees age 79: per-source sum == withdrawal63,65963,659
Lees age 79: wdPretaxRMD == rmd - qcd00
Lees age 80: per-source sum == withdrawal66,90966,909
Lees age 80: wdPretaxRMD == rmd - qcd00
Lees age 81: per-source sum == withdrawal70,29170,291
Lees age 81: wdPretaxRMD == rmd - qcd00
Lees age 82: per-source sum == withdrawal73,81073,810
Lees age 82: wdPretaxRMD == rmd - qcd00
Lees age 83: per-source sum == withdrawal77,47277,472
Lees age 83: wdPretaxRMD == rmd - qcd00
Lees age 84: per-source sum == withdrawal81,28281,282
Lees age 84: wdPretaxRMD == rmd - qcd00
Lees age 85: per-source sum == withdrawal85,24585,245
Lees age 85: wdPretaxRMD == rmd - qcd00
Lees age 86: per-source sum == withdrawal89,36689,366
Lees age 86: wdPretaxRMD == rmd - qcd00
Lees age 87: per-source sum == withdrawal93,65493,654
Lees age 87: wdPretaxRMD == rmd - qcd00
Lees age 88: per-source sum == withdrawal98,11498,114
Lees age 88: wdPretaxRMD == rmd - qcd00
Lees age 89: per-source sum == withdrawal102,751102,751
Lees age 89: wdPretaxRMD == rmd - qcd00
Lees age 90: per-source sum == withdrawal107,573107,573
Lees age 90: wdPretaxRMD == rmd - qcd00
Lees age 91: per-source sum == withdrawal112,588112,588
Lees age 91: wdPretaxRMD == rmd - qcd00
Lees age 92: per-source sum == withdrawal117,803117,803
Lees age 92: wdPretaxRMD == rmd - qcd00
Lees age 93: per-source sum == withdrawal123,223123,223
Lees age 93: wdPretaxRMD == rmd - qcd00
Lees age 94: per-source sum == withdrawal128,859128,859
Lees age 94: wdPretaxRMD == rmd - qcd00
Lees age 95: per-source sum == withdrawal134,718134,718
Lees age 95: wdPretaxRMD == rmd - qcd00
Washingtons age 63: per-source sum == withdrawal00
Washingtons age 63: wdPretaxRMD == rmd - qcd00
Washingtons age 64: per-source sum == withdrawal00
Washingtons age 64: wdPretaxRMD == rmd - qcd00
Washingtons age 65: per-source sum == withdrawal19,09519,095
Washingtons age 65: wdPretaxRMD == rmd - qcd00
Washingtons age 66: per-source sum == withdrawal22,19922,199
Washingtons age 66: wdPretaxRMD == rmd - qcd00
Washingtons age 67: per-source sum == withdrawal90,54490,544
Washingtons age 67: wdPretaxRMD == rmd - qcd00
Washingtons age 68: per-source sum == withdrawal95,00595,005
Washingtons age 68: wdPretaxRMD == rmd - qcd00
Washingtons age 69: per-source sum == withdrawal74,87674,876
Washingtons age 69: wdPretaxRMD == rmd - qcd00
Washingtons age 70: per-source sum == withdrawal28,52728,527
Washingtons age 70: wdPretaxRMD == rmd - qcd00
Washingtons age 71: per-source sum == withdrawal30,01030,010
Washingtons age 71: wdPretaxRMD == rmd - qcd00
Washingtons age 72: per-source sum == withdrawal31,55531,555
Washingtons age 72: wdPretaxRMD == rmd - qcd00
Washingtons age 73: per-source sum == withdrawal21,43821,438
Washingtons age 73: wdPretaxRMD == rmd - qcd00
Washingtons age 74: per-source sum == withdrawal11,21011,210
Washingtons age 74: wdPretaxRMD == rmd - qcd00
Washingtons age 75: per-source sum == withdrawal107,168107,168
Washingtons age 75: wdPretaxRMD == rmd - qcd90,40890,408
Washingtons age 76: per-source sum == withdrawal115,732115,732
Washingtons age 76: wdPretaxRMD == rmd - qcd96,32996,329
Washingtons age 77: per-source sum == withdrawal124,283124,283
Washingtons age 77: wdPretaxRMD == rmd - qcd102,172102,172
Washingtons age 78: per-source sum == withdrawal133,941133,941
Washingtons age 78: wdPretaxRMD == rmd - qcd108,827108,827
Washingtons age 79: per-source sum == withdrawal144,213144,213
Washingtons age 79: wdPretaxRMD == rmd - qcd115,893115,893
Washingtons age 80: per-source sum == withdrawal155,237155,237
Washingtons age 80: wdPretaxRMD == rmd - qcd123,391123,391
Washingtons age 81: per-source sum == withdrawal166,379166,379
Washingtons age 81: wdPretaxRMD == rmd - qcd130,667130,667
Washingtons age 82: per-source sum == withdrawal494,293494,293
Washingtons age 82: wdPretaxRMD == rmd - qcd139,059139,059
Washingtons age 83: per-source sum == withdrawal521,964521,964
Washingtons age 83: wdPretaxRMD == rmd - qcd147,111147,111
Washingtons age 84: per-source sum == withdrawal559,472559,472
Washingtons age 84: wdPretaxRMD == rmd - qcd156,472156,472
Washingtons age 85: per-source sum == withdrawal432,517432,517
Washingtons age 85: wdPretaxRMD == rmd - qcd165,332165,332
Washingtons age 86: per-source sum == withdrawal170,118170,118
Washingtons age 86: wdPretaxRMD == rmd - qcd170,118170,118
Washingtons age 87: per-source sum == withdrawal266,664266,664
Washingtons age 87: wdPretaxRMD == rmd - qcd179,498179,498
Washingtons age 88: per-source sum == withdrawal271,567271,567
Washingtons age 88: wdPretaxRMD == rmd - qcd187,857187,857
Washingtons age 89: per-source sum == withdrawal287,183287,183
Washingtons age 89: wdPretaxRMD == rmd - qcd197,891197,891
Washingtons age 90: per-source sum == withdrawal301,093301,093
Washingtons age 90: wdPretaxRMD == rmd - qcd206,536206,536
Washingtons age 91: per-source sum == withdrawal315,201315,201
Washingtons age 91: wdPretaxRMD == rmd - qcd215,229215,229
Washingtons age 92: per-source sum == withdrawal329,413329,413
Washingtons age 92: wdPretaxRMD == rmd - qcd223,898223,898
Washingtons age 93: per-source sum == withdrawal343,579343,579
Washingtons age 93: wdPretaxRMD == rmd - qcd232,455232,455
Washingtons age 94: per-source sum == withdrawal354,318354,318
Washingtons age 94: wdPretaxRMD == rmd - qcd238,254238,254
Washingtons age 95: per-source sum == withdrawal364,456364,456
Washingtons age 95: wdPretaxRMD == rmd - qcd243,474243,474

Roth Optimizer Hang 3/3

TestExpectedActualResult
Already-retired plan: projection length matches age range2929
Past startAge (62) for 67-year-old: engine does not throw00
Long conversion window (67-95, $1M pretax): non-zero total conversions11

F-219 T1-T6 6/6

TestExpectedActualResult
T1: primary transition, spouse on ACA, other source22,33522,335
T2: primary transition, spouse on Medicare via SSDI3,1913,191
T3: spouse transition, primary still pre-Medicare23,42823,428
T4: spouse transition, primary on Medicare (Srini age 71)8,5528,552
T5 (regression): single transition unchanged8,6828,682
T6 (regression): both transition same year, other source14,35814,358

Brief 1B 8/8

TestExpectedActualResult
Test A: mixed over-routing — total = 55000 (no over-allocation)55,00055,000
Test B: routed-routed clamp — savings conserved at 3000030,00030,000
Test B: routed-routed clamp — spouse pre-tax ≈ 1230812,30812,308
Test C: no-shortfall — savings === 70000 (savRatio=1 guard)70,00070,000
Test C: no-shortfall — spouse pre-tax === 16000 (returns/balance guard)16,00016,000
Test C: no-shortfall — brokerage === 31000 (returns/balance guard)31,00031,000
Test D: no-limits block — savings conserved at 4000040,00040,000
Test D: no-limits block — spouse pre-tax ≈ 1727317,27317,273

Release 2 7/7

TestExpectedActualResult
Percent mode: 10% of $100K income → $10,000 deferral (year 0)10,00010,000
Percent mode tracks income: $10,000 deferral at year 0 (growth ×1)10,00010,000
Percent mode tracks income: cumulative preTax $31,525 at year 231,52531,525
Percent 10% of $100K ≡ dollar $10,000 — preTax identical every year77
Percent mode §402(g) clamp: 90% of $200K clamps identically to dollar $180K24,50024,500
Percent mode §402(g) clamp: clamped deferral is below the raw $180,000 want11
Spouse percent mode: 10% of $60K spouse income ≡ dollar $6,000 (own income, not household)77

Birth-Month Retirement 10/10

TestExpectedActualResult
Flag false is byte-identical to flag absent (migration safety)4141
retireMonth < birthMonth shifts the retirement year +1 (born March, retire January)4141
January birth produces no shift (retireMonth 0 < birthMonth 0 is false)4141
retireMonth on or after birthMonth produces no shift (born March, retire June)4141
Flag on: the age-65 row is still a working year (not retired)00
Flag on: the age-66 row is retired11
Flag off: the age-65 row is retired (bare age-counter, unchanged behavior)11
Partial-year proration rides the shifted year (equivalence)4141
Shifted partial year: age-66 earned is 3/12 of the age-65 full year120,000120,000
Spouse shift mirrors the primary path (spouse born July, retire January)4141

One-Time Expense 5/5

TestExpectedActualResult
TC1: single event at age 60 surfaces as oneTimeExpense=3000030,00030,000
TC1: another in-range row (age 70) has oneTimeExpense=000
TC2: two events at age 70 sum to oneTimeExpense=3500035,00035,000
TC3: empty oneTimeExpenses produces oneTimeExpense=0 on every row00
TC4: one-time expense does not leak into y.expenses in the spend year92,74292,742

Cliff-Aware Fill 7/7

TestExpectedActualResult
ACA cap binds — cliffFill converts strictly less than smartFill11
ACA cap binds — cliffFill still converts > 011
ACA cap inert post-Medicare — equals smartFill11
ACA cap inert under enhanced rules — equals smartFill11
ACA cap inert with non-ACA coverage — equals smartFill11
NIIT cap binds — cliffFill converts strictly less than smartFill11
NIIT off — equals smartFill11

Optimizer ACA Inert 4/4

TestExpectedActualResult
Non-ACA baseline: total acaSubsidy = 0 (baseACA = 0)00
Non-ACA + conversions: candidate total acaSubsidy = 000
Non-ACA + cliffFill: total acaSubsidy = 000
Non-ACA cliffFill ties smartFill on all score-relevant totals11

FICA 10/10

Authority: IRC §3101(a) (OASDI 6.2%); IRC §3101(b) (Medicare 1.45%); IRC §3101(b)(2) (Additional Medicare 0.9% above household threshold); IRS Pub 15.
Method: Per-person calcFICA on W-2 wages; SS portion capped at annual wage base ($184,500 in 2026); Medicare uncapped; Additional Medicare 0.9% on combined household wages above $250,000 MFJ / $200,000 single.
TestExpectedActualResult
SS portion = wages × 6.2%6,2006,200
Medicare portion = wages × 1.45%1,4501,450
Total = SS + Medicare, no Addl Med here7,6507,650
SS portion at cap = cap × 6.2%11,43911,439
Medicare at cap = cap × 1.45% (no cap on Medicare)2,6752,675
SS portion caps at wage base × 6.2%11,43911,439
Medicare continues on full wage amount3,6253,625
Zero wages → all zero00
SS portion limited to remaining base5,2395,239
Medicare still on full wages2,1752,175

Pre-tax 401(k) fix 2/2

Authority: IRC §3121(a) (FICA wage base includes 401(k) deferrals); IRC §62(a)(2) (above-the-line treatment for federal income tax).
Method: Verifies that 401(k) pre-tax deferrals reduce ordinary income for federal tax computation but NOT for the FICA wage base.
TestExpectedActualResult
Having a pre-tax account reduces pre-retirement federal tax11
FICA unchanged by pre-tax 401(k) choice9,1809,180

Phase resolver 6/6

Method: Income phase resolver tests confirming phase-level overrides take priority for ages they cover, age-outside-phase falls back to base config, per-phase incomeBreakdown propagates to FICA correctly, per-phase selfEmployed propagates to SE tax.
TestExpectedActualResult
No phases → base income at year 0120,000120,000
Phase income overrides base during covered years150,000150,000
Age outside phases uses base income120,000120,000
Phase-level incomeBreakdown reduces FICA base by §125 + payrollHSA10,09810,098
Phase SE does not pollute FICA (separate channels)00
W-2 + SE in same phase: FICA on W-2 only (unchanged by SE)7,6507,650

SE Tax 10/10

Authority: IRC §1401 (OASDI 12.4% / Medicare 2.9%); IRC §1402(a)(12) (92.35% multiplier); IRC §1402(b)(2) (wage base shared with W-2); IRC §1402(b) ($400 SECA-base floor); IRC §164(f) (half-of-SE-tax above-the-line deduction); IRS Schedule SE Instructions; IRS Pub 334.
Method: calcSETax computes SECA base = netSE × 0.9235; SS portion = min(SECA, ssWageBaseRemaining) × 12.4%; Medicare = SECA × 2.9%; halfDeduction = total / 2 reduces AGI.
TestExpectedActualResult
$50K net SE: secaBase = $46,17546,17546,175
$50K net SE: SS portion = $5,7265,7265,726
$50K net SE: Medicare = $1,3391,3391,339
$50K net SE: total = $7,0657,0657,065
$50K net SE: halfDeduction ≈ $3,5333,5333,533
Negative SE: zero SE tax00
Negative SE: zero half-deduction00
$400 net SE: under SECA floor → zero SE tax00
Wage base sharing: SS portion limited4,2784,278
Wage base sharing: Medicare uncapped2,1432,143

SE Tax Integration 20/20

Method: End-to-end runProjection() integration tests verifying SE tax flows through engine pipeline: AGI/MAGI propagation via the `other` accumulator, year-output field surface (seTax / seNetEarnings / seHalfDeduction), wage base sharing with W-2 income, business loss handling (negative net SE → no SE tax, AGI reduction only), spouse SE independence.
TestExpectedActualResult
SE tax in year output ≈ $11,30411,30411,304
seNetEarnings = $80K80,00080,000
seHalfDeduction ≈ $5,6525,6525,652
SE loss: zero SE tax00
SE loss: seNetEarnings = -$20K-20,000-20,000
SE loss: seHalfDeduction = 000
SE loss reduces MAGI vs baseline11
W-2 + SE: SE tax respects wage base sharing + Addl Medicare6,6366,636
Working-age SE: seTax > 011
Spouse SE: seTax > 011
F-044: $220K SE single → seTax includes ~$29 Addl Medicare28,79928,799
F-044: $130K W-2 + $145K SE → SE Addl Medicare via §1401(b)(2)(B)11,21611,216
F-044: MFJ combined SE ($80K + $200K) → Addl Medicare on $8,580 excess39,61539,615
F-044: $300K SE single → seTax includes $693 Addl Medicare31,60531,605
F-044: §164(f) half-deduction is NOT inflated by Addl Medicare15,45615,456
F-156: retired primary + spouse SE $300K → seTax includes $243 Addl Medicare31,15531,155
F-156: retired primary + spouse SE $200K (below threshold) → no Addl Medicare28,23428,234
F-156: retired primary + spouse W-2 $300K → fica reflects W-2 Addl Medicare ($450)16,23916,239
F-156: retired primary + spouse W-2 $300K → seTax = 0 (no SE)00
F-156: working primary $300K SE → seTax = $31,605 (matches 23d, no double-count)31,60531,605

QBI 10/10

Authority: IRC §199A(a)-(d), §199A(i); Treas. Reg. §1.199A-3(b)(1)(vi); IRS Rev. Proc. 2025-32 §4.26 (post-OBBBA §70105).
Method: Per-business 20% deduction with SSTB phaseout, household taxable-income cap (20% × (taxable − net cap gain)), W-2 wage limit (sole-prop assumption: $0), OBBBA $400 floor for ≥$1,000 QBI from a qualified trade or business. 2026 thresholds: $403,500 / $553,500 MFJ; $201,750 / $276,750 single (post-OBBBA $150K / $75K phase-in extension).
TestExpectedActualResult
Below threshold MFJ: full 20% deduction20,00020,000
SSTB above upper MFJ: $0 deduction00
Non-SSTB above upper MFJ no W-2: $400 floor400400
SSTB phase-in midpoint MFJ: W-2=0 → $400 floor400400
Taxable income limit MFJ: capped at 20% × (taxable − net capgain)10,00010,000
QBI below $1,000: no deduction00
Single below threshold: full 20% deduction10,00010,000
Single SSTB above upper: $0 deduction00
Two-business household MFJ: combined deduction16,00016,000
Mixed SSTB/non-SSTB above upper: $400 floor via non-SSTB400400

QBI Integration 6/6

Method: End-to-end runProjection() tests verifying QBI deduction flows correctly through engine: per-baseline computation across actual / no-conversion / conversion-only scenarios for accurate Roth conversion delta math, surface in year output (qbiDeduction field), interaction with TLH-ordinary-offset and capital-gains stacking. v6.14.1 added TLH-ordinary-offset symmetry across all three baselines.
TestExpectedActualResult
W-2 + SE: qbiDeduction > 011
W-2 + SE $100K: qbiDeduction ≈ 20% × (netSE − halfSE)18,93218,932
Pure SE $100K: deduction capped by household taxable income limit11
SSTB in phase-in range: deduction reduced vs full11
SSTB conversion: conversionTax > 011
TLH + QBI: deduction computed (no asymmetry crash)11

Solo 401k 17/17

Authority: IRC §401(c) (self-employed plan participation); IRC §401(c)(2)(A)(v) (positive-earned-income gating); IRC §402(g) + §414(v) (elective deferral limit + age-based catch-up); SECURE 2.0 §109 (enhanced catch-up ages 60-63); IRC §415(c) (annual addition cap); IRC §404(a)(8)(C) (20% sole-prop employer limit on net SE − half-SE-tax); SECURE 2.0 §604 (Roth employer profit-share); IRS Notice 2025-67 (2026 contribution limits).
Method: Solo 401(k) employee elective deferral (Traditional or Roth) and employer profit-share for sole prop / SMLLC / partnership entities. §402(g) capacity aggregates with any W-2 401(k) deferral target. §415(c) caps combined employee + employer at $72,000 (2026). Manual override for both employee dollar amount and employer percentage; auto-max default.
TestExpectedActualResult
$100K netSE age 45 auto-max: employee = $24,50024,50024,500
$100K netSE age 45 auto-max: employer ≈ $18,58718,58718,587
Traditional employee classification24,50024,500
Roth employee classification00
Age 62 SECURE 2.0 catch-up: employee = $35,75035,75035,750
§415(c) binds: employer + employee = annual addition limit72,00072,000
§415(c) clamp produces employer = $47,50047,50047,500
§402(g) aggregation: Solo limited by W-2 deferral target4,5004,500
Auto employer respects §415(c)18,58718,587
Roth employee: tradEmployee = 000
Roth employee: rothEmployee tracks amount24,50024,500
Roth employer: rothEmployerAmt > 018,58718,587
Roth employer: tradEmployer = 000
Manual deferral $10K respected10,00010,000
Manual employer 10% = $9,2949,2949,294
Negative SE: zero employee deferral00
Negative SE: zero employer profit-share00

Solo 401k Integration 9/9

Authority: Treas. Reg. §1.199A-3(b)(1)(vi) (retirement plan deductions reduce QBI); IRS Notice 2024-2 Q&A L9 (Roth employer profit-share treatment).
Method: End-to-end runProjection() integration tests verifying Solo 401(k) flows correctly: contribution amounts surface in year output (solo401kEmployee / solo401kEmployer fields); traditional contributions reduce AGI/MAGI; Roth employee preserves AGI; traditional employee + traditional employer + Roth employer all reduce QBI input; Roth employee preserves QBI input; spousal Solo 401(k) read independently via spouseSelfEmployed.
TestExpectedActualResult
solo401kEmployee surfaces in year output24,50024,500
solo401kEmployer ≈ $18,58718,58718,587
Traditional Solo reduces MAGI11
Roth employee preserves AGI11
Traditional Solo: qbiDeduction not larger than without Solo11
Roth employee preserves QBI deduction11
Roth employer: same QBI input as traditional employer (W-2+SE)11
Roth employer: higher MAGI than traditional employer11
Spouse Solo 401(k): contributions > 011

§402(g) precision 6/6

TestExpectedActualResult
Pool >> target (regression): solo401kEmployee = 000
Pool < target, traditional Solo: solo401kEmployee = $9,500 (was $0 pre-fix)9,5009,500
Pool < target, Roth Solo: solo401kEmployee = $9,500 (Roth deferrals count vs §402(g) per §402A)9,5009,500
Percent W-2 (25% of $98K = $24,500) consumes §402(g): solo401kEmployee = 000
Percent W-2 + pool clamp frees §402(g) room: solo401kEmployee = $9,5009,5009,500
Spouse percent W-2 (E4): spouse Solo §402(g) capacity consumed, solo401kEmployee = 000

QBI loss carry 6/6

TestExpectedActualResult
SE loss year-0: qbiLossCarryforward (carry-in) = 000
SE loss year-0: qbiLossCarryforwardNext = $30,000 (loss magnitude)30,00030,000
Loss y0 → profit y1: y1 qbiLossCarryforward = $30,000 (carry-in from y0)30,00030,000
Loss y0 → profit y1: y1 qbiLossCarryforwardNext = 0 (carry absorbed)00
Pre-existing carry $25K + y0 profit $40K: y0 qbiLossCarryforward = $25K (carry-in from params)25,00025,000
Pre-existing carry $25K + y0 profit $40K: y0 qbiLossCarryforwardNext = 0 (absorbed)00

Solo 401k S-Corp 6/6

TestExpectedActualResult
S-corp $100K salary: employer auto 25% = $25,00025,00025,000
S-corp $100K salary: employee auto-max = $24,50024,50024,500
S-corp: §415(c) not binding ($49,500 < $72,000)49,50049,500
S-corp manual 15%: employer = $15,00015,00015,000
S-corp $300K salary: §415(c) binds72,00072,000
S-corp §415(c): employer clamped to $47,50047,50047,500

S-Corp Integration 4/4

TestExpectedActualResult
S-corp: seTax = 0 (IRC §1402(a)(13))00
S-corp: FICA on salary ≈ $7,6507,6507,650
S-corp QBI deduction ≈ $10,10010,10010,100
S-corp age 62: QBI deduction ≈ $7,8507,8507,850

§603 Roth Catch-Up 11/11

TestExpectedActualResult
§603: trad base = $24,50024,50024,500
§603: forced Roth catch-up = $8,0008,0008,000
§603: total employee unchanged = $32,50032,50032,500
§603 + §109: trad base = $24,50024,50024,500
§603 + §109: forced Roth super catch-up = $11,25011,25011,250
§603 below threshold: all traditional = $32,50032,50032,500
§603 below threshold: no forced Roth00
§603 sole prop: all traditional = $32,50032,50032,500
§603 sole prop: no forced Roth00
§603 + already Roth: tradEmployee = 000
§603 + already Roth: all Roth = $32,50032,50032,500

§199A W-2 Limit 7/7

TestExpectedActualResult
S-corp above upper: W-2 limit not binding ($10,100)10,10010,100
Above upper, low W-2: limit binds at $10,00010,00010,000
UBIA path wins: 25%W2+2.5%UBIA = $17,50017,50017,500
Phase-in non-SSTB: W-2 high, no reduction = $16,00016,00016,000
Phase-in non-SSTB low W-2: reduction ≈ $13,91713,91713,917
Phase-in SSTB: phased amounts ≈ $5,7075,7075,707
Zero W-2 above upper: $400 floor (backward compat)400400

SEP-IRA 5/5

TestExpectedActualResult
SEP sole prop: employer 20% of planComp = $18,58718,58718,587
SEP sole prop: employee = $0 (no deferral)00
SEP S-corp: employer 25% of salary = $25,00025,00025,000
SEP S-corp: employee = $000
SEP S-corp: QBI deduction ≈ $15,00015,00015,000

SIMPLE IRA 23/23

TestExpectedActualResult
$100K netSE age 45: employee = $17,00017,00017,000
$100K netSE age 45: employer match = $3,0003,0003,000
Traditional employee classification17,00017,000
Age 52 catch-up: employee = $21,00021,00021,000
Age 52: employer match still = $3,0003,0003,000
Age 62 SECURE 2.0 super catch-up: employee = $22,25022,25022,250
Non-elective: employer = $2,0002,0002,000
Non-elective: employee still auto-maxes = $17,00017,00017,000
Manual $10K deferral respected10,00010,000
Match mirrors deferral (< 3% cap): $3,0003,0003,000
S-corp: employer match based on W-2 salary = $2,4002,4002,400
S-corp: employee deferral = $17,00017,00017,000
§402(g) aggregation: deferral capped at $4,5004,5004,500
Match tracks actual deferral: min($3K, $4.5K) = $3,0003,0003,000
Negative SE: zero employee deferral00
Negative SE: zero employer contribution00
§603: tradEmployee = $17,000 (base)17,00017,000
§603: rothEmployee = $4,000 (catch-up forced Roth)4,0004,000
§603: total deferral = $21,00021,00021,000
Roth employee: tradEmployee = 000
Roth employee: rothEmployee = $17,00017,00017,000
Employer always traditional: tradEmployer = $3,0003,0003,000
Employer rothEmployerAmt = 000

SIMPLE IRA Integration 5/5

TestExpectedActualResult
solo401kEmployee = SIMPLE deferral ≈ $17,00017,00017,000
solo401kEmployer = match ≈ $3,0003,0003,000
Traditional SIMPLE reduces AGI11
Non-elective employer ≈ $2,0002,0002,000
Traditional SIMPLE reduces QBI deduction11

Mega Backdoor Roth 5/5

TestExpectedActualResult
Auto-max: afterTax = $28,91328,91328,913
Employee + employer unchanged43,08743,087
Manual cap $15K respected15,00015,000
§415(c) ceiling: afterTax = $000
Disabled: afterTax = 000

Mega Backdoor Roth Integration 2/2

TestExpectedActualResult
solo401kAfterTax > 0 in year output11
solo401kAfterTax ≈ $28,91328,91328,913

Pre-flight 3/3

TestExpectedActualResult
calcSpousalBenefit existsfunctionfunction
calcSpousalBenefit has 4 parameters (not old 2-param version)44
ssReverseAdjustPIA existstruetrue

Spousal SS 13/13

TestExpectedActualResult
Spouse at FRA (67), no own record → 50% of worker PIA12,00012,000
Worker PIA = $3,000/mo, spouse at FRA → $18,000/yr floor18,00018,000
Spouse own = $9,600/yr (< $12K floor) → top-up = $2,4002,4002,400
Spouse own = $600/mo ($7,200/yr) → top-up = $4,8004,8004,800
Spouse own = $12,000/yr (= floor) → top-up = $000
Spouse own = $13,200/yr (> floor) → top-up = $000
Spouse claims at 62 (60mo early), no own record → 32.5% of worker PIA7,8007,800
Spouse claims at 65 (24mo early) → ~41.7% of worker PIA annual10,00010,000
FRA=66, claims at 62 (48mo early) → 35% of worker PIA8,4008,400
Spouse claims at 70 (past FRA) → same as FRA, no DRC increase12,00012,000
Spouse claims at 68 (past FRA) → same as FRA12,00012,000
Worker PIA = $0 → top-up = $000
Spouse own = $0, worker PIA = $0 → $000

COLA 2/2

TestExpectedActualResult
Spousal benefit grows with COLA at age 68 vs 6711
Spousal top-up at 68 ≈ $18,360 (18,000 × 1.02)18,36018,360

UI Wording 4/4

TestExpectedActualResult
"Spousal SS Benefit" Plan Health lever title exists in HTML11
Lever says benefit is "already included in your projection"11
Lever links to SS tab (inputTab=ss)11
Old 2-param calcSpousalBenefit signature is NOT present11

Survivor claim-age cap 6/6

TestExpectedActualResult
Primary dies y0, survivor past FRA → survivor benefit applies immediately, not deferred to age 8558,34458,344
Primary dies y0, survivor benefit holds across years (not just y0)58,34458,344
Spouse dies y0, primary is lower earner → survivor benefit dominates immediately60,00060,000
Pre-FRA strategic claim age respected — survivor 62 with claim age 65 → no benefit yet11
Pre-FRA strategic claim age respected — survivor benefit starts at chosen age 6511
User-set claim age above FRA is capped — no waiting past FRA per RS 00615.30111

Reverse round-trip 16/16

TestExpectedActualResult
PIA $1500 claim 62 → adj $1050 → reverse $15001,5001,500
PIA $1500 claim 65 → adj $1300 → reverse $15001,5001,500
PIA $1500 claim 67 → adj $1500 → reverse $15001,5001,500
PIA $1500 claim 68 → adj $1620 → reverse $15001,5001,500
PIA $1500 claim 70 → adj $1860 → reverse $15001,5001,500
PIA $2500 claim 62 → adj $1750 → reverse $25002,5002,500
PIA $2500 claim 65 → adj $2166 → reverse $24992,5002,499
PIA $2500 claim 67 → adj $2500 → reverse $25002,5002,500
PIA $2500 claim 68 → adj $2700 → reverse $25002,5002,500
PIA $2500 claim 70 → adj $3100 → reverse $25002,5002,500
PIA $3500 claim 62 → adj $2450 → reverse $35003,5003,500
PIA $3500 claim 65 → adj $3033 → reverse $35003,5003,500
PIA $3500 claim 67 → adj $3500 → reverse $35003,5003,500
PIA $3500 claim 68 → adj $3780 → reverse $35003,5003,500
PIA $3500 claim 70 → adj $4340 → reverse $35003,5003,500
Zero current monthly returns 000

Primary already-collecting 4/4

TestExpectedActualResult
Age 75: ss = current monthly × 12 (COLA 0%)50,40050,400
Age 80: ss still 50400 (COLA 0%)50,40050,400
Age 75 with COLA 2%: ss = 50400 (zero COLA years)50,40050,400
Age 80 with COLA 2%: ss ≈ 50400 × 1.02^5 ≈ 5564855,64855,646

Spousal floor 1/1

TestExpectedActualResult
Already-collecting primary supplies recovered PIA for spousal floor54,00054,000

Spouse already-collecting 2/2

TestExpectedActualResult
Primary not yet filed, spouse already collecting → ss > 011
Spouse benefit constant when primary still not filed (COLA 0%)11

Both already-collecting 2/2

TestExpectedActualResult
Year 0 (age 73): combined ss ≈ (3500+1800) × 12 = 6360063,60063,600
Five years later (age 78): combined ss ≈ 63600 × 1.02^5 ≈ 7022170,22170,219

Backwards compat 1/1

TestExpectedActualResult
Non-working spouse with ssAlreadyCollecting:false → $54K at FRA54,00054,000

Clarks Y0 37/37

TestExpectedActualResult
year = 20262,0262,026
age = 646464
spAge = 626262
earned = 182000182,000182,000
primaryEarned = 110000110,000110,000
spouseEarned = 7200072,00072,000
savings = 2800028,00028,000
pension = 000
ss = 000
ssTaxable = 000
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 000
hsaContrib = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 000
capGains = 000
agi = 165200165,200165,200
fedTax = 1720217,20217,202
stateTax = 000
fica = 1392313,92313,923
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 3112531,12531,125
medicareCost = 18261,8261,826
irmaa = 000
irmaaBracket = 000
preTax = 873976873,976873,976
roth = 167990167,990167,990
taxable = 111494111,494111,494
netWorth = 11534601,153,4601,153,460
retired === nulltruetrue

Clarks Y1 37/37

TestExpectedActualResult
year = 20272,0272,027
age = 656565
spAge = 636363
retired = truetruetrue
earned = 7344073,44073,440
primaryEarned = 000
spouseEarned = 7344073,44073,440
savings = 000
pension = 000
ss = 000
ssTaxable = 000
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 000
hsaContrib = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 1980719,80719,807
capGains = 99049,9049,904
agi = 7722477,22477,224
fedTax = 26722,6722,672
stateTax = 000
fica = 56185,6185,618
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 82908,2908,290
medicareCost = 25572,5572,557
irmaa = 000
irmaaBracket = 000
preTax = 935154935,154935,154
roth = 179749179,749179,749
taxable = 9810598,10598,105
netWorth = 12130081,213,0081,213,008

Clarks Y3 37/37

TestExpectedActualResult
year = 20292,0292,029
age = 676767
spAge = 656565
retired = truetruetrue
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
pension = 000
ss = 3311033,11033,110
ssTaxable = 81498,1498,149
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 000
hsaContrib = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 5994659,94659,946
capGains = 2997329,97329,973
agi = 3812238,12238,122
fedTax = 000
stateTax = 000
fica = 000
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 000
medicareCost = 56385,6385,638
irmaa = 000
irmaaBracket = 000
preTax = 10706581,070,6581,070,658
roth = 205795205,795205,795
taxable = 2393623,93623,936
netWorth = 13003891,300,3891,300,389

Clarks Y5 37/37

TestExpectedActualResult
year = 20312,0312,031
age = 696969
spAge = 676767
retired = truetruetrue
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
pension = 000
ss = 5962059,62059,620
ssTaxable = 3009630,09630,096
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 000
hsaContrib = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 4253842,53842,538
capGains = 000
agi = 7263472,63472,634
fedTax = 32103,2103,210
stateTax = 000
fica = 000
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 32103,2103,210
medicareCost = 62156,2156,215
irmaa = 000
irmaaBracket = 000
preTax = 11330761,133,0761,133,076
roth = 235615235,615235,615
taxable = 000
netWorth = 13686911,368,6911,368,691

Clarks Y11 37/37

TestExpectedActualResult
year = 20372,0372,037
age = 757575
spAge = 737373
retired = truetruetrue
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
pension = 000
ss = 6714267,14267,142
ssTaxable = 4630646,30646,306
rmd = 5221852,21852,218
rmdRequired = truetruetrue
rothConv = 000
hsaContrib = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 5784857,84857,848
capGains = 000
agi = 104154104,154104,154
fedTax = 59265,9265,926
stateTax = 000
fica = 000
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 59265,9265,926
medicareCost = 83298,3298,329
irmaa = 000
irmaaBracket = 000
preTax = 13125961,312,5961,312,596
roth = 353594353,594353,594
taxable = 000
netWorth = 16661901,666,1901,666,190

Clarks Y31 37/37

TestExpectedActualResult
year = 20572,0572,057
age = 959595
spAge = 939393
retired = truetruetrue
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
pension = 000
ss = 9977099,77099,770
ssTaxable = 8480584,80584,805
rmd = 140446140,446140,446
rmdRequired = truetruetrue
rothConv = 000
hsaContrib = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 213238213,238213,238
capGains = 3639636,39636,396
agi = 261646261,646261,646
fedTax = 1558915,58915,589
stateTax = 000
fica = 000
cgTax = 000
niitTax = 443443443
qbiDeduction = 000
conversionTax = 000
tax = 1558915,58915,589
medicareCost = 2210022,10022,100
irmaa = 000
irmaaBracket = 000
preTax = 11871881,187,1881,187,188
roth = 13682981,368,2981,368,298
taxable = 8058480,58480,584
netWorth = 26360702,636,0702,636,070

Lees Y0 43/43

TestExpectedActualResult
year = 20262,0262,026
age = 595959
spAge = 575757
earned = 267000267,000267,000
primaryEarned = 175000175,000175,000
spouseEarned = 9200092,00092,000
totalInc = 267000267,000267,000
savings = 4300043,00043,000
hsaContrib = 85508,5508,550
cashInterest = 22502,2502,250
pension = 000
ss = 000
ssTaxable = 000
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 000
capGains = 000
agi = 245700245,700245,700
fedTax = 3643636,43636,436
stateTax = 1387013,87013,870
fica = 1984819,84819,848
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 7015470,15470,154
medicareCost = 000
irmaa = 000
irmaaBracket = 000
acaSubsidy = 000
expenses = 8800088,00088,000
preTax = 11930501,193,0501,193,050
roth = 217745217,745217,745
taxable = 324565324,565324,565
hsa = 4616346,16346,163
netWorth = 17815231,781,5231,781,523
retired === nulltruetrue
isSingle === nulltruetrue

Lees Y3 55/55

TestExpectedActualResult
year = 20292,0292,029
age = 626262
spAge = 606060
earned = 9763197,63197,631
primaryEarned = 000
spouseEarned = 9763197,63197,631
totalInc = 9763197,63197,631
savings = 000
hsaContrib = 85508,5508,550
cashInterest = 365365365
pension = 000
ss = 000
ssTaxable = 000
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 163554163,554163,554
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 4893948,93948,939
withdrawalForSpending = 4893948,93948,939
capGains = 000
agi = 238000238,000238,000
fedTax = 3307633,07633,076
stateTax = 1342813,42813,428
fica = 74697,4697,469
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 2890128,90128,901
tax = 5397353,97353,973
drawdownTax = 000
taxAwareDrawdown = 000
medicareCost = 000
irmaa = 000
irmaaBracket = 000
healthcare = 2533825,33825,338
acaSubsidy = 000
acaBenchmark = 2533825,33825,338
acaNetPremium = 2533825,33825,338
acaFPLPercent = 11441,1441,144
expenses = 121498121,498121,498
cash = 000
preTax = 13220841,322,0841,322,084
preTaxPrimary = 949207949,207949,207
preTaxSpouse = 372877372,877372,877
roth = 497443497,443497,443
taxable = 325069325,069325,069
taxableInv = 325069325,069325,069
hsa = 8383483,83483,834
netWorth = 22284302,228,4302,228,430
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === "aca"truetrue

Lees Y5 55/55

TestExpectedActualResult
year = 20312,0312,031
age = 646464
spAge = 626262
earned = 000
primaryEarned = 000
spouseEarned = 000
totalInc = 000
savings = 000
hsaContrib = 000
cashInterest = 000
pension = 000
ss = 000
ssTaxable = 000
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 199513199,513199,513
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 149180149,180149,180
withdrawalForSpending = 149180149,180149,180
capGains = 5348753,48753,487
agi = 253000253,000253,000
fedTax = 3114731,14731,147
stateTax = 1429014,29014,290
fica = 000
cgTax = 80238,0238,023
niitTax = 114114114
qbiDeduction = 000
conversionTax = 2301023,01023,010
tax = 4543745,43745,437
drawdownTax = 000
taxAwareDrawdown = 000
medicareCost = 12951,2951,295
irmaa = 000
irmaaBracket = 000
healthcare = 2344123,44123,441
acaSubsidy = 000
acaBenchmark = 2344123,44123,441
acaNetPremium = 2344123,44123,441
acaFPLPercent = 10491,0491,049
expenses = 126752126,752126,752
cash = 000
preTax = 11067261,106,7261,106,726
preTaxPrimary = 794588794,588794,588
preTaxSpouse = 312138312,138312,138
roth = 976451976,451976,451
taxable = 198957198,957198,957
taxableInv = 198957198,957198,957
hsa = 000
netWorth = 22821342,282,1342,282,134
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === "aca"truetrue

Lees Y11 56/56

TestExpectedActualResult
year = 20372,0372,037
age = 707070
spAge = 686868
earned = 000
primaryEarned = 000
spouseEarned = 000
totalInc = 9053890,53890,538
savings = 000
hsaContrib = 000
cashInterest = 000
pension = 000
ss = 9053890,53890,538
ssTaxable = 1855618,55618,556
rmd = 000
rmdRequired = falsefalsefalse
rothConv = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 3960439,60439,604
withdrawalForSpending = 3960439,60439,604
capGains = 000
agi = 3205932,05932,059
fedTax = 000
stateTax = 000
fica = 000
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 000
drawdownTax = 000
taxAwareDrawdown = 000
medicareCost = 83298,3298,329
irmaa = 000
irmaaBracket = 000
healthcare = 000
acaSubsidy = 000
acaBenchmark = 000
acaNetPremium = 000
acaFPLPercent = 000
expenses = 130142130,142130,142
cash = 000
preTax = 000
preTaxPrimary = 000
preTaxSpouse = 000
roth = 24012012,401,2012,401,201
taxable = 000
taxableInv = 000
hsa = 000
netWorth = 24012012,401,2012,401,201
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue

Lees Y16 59/59

TestExpectedActualResult
year = 20422,0422,042
age = 757575
spAge = 737373
earned = 000
primaryEarned = 000
spouseEarned = 000
totalInc = 9996199,96199,961
savings = 000
hsaContrib = 000
cashInterest = 000
pension = 000
ss = 9996299,96299,961
ssTaxable = 1108311,08311,083
rmd = 000
rmdPrimary = 000
rmdSpouse = 000
rmdReinvested = 000
rothConv = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 5188351,88351,884
withdrawalForSpending = 5188351,88351,884
capGains = 000
agi = 1108311,08311,083
fedTax = 000
stateTax = 000
fica = 000
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 000
drawdownTax = 000
taxAwareDrawdown = 000
medicareCost = 1063110,63110,631
irmaa = 000
irmaaBracket = 000
healthcare = 000
acaSubsidy = 000
acaBenchmark = 000
acaNetPremium = 000
acaFPLPercent = 000
expenses = 151845151,845151,845
cash = 000
preTax = 000
preTaxPrimary = 000
preTaxSpouse = 000
roth = 30820843,082,0843,082,084
taxable = 000
taxableInv = 000
hsa = 000
netWorth = 30820843,082,0843,082,084
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue
rmdRequired === falsetruetrue

Lees Y36 59/59

TestExpectedActualResult
year = 20622,0622,062
age = 959595
spAge = 939393
earned = 000
primaryEarned = 000
spouseEarned = 000
totalInc = 148536148,536148,536
savings = 000
hsaContrib = 000
cashInterest = 000
pension = 000
ss = 148536148,536148,536
ssTaxable = 3172831,72831,728
rmd = 000
rmdPrimary = 000
rmdSpouse = 000
rmdReinvested = 000
rothConv = 000
qcd = 000
charityTotal = 000
isItemizing = 000
isBunchYear = falsefalsefalse
withdrawal = 134718134,718134,718
withdrawalForSpending = 134718134,718134,718
capGains = 000
agi = 3172831,72831,728
fedTax = 000
stateTax = 000
fica = 000
cgTax = 000
niitTax = 000
qbiDeduction = 000
conversionTax = 000
tax = 000
drawdownTax = 000
taxAwareDrawdown = 000
medicareCost = 2820628,20628,206
irmaa = 000
irmaaBracket = 000
healthcare = 000
acaSubsidy = 000
acaBenchmark = 000
acaNetPremium = 000
acaFPLPercent = 000
expenses = 283254283,254283,254
cash = 000
preTax = 000
preTaxPrimary = 000
preTaxSpouse = 000
roth = 83725238,372,5238,372,523
taxable = 000
taxableInv = 000
hsa = 000
netWorth = 83725238,372,5238,372,523
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue
rmdRequired === falsetruetrue

Washingtons Y0 41/41

TestExpectedActualResult
year = 20262,0262,026
age = 636363
spAge = 616161
earned = 208000208,000208,000
primaryEarned = 130000130,000130,000
spouseEarned = 7800078,00078,000
savings = 3200032,00032,000
cashInterest = 45004,5004,500
cash = 104500104,500104,500
agi = 193300193,300193,300
fedTax = 2486624,86624,866
stateTax = 96659,6659,665
fica = 1591215,91215,912
tax = 5044350,44350,443
debtPayments = 2160021,60021,600
debtInterest = 71377,1377,137
debtPrincipalPaid = 1446314,46314,463
expenses = 103600103,600103,600
preTax = 10370441,037,0441,037,044
preTaxPrimary = 10370441,037,0441,037,044
preTaxSpouse = 000
roth = 276060276,060276,060
taxableInv = 219136219,136219,136
netWorth = 16367401,636,7401,636,740
pension = 000
ss = 000
ssTaxable = 000
ssdi = 000
rmd = 000
rmdPrimary = 000
rmdSpouse = 000
rmdRequired = falsefalsefalse
ltcCost = 000
medicareCost = 000
irmaa = 000
irmaaBracket = 000
niitTax = 000
retired === nulltruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue

Washingtons Y2 42/42

TestExpectedActualResult
year = 20282,0282,028
age = 656565
spAge = 636363
earned = 8115181,15181,151
primaryEarned = 000
spouseEarned = 8115181,15181,151
savings = 000
cashInterest = 40554,0554,055
cash = 9416394,16394,163
agi = 107715107,715107,715
fedTax = 73727,3727,372
stateTax = 53865,3865,386
fica = 62086,2086,208
tax = 1896618,96618,966
pension = 3000030,00030,000
pensionTaxable = 3000030,00030,000
ss = 000
ssTaxable = 000
ssdi = 000
rmd = 000
rmdPrimary = 000
rmdSpouse = 000
rmdRequired = falsefalsefalse
medicareCost = 26852,6852,685
irmaa = 000
irmaaBracket = 000
ltcCost = 000
niitTax = 000
debtPayments = 2160021,60021,600
debtInterest = 59345,9345,934
debtPrincipalPaid = 1566615,66615,666
expenses = 111279111,279111,279
preTax = 12097331,209,7331,209,733
preTaxPrimary = 12097331,209,7331,209,733
preTaxSpouse = 000
roth = 325403325,403325,403
taxableInv = 256494256,494256,494
netWorth = 18857931,885,7931,885,793
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue

Washingtons Y7 46/46

TestExpectedActualResult
year = 20332,0332,033
age = 707070
spAge = 686868
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
cashInterest = 000
cash = 000
agi = 8656286,56286,562
fedTax = 28702,8702,870
stateTax = 764764764
fica = 000
tax = 36343,6343,634
pension = 3312233,12233,122
pensionTaxable = 3312233,12233,122
ss = 7129271,29271,292
ssTaxable = 3917739,17739,177
ssdi = 000
rmd = 000
rmdPrimary = 000
rmdSpouse = 000
rmdRequired = falsefalsefalse
medicareCost = 68536,8536,853
irmaa = 000
irmaaBracket = 000
ltcCost = 000
niitTax = 000
capGains = 1426314,26314,263
cgTax = 000
withdrawal = 2852728,52728,527
withdrawalForSpending = 2852728,52728,527
debtPayments = 2160021,60021,600
debtInterest = 24722,4722,472
debtPrincipalPaid = 1912819,12819,128
expenses = 129303129,303129,303
preTax = 16967141,696,7141,696,714
preTaxPrimary = 16967141,696,7141,696,714
preTaxSpouse = 000
roth = 456395456,395456,395
taxableInv = 107001107,001107,001
netWorth = 22601102,260,1102,260,110
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue

Washingtons Y9 46/46

TestExpectedActualResult
year = 20352,0352,035
age = 727272
spAge = 707070
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
cashInterest = 000
cash = 000
agi = 9306593,06593,065
fedTax = 30993,0993,099
stateTax = 945945945
fica = 000
tax = 40444,0444,044
pension = 3446134,46134,461
pensionTaxable = 3446134,46134,461
ss = 7417274,17274,172
ssTaxable = 4282642,82642,826
ssdi = 000
rmd = 000
rmdPrimary = 000
rmdSpouse = 000
rmdRequired = falsefalsefalse
medicareCost = 75557,5557,555
irmaa = 000
irmaaBracket = 000
ltcCost = 000
niitTax = 000
capGains = 1577815,77815,778
cgTax = 000
withdrawal = 3155531,55531,555
withdrawalForSpending = 3155531,55531,555
debtPayments = 2160021,60021,600
debtInterest = 882882882
debtPrincipalPaid = 2071820,71820,718
expenses = 136146136,146136,146
preTax = 19425671,942,5671,942,567
preTaxPrimary = 19425671,942,5671,942,567
preTaxSpouse = 000
roth = 522527522,527522,527
taxableInv = 5438454,38454,384
netWorth = 25194782,519,4782,519,478
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue

Washingtons Y12 47/47

TestExpectedActualResult
year = 20382,0382,038
age = 757575
spAge = 737373
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
cashInterest = 000
cash = 000
agi = 202263202,263202,263
fedTax = 1774417,74417,744
stateTax = 61786,1786,178
fica = 000
tax = 2392223,92223,922
pension = 3657036,57036,570
pensionTaxable = 3657036,57036,570
ss = 7871278,71278,712
ssTaxable = 6690566,90566,905
ssdi = 000
rmd = 9040890,40890,408
rmdPrimary = 9040890,40890,408
rmdSpouse = 000
rmdRequired = truetruetrue
rmdReinvested = 9040890,40890,408
medicareCost = 87468,7468,746
irmaa = 000
irmaaBracket = 000
ltcCost = 000
niitTax = 000
capGains = 83808,3808,380
cgTax = 12571,2571,257
withdrawal = 107168107,168107,168
withdrawalForSpending = 1676016,76016,760
debtPayments = 000
debtInterest = 000
debtPrincipalPaid = 000
expenses = 108122108,122108,122
preTax = 22829922,282,9922,282,992
preTaxPrimary = 22829922,282,9922,282,992
preTaxSpouse = 000
roth = 640118640,118640,118
taxableInv = 106329106,329106,329
netWorth = 30294393,029,4393,029,439
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === truetruetrue

Washingtons Y32 47/47

TestExpectedActualResult
year = 20582,0582,058
age = 959595
spAge = 939393
earned = 000
primaryEarned = 000
spouseEarned = 000
savings = 000
cashInterest = 000
cash = 000
agi = 457724457,724457,724
fedTax = 5144651,44651,446
stateTax = 1703817,03817,038
fica = 000
tax = 6848468,48468,484
pension = 5434154,34154,341
pensionTaxable = 5434154,34154,341
ss = 116962116,962116,962
ssTaxable = 9941899,41899,418
ssdi = 000
rmd = 243474243,474243,474
rmdPrimary = 243474243,474243,474
rmdSpouse = 000
rmdRequired = truetruetrue
rmdReinvested = 243474243,474243,474
medicareCost = 2320523,20523,205
irmaa = 000
irmaaBracket = 000
ltcCost = 000
niitTax = 22992,2992,299
capGains = 6049160,49160,491
cgTax = 90749,0749,074
withdrawal = 364456364,456364,456
withdrawalForSpending = 120982120,982120,982
debtPayments = 000
debtInterest = 000
debtPrincipalPaid = 000
expenses = 223804223,804223,804
preTax = 20580852,058,0852,058,085
preTaxPrimary = 20580852,058,0852,058,085
preTaxSpouse = 000
roth = 24770542,477,0542,477,054
taxableInv = 16207221,620,7221,620,722
netWorth = 61558616,155,8616,155,861
retired === truetruetrue
isSingle === nulltruetrue
healthcareSource === nulltruetrue
taxConvergenceFlag === falsetruetrue

Clarks Cruise 178/178

TestExpectedActualResult
projection.length = 323232
Y1.year = Y0.year + 12,0272,027
Y2.year = Y1.year + 12,0282,028
Y3.year = Y2.year + 12,0292,029
Y4.year = Y3.year + 12,0302,030
Y5.year = Y4.year + 12,0312,031
Y6.year = Y5.year + 12,0322,032
Y7.year = Y6.year + 12,0332,033
Y8.year = Y7.year + 12,0342,034
Y9.year = Y8.year + 12,0352,035
Y10.year = Y9.year + 12,0362,036
Y11.year = Y10.year + 12,0372,037
Y12.year = Y11.year + 12,0382,038
Y13.year = Y12.year + 12,0392,039
Y14.year = Y13.year + 12,0402,040
Y15.year = Y14.year + 12,0412,041
Y16.year = Y15.year + 12,0422,042
Y17.year = Y16.year + 12,0432,043
Y18.year = Y17.year + 12,0442,044
Y19.year = Y18.year + 12,0452,045
Y20.year = Y19.year + 12,0462,046
Y21.year = Y20.year + 12,0472,047
Y22.year = Y21.year + 12,0482,048
Y23.year = Y22.year + 12,0492,049
Y24.year = Y23.year + 12,0502,050
Y25.year = Y24.year + 12,0512,051
Y26.year = Y25.year + 12,0522,052
Y27.year = Y26.year + 12,0532,053
Y28.year = Y27.year + 12,0542,054
Y29.year = Y28.year + 12,0552,055
Y30.year = Y29.year + 12,0562,056
Y31.year = Y30.year + 12,0572,057
Y1.age = Y0.age + 16565
Y2.age = Y1.age + 16666
Y3.age = Y2.age + 16767
Y4.age = Y3.age + 16868
Y5.age = Y4.age + 16969
Y6.age = Y5.age + 17070
Y7.age = Y6.age + 17171
Y8.age = Y7.age + 17272
Y9.age = Y8.age + 17373
Y10.age = Y9.age + 17474
Y11.age = Y10.age + 17575
Y12.age = Y11.age + 17676
Y13.age = Y12.age + 17777
Y14.age = Y13.age + 17878
Y15.age = Y14.age + 17979
Y16.age = Y15.age + 18080
Y17.age = Y16.age + 18181
Y18.age = Y17.age + 18282
Y19.age = Y18.age + 18383
Y20.age = Y19.age + 18484
Y21.age = Y20.age + 18585
Y22.age = Y21.age + 18686
Y23.age = Y22.age + 18787
Y24.age = Y23.age + 18888
Y25.age = Y24.age + 18989
Y26.age = Y25.age + 19090
Y27.age = Y26.age + 19191
Y28.age = Y27.age + 19292
Y29.age = Y28.age + 19393
Y30.age = Y29.age + 19494
Y31.age = Y30.age + 19595
Y0 earned = primaryEarned + spouseEarned182,000182,000
Y1 earned = primaryEarned + spouseEarned73,44073,440
Y2 earned = primaryEarned + spouseEarned74,90974,909
Y3 earned = primaryEarned + spouseEarned00
Y4 earned = primaryEarned + spouseEarned00
Y5 earned = primaryEarned + spouseEarned00
Y6 earned = primaryEarned + spouseEarned00
Y7 earned = primaryEarned + spouseEarned00
Y8 earned = primaryEarned + spouseEarned00
Y9 earned = primaryEarned + spouseEarned00
Y10 earned = primaryEarned + spouseEarned00
Y11 earned = primaryEarned + spouseEarned00
Y12 earned = primaryEarned + spouseEarned00
Y13 earned = primaryEarned + spouseEarned00
Y14 earned = primaryEarned + spouseEarned00
Y15 earned = primaryEarned + spouseEarned00
Y16 earned = primaryEarned + spouseEarned00
Y17 earned = primaryEarned + spouseEarned00
Y18 earned = primaryEarned + spouseEarned00
Y19 earned = primaryEarned + spouseEarned00
Y20 earned = primaryEarned + spouseEarned00
Y21 earned = primaryEarned + spouseEarned00
Y22 earned = primaryEarned + spouseEarned00
Y23 earned = primaryEarned + spouseEarned00
Y24 earned = primaryEarned + spouseEarned00
Y25 earned = primaryEarned + spouseEarned00
Y26 earned = primaryEarned + spouseEarned00
Y27 earned = primaryEarned + spouseEarned00
Y28 earned = primaryEarned + spouseEarned00
Y29 earned = primaryEarned + spouseEarned00
Y30 earned = primaryEarned + spouseEarned00
Y31 earned = primaryEarned + spouseEarned00
Y0 tax = fedTax + stateTax + fica31,12531,125
Y1 tax = fedTax + stateTax + fica8,2908,290
Y2 tax = fedTax + stateTax + fica7,6327,632
Y3 tax = fedTax + stateTax + fica00
Y4 tax = fedTax + stateTax + fica2,9822,982
Y5 tax = fedTax + stateTax + fica3,2103,210
Y6 tax = fedTax + stateTax + fica3,6243,624
Y7 tax = fedTax + stateTax + fica4,0444,044
Y8 tax = fedTax + stateTax + fica4,4954,495
Y9 tax = fedTax + stateTax + fica4,9394,939
Y10 tax = fedTax + stateTax + fica5,4245,424
Y11 tax = fedTax + stateTax + fica5,9265,926
Y12 tax = fedTax + stateTax + fica6,4326,432
Y13 tax = fedTax + stateTax + fica6,9816,981
Y14 tax = fedTax + stateTax + fica7,5447,544
Y15 tax = fedTax + stateTax + fica8,1218,121
Y16 tax = fedTax + stateTax + fica8,7378,737
Y17 tax = fedTax + stateTax + fica9,0849,084
Y18 tax = fedTax + stateTax + fica9,3979,397
Y19 tax = fedTax + stateTax + fica9,7359,735
Y20 tax = fedTax + stateTax + fica10,15810,158
Y21 tax = fedTax + stateTax + fica10,65810,658
Y22 tax = fedTax + stateTax + fica11,18711,187
Y23 tax = fedTax + stateTax + fica11,73311,733
Y24 tax = fedTax + stateTax + fica12,19712,197
Y25 tax = fedTax + stateTax + fica12,78112,781
Y26 tax = fedTax + stateTax + fica13,26513,265
Y27 tax = fedTax + stateTax + fica13,74313,743
Y28 tax = fedTax + stateTax + fica14,21614,216
Y29 tax = fedTax + stateTax + fica14,67814,678
Y30 tax = fedTax + stateTax + fica15,00715,007
Y31 tax = fedTax + stateTax + fica15,58915,589
Y0 netWorth = sum of buckets1,153,4601,153,460
Y1 netWorth = sum of buckets1,213,0081,213,008
Y2 netWorth = sum of buckets1,275,2631,275,263
Y3 netWorth = sum of buckets1,300,3891,300,389
Y4 netWorth = sum of buckets1,321,6891,321,689
Y5 netWorth = sum of buckets1,368,6911,368,691
Y6 netWorth = sum of buckets1,416,5021,416,502
Y7 netWorth = sum of buckets1,465,0951,465,095
Y8 netWorth = sum of buckets1,514,4101,514,410
Y9 netWorth = sum of buckets1,564,4191,564,419
Y10 netWorth = sum of buckets1,615,0351,615,035
Y11 netWorth = sum of buckets1,666,1901,666,190
Y12 netWorth = sum of buckets1,717,8211,717,821
Y13 netWorth = sum of buckets1,769,8161,769,816
Y14 netWorth = sum of buckets1,822,0821,822,082
Y15 netWorth = sum of buckets1,874,5131,874,513
Y16 netWorth = sum of buckets1,926,9681,926,968
Y17 netWorth = sum of buckets1,979,6201,979,620
Y18 netWorth = sum of buckets2,032,3992,032,399
Y19 netWorth = sum of buckets2,085,1612,085,161
Y20 netWorth = sum of buckets2,137,6832,137,683
Y21 netWorth = sum of buckets2,189,7332,189,733
Y22 netWorth = sum of buckets2,241,1092,241,109
Y23 netWorth = sum of buckets2,291,6022,291,602
Y24 netWorth = sum of buckets2,341,0852,341,085
Y25 netWorth = sum of buckets2,389,2072,389,207
Y26 netWorth = sum of buckets2,435,8152,435,815
Y27 netWorth = sum of buckets2,480,6462,480,646
Y28 netWorth = sum of buckets2,523,4012,523,401
Y29 netWorth = sum of buckets2,563,7712,563,771
Y30 netWorth = sum of buckets2,601,5422,601,542
Y31 netWorth = sum of buckets2,636,0702,636,070
Y0 retired === nulltruetrue
all years Y1+ retired === truetruetrue
Y0 earned > 0 (both working)truetrue
Y1 earned > 0 (spouse continues working)truetrue
Y2 earned > 0 (spouse continues working)truetrue
all years Y3+ earned = 0truetrue
all years Y0-Y2 ss = 0 (pre-claim)truetrue
all years Y3+ ss > 0 (post-primary-claim)truetrue
all years Y0-Y10 rmd = 0 (pre-trigger)truetrue
all years Y0-Y10 rmdRequired === false (pre-trigger)truetrue
all years Y11+ rmdRequired === true (post-trigger)truetrue
all years rothConv = 0truetrue
all years hsaContrib = 0truetrue
all years charityTotal = 0truetrue
all years stateTax = 0truetrue
all years fedTax >= 0truetrue
all years cgTax >= 0truetrue
all years niitTax >= 0truetrue
roth bucket monotonically non-decreasingtruetrue

Lees Cruise 201/201

TestExpectedActualResult
Y0 rmd === 0truetrue
Y1 rmd === 0truetrue
Y2 rmd === 0truetrue
Y3 rmd === 0truetrue
Y4 rmd === 0truetrue
Y5 rmd === 0truetrue
Y6 rmd === 0truetrue
Y7 rmd === 0truetrue
Y8 rmd === 0truetrue
Y9 rmd === 0truetrue
Y10 rmd === 0truetrue
Y11 rmd === 0truetrue
Y12 rmd === 0truetrue
Y13 rmd === 0truetrue
Y14 rmd === 0truetrue
Y15 rmd === 0truetrue
Y16 rmd === 0truetrue
Y17 rmd === 0truetrue
Y18 rmd === 0truetrue
Y19 rmd === 0truetrue
Y20 rmd === 0truetrue
Y21 rmd === 0truetrue
Y22 rmd === 0truetrue
Y23 rmd === 0truetrue
Y24 rmd === 0truetrue
Y25 rmd === 0truetrue
Y26 rmd === 0truetrue
Y27 rmd === 0truetrue
Y28 rmd === 0truetrue
Y29 rmd === 0truetrue
Y30 rmd === 0truetrue
Y31 rmd === 0truetrue
Y32 rmd === 0truetrue
Y33 rmd === 0truetrue
Y34 rmd === 0truetrue
Y35 rmd === 0truetrue
Y36 rmd === 0truetrue
Y12 AGI === ssTaxabletruetrue
Y12 fedTax === 0truetrue
Y12 stateTax === 0truetrue
Y12 withdrawal === expenses − sstruetrue
Y13 AGI === ssTaxabletruetrue
Y13 fedTax === 0truetrue
Y13 stateTax === 0truetrue
Y13 withdrawal === expenses − sstruetrue
Y14 AGI === ssTaxabletruetrue
Y14 fedTax === 0truetrue
Y14 stateTax === 0truetrue
Y14 withdrawal === expenses − sstruetrue
Y15 AGI === ssTaxabletruetrue
Y15 fedTax === 0truetrue
Y15 stateTax === 0truetrue
Y15 withdrawal === expenses − sstruetrue
Y17 AGI === ssTaxabletruetrue
Y17 fedTax === 0truetrue
Y17 stateTax === 0truetrue
Y17 withdrawal === expenses − sstruetrue
Y18 AGI === ssTaxabletruetrue
Y18 fedTax === 0truetrue
Y18 stateTax === 0truetrue
Y18 withdrawal === expenses − sstruetrue
Y19 AGI === ssTaxabletruetrue
Y19 fedTax === 0truetrue
Y19 stateTax === 0truetrue
Y19 withdrawal === expenses − sstruetrue
Y20 AGI === ssTaxabletruetrue
Y20 fedTax === 0truetrue
Y20 stateTax === 0truetrue
Y20 withdrawal === expenses − sstruetrue
Y21 AGI === ssTaxabletruetrue
Y21 fedTax === 0truetrue
Y21 stateTax === 0truetrue
Y21 withdrawal === expenses − sstruetrue
Y22 AGI === ssTaxabletruetrue
Y22 fedTax === 0truetrue
Y22 stateTax === 0truetrue
Y22 withdrawal === expenses − sstruetrue
Y23 AGI === ssTaxabletruetrue
Y23 fedTax === 0truetrue
Y23 stateTax === 0truetrue
Y23 withdrawal === expenses − sstruetrue
Y24 AGI === ssTaxabletruetrue
Y24 fedTax === 0truetrue
Y24 stateTax === 0truetrue
Y24 withdrawal === expenses − sstruetrue
Y25 AGI === ssTaxabletruetrue
Y25 fedTax === 0truetrue
Y25 stateTax === 0truetrue
Y25 withdrawal === expenses − sstruetrue
Y26 AGI === ssTaxabletruetrue
Y26 fedTax === 0truetrue
Y26 stateTax === 0truetrue
Y26 withdrawal === expenses − sstruetrue
Y27 AGI === ssTaxabletruetrue
Y27 fedTax === 0truetrue
Y27 stateTax === 0truetrue
Y27 withdrawal === expenses − sstruetrue
Y28 AGI === ssTaxabletruetrue
Y28 fedTax === 0truetrue
Y28 stateTax === 0truetrue
Y28 withdrawal === expenses − sstruetrue
Y29 AGI === ssTaxabletruetrue
Y29 fedTax === 0truetrue
Y29 stateTax === 0truetrue
Y29 withdrawal === expenses − sstruetrue
Y30 AGI === ssTaxabletruetrue
Y30 fedTax === 0truetrue
Y30 stateTax === 0truetrue
Y30 withdrawal === expenses − sstruetrue
Y31 AGI === ssTaxabletruetrue
Y31 fedTax === 0truetrue
Y31 stateTax === 0truetrue
Y31 withdrawal === expenses − sstruetrue
Y32 AGI === ssTaxabletruetrue
Y32 fedTax === 0truetrue
Y32 stateTax === 0truetrue
Y32 withdrawal === expenses − sstruetrue
Y33 AGI === ssTaxabletruetrue
Y33 fedTax === 0truetrue
Y33 stateTax === 0truetrue
Y33 withdrawal === expenses − sstruetrue
Y34 AGI === ssTaxabletruetrue
Y34 fedTax === 0truetrue
Y34 stateTax === 0truetrue
Y34 withdrawal === expenses − sstruetrue
Y35 AGI === ssTaxabletruetrue
Y35 fedTax === 0truetrue
Y35 stateTax === 0truetrue
Y35 withdrawal === expenses − sstruetrue
Y1 ss === 0truetrue
Y1 ssTaxable === 0truetrue
Y2 ss === 0truetrue
Y2 ssTaxable === 0truetrue
Y4 ss === 0truetrue
Y4 ssTaxable === 0truetrue
Y6 ss === 0truetrue
Y6 ssTaxable === 0truetrue
Y7 ss === 0truetrue
Y7 ssTaxable === 0truetrue
Y8 ss === 0truetrue
Y8 ssTaxable === 0truetrue
Y9 ss === 0truetrue
Y9 ssTaxable === 0truetrue
Y12 ss > Y11 sstruetrue
Y13 ss > Y12 sstruetrue
Y14 ss > Y13 sstruetrue
Y15 ss > Y14 sstruetrue
Y17 ss > Y16 sstruetrue
Y18 ss > Y17 sstruetrue
Y19 ss > Y18 sstruetrue
Y20 ss > Y19 sstruetrue
Y21 ss > Y20 sstruetrue
Y22 ss > Y21 sstruetrue
Y23 ss > Y22 sstruetrue
Y24 ss > Y23 sstruetrue
Y25 ss > Y24 sstruetrue
Y26 ss > Y25 sstruetrue
Y27 ss > Y26 sstruetrue
Y28 ss > Y27 sstruetrue
Y29 ss > Y28 sstruetrue
Y30 ss > Y29 sstruetrue
Y31 ss > Y30 sstruetrue
Y32 ss > Y31 sstruetrue
Y33 ss > Y32 sstruetrue
Y34 ss > Y33 sstruetrue
Y35 ss > Y34 sstruetrue
Y8 medicareCost > Y7 medicareCosttruetrue
Y9 medicareCost > Y8 medicareCosttruetrue
Y10 medicareCost > Y9 medicareCosttruetrue
Y12 medicareCost > Y11 medicareCosttruetrue
Y13 medicareCost > Y12 medicareCosttruetrue
Y14 medicareCost > Y13 medicareCosttruetrue
Y15 medicareCost > Y14 medicareCosttruetrue
Y17 medicareCost > Y16 medicareCosttruetrue
Y18 medicareCost > Y17 medicareCosttruetrue
Y19 medicareCost > Y18 medicareCosttruetrue
Y20 medicareCost > Y19 medicareCosttruetrue
Y21 medicareCost > Y20 medicareCosttruetrue
Y22 medicareCost > Y21 medicareCosttruetrue
Y23 medicareCost > Y22 medicareCosttruetrue
Y24 medicareCost > Y23 medicareCosttruetrue
Y25 medicareCost > Y24 medicareCosttruetrue
Y26 medicareCost > Y25 medicareCosttruetrue
Y27 medicareCost > Y26 medicareCosttruetrue
Y28 medicareCost > Y27 medicareCosttruetrue
Y29 medicareCost > Y28 medicareCosttruetrue
Y30 medicareCost > Y29 medicareCosttruetrue
Y31 medicareCost > Y30 medicareCosttruetrue
Y32 medicareCost > Y31 medicareCosttruetrue
Y33 medicareCost > Y32 medicareCosttruetrue
Y34 medicareCost > Y33 medicareCosttruetrue
Y35 medicareCost > Y34 medicareCosttruetrue
taxConvergenceFlag === false across full projectiontruetrue
niitTax === 0 from Y8 onwardtruetrue
irmaaBracket === 0 across all yearstruetrue
rmdRequired === false across all yearstruetrue
roth balance > 0 across all yearstruetrue
preTax === 0 from Y12 onwardtruetrue
age increments by 1 each yeartruetrue
spAge increments by 1 each yeartruetrue
age[36] === endAge 95truetrue

Washingtons Cruise 1154/1154

TestExpectedActualResult
Y0 age === 63truetrue
Y0 spAge === 61truetrue
Y1 age === 64truetrue
Y1 spAge === 62truetrue
Y2 age === 65truetrue
Y2 spAge === 63truetrue
Y3 age === 66truetrue
Y3 spAge === 64truetrue
Y4 age === 67truetrue
Y4 spAge === 65truetrue
Y5 age === 68truetrue
Y5 spAge === 66truetrue
Y6 age === 69truetrue
Y6 spAge === 67truetrue
Y7 age === 70truetrue
Y7 spAge === 68truetrue
Y8 age === 71truetrue
Y8 spAge === 69truetrue
Y9 age === 72truetrue
Y9 spAge === 70truetrue
Y10 age === 73truetrue
Y10 spAge === 71truetrue
Y11 age === 74truetrue
Y11 spAge === 72truetrue
Y12 age === 75truetrue
Y12 spAge === 73truetrue
Y13 age === 76truetrue
Y13 spAge === 74truetrue
Y14 age === 77truetrue
Y14 spAge === 75truetrue
Y15 age === 78truetrue
Y15 spAge === 76truetrue
Y16 age === 79truetrue
Y16 spAge === 77truetrue
Y17 age === 80truetrue
Y17 spAge === 78truetrue
Y18 age === 81truetrue
Y18 spAge === 79truetrue
Y19 age === 82truetrue
Y19 spAge === 80truetrue
Y20 age === 83truetrue
Y20 spAge === 81truetrue
Y21 age === 84truetrue
Y21 spAge === 82truetrue
Y22 age === 85truetrue
Y22 spAge === 83truetrue
Y23 age === 86truetrue
Y23 spAge === 84truetrue
Y24 age === 87truetrue
Y24 spAge === 85truetrue
Y25 age === 88truetrue
Y25 spAge === 86truetrue
Y26 age === 89truetrue
Y26 spAge === 87truetrue
Y27 age === 90truetrue
Y27 spAge === 88truetrue
Y28 age === 91truetrue
Y28 spAge === 89truetrue
Y29 age === 92truetrue
Y29 spAge === 90truetrue
Y30 age === 93truetrue
Y30 spAge === 91truetrue
Y31 age === 94truetrue
Y31 spAge === 92truetrue
Y32 age === 95truetrue
Y32 spAge === 93truetrue
Y0 isSingle === nulltruetrue
Y0 primaryDead === falsetruetrue
Y0 spouseDead === falsetruetrue
Y1 isSingle === nulltruetrue
Y1 primaryDead === falsetruetrue
Y1 spouseDead === falsetruetrue
Y2 isSingle === nulltruetrue
Y2 primaryDead === falsetruetrue
Y2 spouseDead === falsetruetrue
Y3 isSingle === nulltruetrue
Y3 primaryDead === falsetruetrue
Y3 spouseDead === falsetruetrue
Y4 isSingle === nulltruetrue
Y4 primaryDead === falsetruetrue
Y4 spouseDead === falsetruetrue
Y5 isSingle === nulltruetrue
Y5 primaryDead === falsetruetrue
Y5 spouseDead === falsetruetrue
Y6 isSingle === nulltruetrue
Y6 primaryDead === falsetruetrue
Y6 spouseDead === falsetruetrue
Y7 isSingle === nulltruetrue
Y7 primaryDead === falsetruetrue
Y7 spouseDead === falsetruetrue
Y8 isSingle === nulltruetrue
Y8 primaryDead === falsetruetrue
Y8 spouseDead === falsetruetrue
Y9 isSingle === nulltruetrue
Y9 primaryDead === falsetruetrue
Y9 spouseDead === falsetruetrue
Y10 isSingle === nulltruetrue
Y10 primaryDead === falsetruetrue
Y10 spouseDead === falsetruetrue
Y11 isSingle === nulltruetrue
Y11 primaryDead === falsetruetrue
Y11 spouseDead === falsetruetrue
Y12 isSingle === nulltruetrue
Y12 primaryDead === falsetruetrue
Y12 spouseDead === falsetruetrue
Y13 isSingle === nulltruetrue
Y13 primaryDead === falsetruetrue
Y13 spouseDead === falsetruetrue
Y14 isSingle === nulltruetrue
Y14 primaryDead === falsetruetrue
Y14 spouseDead === falsetruetrue
Y15 isSingle === nulltruetrue
Y15 primaryDead === falsetruetrue
Y15 spouseDead === falsetruetrue
Y16 isSingle === nulltruetrue
Y16 primaryDead === falsetruetrue
Y16 spouseDead === falsetruetrue
Y17 isSingle === nulltruetrue
Y17 primaryDead === falsetruetrue
Y17 spouseDead === falsetruetrue
Y18 isSingle === nulltruetrue
Y18 primaryDead === falsetruetrue
Y18 spouseDead === falsetruetrue
Y19 isSingle === nulltruetrue
Y19 primaryDead === falsetruetrue
Y19 spouseDead === falsetruetrue
Y20 isSingle === nulltruetrue
Y20 primaryDead === falsetruetrue
Y20 spouseDead === falsetruetrue
Y21 isSingle === nulltruetrue
Y21 primaryDead === falsetruetrue
Y21 spouseDead === falsetruetrue
Y22 isSingle === nulltruetrue
Y22 primaryDead === falsetruetrue
Y22 spouseDead === falsetruetrue
Y23 isSingle === nulltruetrue
Y23 primaryDead === falsetruetrue
Y23 spouseDead === falsetruetrue
Y24 isSingle === nulltruetrue
Y24 primaryDead === falsetruetrue
Y24 spouseDead === falsetruetrue
Y25 isSingle === nulltruetrue
Y25 primaryDead === falsetruetrue
Y25 spouseDead === falsetruetrue
Y26 isSingle === nulltruetrue
Y26 primaryDead === falsetruetrue
Y26 spouseDead === falsetruetrue
Y27 isSingle === nulltruetrue
Y27 primaryDead === falsetruetrue
Y27 spouseDead === falsetruetrue
Y28 isSingle === nulltruetrue
Y28 primaryDead === falsetruetrue
Y28 spouseDead === falsetruetrue
Y29 isSingle === nulltruetrue
Y29 primaryDead === falsetruetrue
Y29 spouseDead === falsetruetrue
Y30 isSingle === nulltruetrue
Y30 primaryDead === falsetruetrue
Y30 spouseDead === falsetruetrue
Y31 isSingle === nulltruetrue
Y31 primaryDead === falsetruetrue
Y31 spouseDead === falsetruetrue
Y32 isSingle === nulltruetrue
Y32 primaryDead === falsetruetrue
Y32 spouseDead === falsetruetrue
Y0 taxConvergenceFlag === falsetruetrue
Y1 taxConvergenceFlag === falsetruetrue
Y2 taxConvergenceFlag === falsetruetrue
Y3 taxConvergenceFlag === falsetruetrue
Y4 taxConvergenceFlag === falsetruetrue
Y5 taxConvergenceFlag === falsetruetrue
Y6 taxConvergenceFlag === falsetruetrue
Y7 taxConvergenceFlag === falsetruetrue
Y8 taxConvergenceFlag === falsetruetrue
Y9 taxConvergenceFlag === falsetruetrue
Y10 taxConvergenceFlag === falsetruetrue
Y11 taxConvergenceFlag === falsetruetrue
Y12 taxConvergenceFlag === truetruetrue
Y13 taxConvergenceFlag === falsetruetrue
Y14 taxConvergenceFlag === falsetruetrue
Y15 taxConvergenceFlag === falsetruetrue
Y16 taxConvergenceFlag === falsetruetrue
Y17 taxConvergenceFlag === falsetruetrue
Y18 taxConvergenceFlag === falsetruetrue
Y19 taxConvergenceFlag === truetruetrue
Y20 taxConvergenceFlag === falsetruetrue
Y21 taxConvergenceFlag === falsetruetrue
Y22 taxConvergenceFlag === truetruetrue
Y23 taxConvergenceFlag === falsetruetrue
Y24 taxConvergenceFlag === truetruetrue
Y25 taxConvergenceFlag === falsetruetrue
Y26 taxConvergenceFlag === falsetruetrue
Y27 taxConvergenceFlag === falsetruetrue
Y28 taxConvergenceFlag === falsetruetrue
Y29 taxConvergenceFlag === falsetruetrue
Y30 taxConvergenceFlag === falsetruetrue
Y31 taxConvergenceFlag === falsetruetrue
Y32 taxConvergenceFlag === falsetruetrue
Y0 primaryEarned > 0truetrue
Y0 spouseEarned > 0truetrue
Y0 earned > 0truetrue
Y0 fica > 0truetrue
Y1 primaryEarned > 0truetrue
Y1 spouseEarned > 0truetrue
Y1 earned > 0truetrue
Y1 fica > 0truetrue
Y2 primaryEarned === 0truetrue
Y2 spouseEarned > 0truetrue
Y2 earned > 0truetrue
Y2 fica > 0truetrue
Y3 primaryEarned === 0truetrue
Y3 spouseEarned > 0truetrue
Y3 earned > 0truetrue
Y3 fica > 0truetrue
Y4 primaryEarned === 0truetrue
Y4 spouseEarned === 0truetrue
Y4 earned === 0truetrue
Y4 fica === 0truetrue
Y5 primaryEarned === 0truetrue
Y5 spouseEarned === 0truetrue
Y5 earned === 0truetrue
Y5 fica === 0truetrue
Y6 primaryEarned === 0truetrue
Y6 spouseEarned === 0truetrue
Y6 earned === 0truetrue
Y6 fica === 0truetrue
Y7 primaryEarned === 0truetrue
Y7 spouseEarned === 0truetrue
Y7 earned === 0truetrue
Y7 fica === 0truetrue
Y8 primaryEarned === 0truetrue
Y8 spouseEarned === 0truetrue
Y8 earned === 0truetrue
Y8 fica === 0truetrue
Y9 primaryEarned === 0truetrue
Y9 spouseEarned === 0truetrue
Y9 earned === 0truetrue
Y9 fica === 0truetrue
Y10 primaryEarned === 0truetrue
Y10 spouseEarned === 0truetrue
Y10 earned === 0truetrue
Y10 fica === 0truetrue
Y11 primaryEarned === 0truetrue
Y11 spouseEarned === 0truetrue
Y11 earned === 0truetrue
Y11 fica === 0truetrue
Y12 primaryEarned === 0truetrue
Y12 spouseEarned === 0truetrue
Y12 earned === 0truetrue
Y12 fica === 0truetrue
Y13 primaryEarned === 0truetrue
Y13 spouseEarned === 0truetrue
Y13 earned === 0truetrue
Y13 fica === 0truetrue
Y14 primaryEarned === 0truetrue
Y14 spouseEarned === 0truetrue
Y14 earned === 0truetrue
Y14 fica === 0truetrue
Y15 primaryEarned === 0truetrue
Y15 spouseEarned === 0truetrue
Y15 earned === 0truetrue
Y15 fica === 0truetrue
Y16 primaryEarned === 0truetrue
Y16 spouseEarned === 0truetrue
Y16 earned === 0truetrue
Y16 fica === 0truetrue
Y17 primaryEarned === 0truetrue
Y17 spouseEarned === 0truetrue
Y17 earned === 0truetrue
Y17 fica === 0truetrue
Y18 primaryEarned === 0truetrue
Y18 spouseEarned === 0truetrue
Y18 earned === 0truetrue
Y18 fica === 0truetrue
Y19 primaryEarned === 0truetrue
Y19 spouseEarned === 0truetrue
Y19 earned === 0truetrue
Y19 fica === 0truetrue
Y20 primaryEarned === 0truetrue
Y20 spouseEarned === 0truetrue
Y20 earned === 0truetrue
Y20 fica === 0truetrue
Y21 primaryEarned === 0truetrue
Y21 spouseEarned === 0truetrue
Y21 earned === 0truetrue
Y21 fica === 0truetrue
Y22 primaryEarned === 0truetrue
Y22 spouseEarned === 0truetrue
Y22 earned === 0truetrue
Y22 fica === 0truetrue
Y23 primaryEarned === 0truetrue
Y23 spouseEarned === 0truetrue
Y23 earned === 0truetrue
Y23 fica === 0truetrue
Y24 primaryEarned === 0truetrue
Y24 spouseEarned === 0truetrue
Y24 earned === 0truetrue
Y24 fica === 0truetrue
Y25 primaryEarned === 0truetrue
Y25 spouseEarned === 0truetrue
Y25 earned === 0truetrue
Y25 fica === 0truetrue
Y26 primaryEarned === 0truetrue
Y26 spouseEarned === 0truetrue
Y26 earned === 0truetrue
Y26 fica === 0truetrue
Y27 primaryEarned === 0truetrue
Y27 spouseEarned === 0truetrue
Y27 earned === 0truetrue
Y27 fica === 0truetrue
Y28 primaryEarned === 0truetrue
Y28 spouseEarned === 0truetrue
Y28 earned === 0truetrue
Y28 fica === 0truetrue
Y29 primaryEarned === 0truetrue
Y29 spouseEarned === 0truetrue
Y29 earned === 0truetrue
Y29 fica === 0truetrue
Y30 primaryEarned === 0truetrue
Y30 spouseEarned === 0truetrue
Y30 earned === 0truetrue
Y30 fica === 0truetrue
Y31 primaryEarned === 0truetrue
Y31 spouseEarned === 0truetrue
Y31 earned === 0truetrue
Y31 fica === 0truetrue
Y32 primaryEarned === 0truetrue
Y32 spouseEarned === 0truetrue
Y32 earned === 0truetrue
Y32 fica === 0truetrue
Y0 retired === nulltruetrue
Y1 retired === nulltruetrue
Y2 retired === truetruetrue
Y3 retired === truetruetrue
Y4 retired === truetruetrue
Y5 retired === truetruetrue
Y6 retired === truetruetrue
Y7 retired === truetruetrue
Y8 retired === truetruetrue
Y9 retired === truetruetrue
Y10 retired === truetruetrue
Y11 retired === truetruetrue
Y12 retired === truetruetrue
Y13 retired === truetruetrue
Y14 retired === truetruetrue
Y15 retired === truetruetrue
Y16 retired === truetruetrue
Y17 retired === truetruetrue
Y18 retired === truetruetrue
Y19 retired === truetruetrue
Y20 retired === truetruetrue
Y21 retired === truetruetrue
Y22 retired === truetruetrue
Y23 retired === truetruetrue
Y24 retired === truetruetrue
Y25 retired === truetruetrue
Y26 retired === truetruetrue
Y27 retired === truetruetrue
Y28 retired === truetruetrue
Y29 retired === truetruetrue
Y30 retired === truetruetrue
Y31 retired === truetruetrue
Y32 retired === truetruetrue
Y0 pension === 0truetrue
Y1 pension === 0truetrue
Y2 pension === pensionTaxabletruetrue
Y3 pension === pensionTaxabletruetrue
Y4 pension === pensionTaxabletruetrue
Y5 pension === pensionTaxabletruetrue
Y6 pension === pensionTaxabletruetrue
Y7 pension === pensionTaxabletruetrue
Y8 pension === pensionTaxabletruetrue
Y9 pension === pensionTaxabletruetrue
Y10 pension === pensionTaxabletruetrue
Y11 pension === pensionTaxabletruetrue
Y12 pension === pensionTaxabletruetrue
Y13 pension === pensionTaxabletruetrue
Y14 pension === pensionTaxabletruetrue
Y15 pension === pensionTaxabletruetrue
Y16 pension === pensionTaxabletruetrue
Y17 pension === pensionTaxabletruetrue
Y18 pension === pensionTaxabletruetrue
Y19 pension === pensionTaxabletruetrue
Y20 pension === pensionTaxabletruetrue
Y21 pension === pensionTaxabletruetrue
Y22 pension === pensionTaxabletruetrue
Y23 pension === pensionTaxabletruetrue
Y24 pension === pensionTaxabletruetrue
Y25 pension === pensionTaxabletruetrue
Y26 pension === pensionTaxabletruetrue
Y27 pension === pensionTaxabletruetrue
Y28 pension === pensionTaxabletruetrue
Y29 pension === pensionTaxabletruetrue
Y30 pension === pensionTaxabletruetrue
Y31 pension === pensionTaxabletruetrue
Y32 pension === pensionTaxabletruetrue
Y3 pension >= Y2 pension (monotone COLA)truetrue
Y4 pension >= Y3 pension (monotone COLA)truetrue
Y5 pension >= Y4 pension (monotone COLA)truetrue
Y6 pension >= Y5 pension (monotone COLA)truetrue
Y7 pension >= Y6 pension (monotone COLA)truetrue
Y8 pension >= Y7 pension (monotone COLA)truetrue
Y9 pension >= Y8 pension (monotone COLA)truetrue
Y10 pension >= Y9 pension (monotone COLA)truetrue
Y11 pension >= Y10 pension (monotone COLA)truetrue
Y12 pension >= Y11 pension (monotone COLA)truetrue
Y13 pension >= Y12 pension (monotone COLA)truetrue
Y14 pension >= Y13 pension (monotone COLA)truetrue
Y15 pension >= Y14 pension (monotone COLA)truetrue
Y16 pension >= Y15 pension (monotone COLA)truetrue
Y17 pension >= Y16 pension (monotone COLA)truetrue
Y18 pension >= Y17 pension (monotone COLA)truetrue
Y19 pension >= Y18 pension (monotone COLA)truetrue
Y20 pension >= Y19 pension (monotone COLA)truetrue
Y21 pension >= Y20 pension (monotone COLA)truetrue
Y22 pension >= Y21 pension (monotone COLA)truetrue
Y23 pension >= Y22 pension (monotone COLA)truetrue
Y24 pension >= Y23 pension (monotone COLA)truetrue
Y25 pension >= Y24 pension (monotone COLA)truetrue
Y26 pension >= Y25 pension (monotone COLA)truetrue
Y27 pension >= Y26 pension (monotone COLA)truetrue
Y28 pension >= Y27 pension (monotone COLA)truetrue
Y29 pension >= Y28 pension (monotone COLA)truetrue
Y30 pension >= Y29 pension (monotone COLA)truetrue
Y31 pension >= Y30 pension (monotone COLA)truetrue
Y32 pension >= Y31 pension (monotone COLA)truetrue
Y0 ss === 0truetrue
Y1 ss === 0truetrue
Y2 ss === 0truetrue
Y3 ss === 0truetrue
Y4 ss === 0truetrue
Y5 ss === 0truetrue
Y6 ss > 0truetrue
Y7 ss > 0truetrue
Y8 ss > 0truetrue
Y9 ss > 0truetrue
Y10 ss > 0truetrue
Y11 ss > 0truetrue
Y12 ss > 0truetrue
Y13 ss > 0truetrue
Y14 ss > 0truetrue
Y15 ss > 0truetrue
Y16 ss > 0truetrue
Y17 ss > 0truetrue
Y18 ss > 0truetrue
Y19 ss > 0truetrue
Y20 ss > 0truetrue
Y21 ss > 0truetrue
Y22 ss > 0truetrue
Y23 ss > 0truetrue
Y24 ss > 0truetrue
Y25 ss > 0truetrue
Y26 ss > 0truetrue
Y27 ss > 0truetrue
Y28 ss > 0truetrue
Y29 ss > 0truetrue
Y30 ss > 0truetrue
Y31 ss > 0truetrue
Y32 ss > 0truetrue
Y7 ss > Y6 ss (primary onset jump)truetrue
Y8 ss >= Y7 ss (monotone after both claim)truetrue
Y9 ss >= Y8 ss (monotone after both claim)truetrue
Y10 ss >= Y9 ss (monotone after both claim)truetrue
Y11 ss >= Y10 ss (monotone after both claim)truetrue
Y12 ss >= Y11 ss (monotone after both claim)truetrue
Y13 ss >= Y12 ss (monotone after both claim)truetrue
Y14 ss >= Y13 ss (monotone after both claim)truetrue
Y15 ss >= Y14 ss (monotone after both claim)truetrue
Y16 ss >= Y15 ss (monotone after both claim)truetrue
Y17 ss >= Y16 ss (monotone after both claim)truetrue
Y18 ss >= Y17 ss (monotone after both claim)truetrue
Y19 ss >= Y18 ss (monotone after both claim)truetrue
Y20 ss >= Y19 ss (monotone after both claim)truetrue
Y21 ss >= Y20 ss (monotone after both claim)truetrue
Y22 ss >= Y21 ss (monotone after both claim)truetrue
Y23 ss >= Y22 ss (monotone after both claim)truetrue
Y24 ss >= Y23 ss (monotone after both claim)truetrue
Y25 ss >= Y24 ss (monotone after both claim)truetrue
Y26 ss >= Y25 ss (monotone after both claim)truetrue
Y27 ss >= Y26 ss (monotone after both claim)truetrue
Y28 ss >= Y27 ss (monotone after both claim)truetrue
Y29 ss >= Y28 ss (monotone after both claim)truetrue
Y30 ss >= Y29 ss (monotone after both claim)truetrue
Y31 ss >= Y30 ss (monotone after both claim)truetrue
Y32 ss >= Y31 ss (monotone after both claim)truetrue
Y0 rmd === 0truetrue
Y0 rmdRequired === falsetruetrue
Y0 rmdReinvested === 0truetrue
Y1 rmd === 0truetrue
Y1 rmdRequired === falsetruetrue
Y1 rmdReinvested === 0truetrue
Y2 rmd === 0truetrue
Y2 rmdRequired === falsetruetrue
Y2 rmdReinvested === 0truetrue
Y3 rmd === 0truetrue
Y3 rmdRequired === falsetruetrue
Y3 rmdReinvested === 0truetrue
Y4 rmd === 0truetrue
Y4 rmdRequired === falsetruetrue
Y4 rmdReinvested === 0truetrue
Y5 rmd === 0truetrue
Y5 rmdRequired === falsetruetrue
Y5 rmdReinvested === 0truetrue
Y6 rmd === 0truetrue
Y6 rmdRequired === falsetruetrue
Y6 rmdReinvested === 0truetrue
Y7 rmd === 0truetrue
Y7 rmdRequired === falsetruetrue
Y7 rmdReinvested === 0truetrue
Y8 rmd === 0truetrue
Y8 rmdRequired === falsetruetrue
Y8 rmdReinvested === 0truetrue
Y9 rmd === 0truetrue
Y9 rmdRequired === falsetruetrue
Y9 rmdReinvested === 0truetrue
Y10 rmd === 0truetrue
Y10 rmdRequired === falsetruetrue
Y10 rmdReinvested === 0truetrue
Y11 rmd === 0truetrue
Y11 rmdRequired === falsetruetrue
Y11 rmdReinvested === 0truetrue
Y12 rmd > 0truetrue
Y12 rmdRequired === truetruetrue
Y12 rmdReinvested > 0truetrue
Y13 rmd > 0truetrue
Y13 rmdRequired === truetruetrue
Y13 rmdReinvested > 0truetrue
Y14 rmd > 0truetrue
Y14 rmdRequired === truetruetrue
Y14 rmdReinvested > 0truetrue
Y15 rmd > 0truetrue
Y15 rmdRequired === truetruetrue
Y15 rmdReinvested > 0truetrue
Y16 rmd > 0truetrue
Y16 rmdRequired === truetruetrue
Y16 rmdReinvested > 0truetrue
Y17 rmd > 0truetrue
Y17 rmdRequired === truetruetrue
Y17 rmdReinvested > 0truetrue
Y18 rmd > 0truetrue
Y18 rmdRequired === truetruetrue
Y18 rmdReinvested > 0truetrue
Y19 rmd > 0truetrue
Y19 rmdRequired === truetruetrue
Y19 rmdReinvested > 0truetrue
Y20 rmd > 0truetrue
Y20 rmdRequired === truetruetrue
Y20 rmdReinvested > 0truetrue
Y21 rmd > 0truetrue
Y21 rmdRequired === truetruetrue
Y21 rmdReinvested > 0truetrue
Y22 rmd > 0truetrue
Y22 rmdRequired === truetruetrue
Y22 rmdReinvested === 0 (LTC final year consumes full RMD)truetrue
Y23 rmd > 0truetrue
Y23 rmdRequired === truetruetrue
Y23 rmdReinvested > 0truetrue
Y24 rmd > 0truetrue
Y24 rmdRequired === truetruetrue
Y24 rmdReinvested > 0truetrue
Y25 rmd > 0truetrue
Y25 rmdRequired === truetruetrue
Y25 rmdReinvested > 0truetrue
Y26 rmd > 0truetrue
Y26 rmdRequired === truetruetrue
Y26 rmdReinvested > 0truetrue
Y27 rmd > 0truetrue
Y27 rmdRequired === truetruetrue
Y27 rmdReinvested > 0truetrue
Y28 rmd > 0truetrue
Y28 rmdRequired === truetruetrue
Y28 rmdReinvested > 0truetrue
Y29 rmd > 0truetrue
Y29 rmdRequired === truetruetrue
Y29 rmdReinvested > 0truetrue
Y30 rmd > 0truetrue
Y30 rmdRequired === truetruetrue
Y30 rmdReinvested > 0truetrue
Y31 rmd > 0truetrue
Y31 rmdRequired === truetruetrue
Y31 rmdReinvested > 0truetrue
Y32 rmd > 0truetrue
Y32 rmdRequired === truetruetrue
Y32 rmdReinvested > 0truetrue
Y0 rmdSpouse === 0truetrue
Y0 rmdPrimary === rmdtruetrue
Y1 rmdSpouse === 0truetrue
Y1 rmdPrimary === rmdtruetrue
Y2 rmdSpouse === 0truetrue
Y2 rmdPrimary === rmdtruetrue
Y3 rmdSpouse === 0truetrue
Y3 rmdPrimary === rmdtruetrue
Y4 rmdSpouse === 0truetrue
Y4 rmdPrimary === rmdtruetrue
Y5 rmdSpouse === 0truetrue
Y5 rmdPrimary === rmdtruetrue
Y6 rmdSpouse === 0truetrue
Y6 rmdPrimary === rmdtruetrue
Y7 rmdSpouse === 0truetrue
Y7 rmdPrimary === rmdtruetrue
Y8 rmdSpouse === 0truetrue
Y8 rmdPrimary === rmdtruetrue
Y9 rmdSpouse === 0truetrue
Y9 rmdPrimary === rmdtruetrue
Y10 rmdSpouse === 0truetrue
Y10 rmdPrimary === rmdtruetrue
Y11 rmdSpouse === 0truetrue
Y11 rmdPrimary === rmdtruetrue
Y12 rmdSpouse === 0truetrue
Y12 rmdPrimary === rmdtruetrue
Y13 rmdSpouse === 0truetrue
Y13 rmdPrimary === rmdtruetrue
Y14 rmdSpouse === 0truetrue
Y14 rmdPrimary === rmdtruetrue
Y15 rmdSpouse === 0truetrue
Y15 rmdPrimary === rmdtruetrue
Y16 rmdSpouse === 0truetrue
Y16 rmdPrimary === rmdtruetrue
Y17 rmdSpouse === 0truetrue
Y17 rmdPrimary === rmdtruetrue
Y18 rmdSpouse === 0truetrue
Y18 rmdPrimary === rmdtruetrue
Y19 rmdSpouse === 0truetrue
Y19 rmdPrimary === rmdtruetrue
Y20 rmdSpouse === 0truetrue
Y20 rmdPrimary === rmdtruetrue
Y21 rmdSpouse === 0truetrue
Y21 rmdPrimary === rmdtruetrue
Y22 rmdSpouse === 0truetrue
Y22 rmdPrimary === rmdtruetrue
Y23 rmdSpouse === 0truetrue
Y23 rmdPrimary === rmdtruetrue
Y24 rmdSpouse === 0truetrue
Y24 rmdPrimary === rmdtruetrue
Y25 rmdSpouse === 0truetrue
Y25 rmdPrimary === rmdtruetrue
Y26 rmdSpouse === 0truetrue
Y26 rmdPrimary === rmdtruetrue
Y27 rmdSpouse === 0truetrue
Y27 rmdPrimary === rmdtruetrue
Y28 rmdSpouse === 0truetrue
Y28 rmdPrimary === rmdtruetrue
Y29 rmdSpouse === 0truetrue
Y29 rmdPrimary === rmdtruetrue
Y30 rmdSpouse === 0truetrue
Y30 rmdPrimary === rmdtruetrue
Y31 rmdSpouse === 0truetrue
Y31 rmdPrimary === rmdtruetrue
Y32 rmdSpouse === 0truetrue
Y32 rmdPrimary === rmdtruetrue
Y0 irmaa === 0truetrue
Y0 irmaaBracket === 0truetrue
Y1 irmaa === 0truetrue
Y1 irmaaBracket === 0truetrue
Y2 irmaa === 0truetrue
Y2 irmaaBracket === 0truetrue
Y3 irmaa === 0truetrue
Y3 irmaaBracket === 0truetrue
Y4 irmaa === 0truetrue
Y4 irmaaBracket === 0truetrue
Y5 irmaa === 0truetrue
Y5 irmaaBracket === 0truetrue
Y6 irmaa === 0truetrue
Y6 irmaaBracket === 0truetrue
Y7 irmaa === 0truetrue
Y7 irmaaBracket === 0truetrue
Y8 irmaa === 0truetrue
Y8 irmaaBracket === 0truetrue
Y9 irmaa === 0truetrue
Y9 irmaaBracket === 0truetrue
Y10 irmaa === 0truetrue
Y10 irmaaBracket === 0truetrue
Y11 irmaa === 0truetrue
Y11 irmaaBracket === 0truetrue
Y12 irmaa === 0truetrue
Y12 irmaaBracket === 0truetrue
Y13 irmaa === 0truetrue
Y13 irmaaBracket === 0truetrue
Y14 irmaa === 0truetrue
Y14 irmaaBracket === 0truetrue
Y15 irmaa === 0truetrue
Y15 irmaaBracket === 0truetrue
Y16 irmaa === 0truetrue
Y16 irmaaBracket === 0truetrue
Y17 irmaa === 0truetrue
Y17 irmaaBracket === 0truetrue
Y18 irmaa === 0truetrue
Y18 irmaaBracket === 0truetrue
Y19 irmaa === 0truetrue
Y19 irmaaBracket === 0truetrue
Y20 irmaa === 0truetrue
Y20 irmaaBracket === 0truetrue
Y21 irmaa > 0truetrue
Y21 irmaaBracket === 1truetrue
Y22 irmaa > 0truetrue
Y22 irmaaBracket === 1truetrue
Y23 irmaa > 0truetrue
Y23 irmaaBracket === 1truetrue
Y24 irmaa > 0truetrue
Y24 irmaaBracket === 1truetrue
Y25 irmaa === 0truetrue
Y25 irmaaBracket === 0truetrue
Y26 irmaa === 0truetrue
Y26 irmaaBracket === 0truetrue
Y27 irmaa === 0truetrue
Y27 irmaaBracket === 0truetrue
Y28 irmaa === 0truetrue
Y28 irmaaBracket === 0truetrue
Y29 irmaa === 0truetrue
Y29 irmaaBracket === 0truetrue
Y30 irmaa === 0truetrue
Y30 irmaaBracket === 0truetrue
Y31 irmaa === 0truetrue
Y31 irmaaBracket === 0truetrue
Y32 irmaa === 0truetrue
Y32 irmaaBracket === 0truetrue
Y0 medicareCost === 0truetrue
Y1 medicareCost > 0truetrue
Y2 medicareCost > 0truetrue
Y3 medicareCost > 0truetrue
Y4 medicareCost > 0truetrue
Y5 medicareCost > 0truetrue
Y6 medicareCost > 0truetrue
Y7 medicareCost > 0truetrue
Y8 medicareCost > 0truetrue
Y9 medicareCost > 0truetrue
Y10 medicareCost > 0truetrue
Y11 medicareCost > 0truetrue
Y12 medicareCost > 0truetrue
Y13 medicareCost > 0truetrue
Y14 medicareCost > 0truetrue
Y15 medicareCost > 0truetrue
Y16 medicareCost > 0truetrue
Y17 medicareCost > 0truetrue
Y18 medicareCost > 0truetrue
Y19 medicareCost > 0truetrue
Y20 medicareCost > 0truetrue
Y21 medicareCost > 0truetrue
Y22 medicareCost > 0truetrue
Y23 medicareCost > 0truetrue
Y24 medicareCost > 0truetrue
Y25 medicareCost > 0truetrue
Y26 medicareCost > 0truetrue
Y27 medicareCost > 0truetrue
Y28 medicareCost > 0truetrue
Y29 medicareCost > 0truetrue
Y30 medicareCost > 0truetrue
Y31 medicareCost > 0truetrue
Y32 medicareCost > 0truetrue
Y4 medicareCost >= Y3 (tier 0 stable; both enrolled)truetrue
Y5 medicareCost >= Y4 (tier 0 stable; both enrolled)truetrue
Y6 medicareCost >= Y5 (tier 0 stable; both enrolled)truetrue
Y7 medicareCost >= Y6 (tier 0 stable; both enrolled)truetrue
Y8 medicareCost >= Y7 (tier 0 stable; both enrolled)truetrue
Y9 medicareCost >= Y8 (tier 0 stable; both enrolled)truetrue
Y10 medicareCost >= Y9 (tier 0 stable; both enrolled)truetrue
Y11 medicareCost >= Y10 (tier 0 stable; both enrolled)truetrue
Y12 medicareCost >= Y11 (tier 0 stable; both enrolled)truetrue
Y13 medicareCost >= Y12 (tier 0 stable; both enrolled)truetrue
Y14 medicareCost >= Y13 (tier 0 stable; both enrolled)truetrue
Y15 medicareCost >= Y14 (tier 0 stable; both enrolled)truetrue
Y16 medicareCost >= Y15 (tier 0 stable; both enrolled)truetrue
Y17 medicareCost >= Y16 (tier 0 stable; both enrolled)truetrue
Y18 medicareCost >= Y17 (tier 0 stable; both enrolled)truetrue
Y19 medicareCost >= Y18 (tier 0 stable; both enrolled)truetrue
Y20 medicareCost >= Y19 (tier 0 stable; both enrolled)truetrue
Y26 medicareCost >= Y25 (tier 0 post-IRMAA-window)truetrue
Y27 medicareCost >= Y26 (tier 0 post-IRMAA-window)truetrue
Y28 medicareCost >= Y27 (tier 0 post-IRMAA-window)truetrue
Y29 medicareCost >= Y28 (tier 0 post-IRMAA-window)truetrue
Y30 medicareCost >= Y29 (tier 0 post-IRMAA-window)truetrue
Y31 medicareCost >= Y30 (tier 0 post-IRMAA-window)truetrue
Y32 medicareCost >= Y31 (tier 0 post-IRMAA-window)truetrue
Y0 ltcCost === 0truetrue
Y1 ltcCost === 0truetrue
Y2 ltcCost === 0truetrue
Y3 ltcCost === 0truetrue
Y4 ltcCost === 0truetrue
Y5 ltcCost === 0truetrue
Y6 ltcCost === 0truetrue
Y7 ltcCost === 0truetrue
Y8 ltcCost === 0truetrue
Y9 ltcCost === 0truetrue
Y10 ltcCost === 0truetrue
Y11 ltcCost === 0truetrue
Y12 ltcCost === 0truetrue
Y13 ltcCost === 0truetrue
Y14 ltcCost === 0truetrue
Y15 ltcCost === 0truetrue
Y16 ltcCost === 0truetrue
Y17 ltcCost === 0truetrue
Y18 ltcCost === 0truetrue
Y19 ltcCost > 0truetrue
Y20 ltcCost > 0truetrue
Y21 ltcCost > 0truetrue
Y22 ltcCost > 0truetrue
Y23 ltcCost === 0truetrue
Y24 ltcCost === 0truetrue
Y25 ltcCost === 0truetrue
Y26 ltcCost === 0truetrue
Y27 ltcCost === 0truetrue
Y28 ltcCost === 0truetrue
Y29 ltcCost === 0truetrue
Y30 ltcCost === 0truetrue
Y31 ltcCost === 0truetrue
Y32 ltcCost === 0truetrue
Y0 debtPayments > 0truetrue
Y0 debtInterest > 0truetrue
Y0 debtPrincipalPaid > 0truetrue
Y1 debtPayments > 0truetrue
Y1 debtInterest > 0truetrue
Y1 debtPrincipalPaid > 0truetrue
Y2 debtPayments > 0truetrue
Y2 debtInterest > 0truetrue
Y2 debtPrincipalPaid > 0truetrue
Y3 debtPayments > 0truetrue
Y3 debtInterest > 0truetrue
Y3 debtPrincipalPaid > 0truetrue
Y4 debtPayments > 0truetrue
Y4 debtInterest > 0truetrue
Y4 debtPrincipalPaid > 0truetrue
Y5 debtPayments > 0truetrue
Y5 debtInterest > 0truetrue
Y5 debtPrincipalPaid > 0truetrue
Y6 debtPayments > 0truetrue
Y6 debtInterest > 0truetrue
Y6 debtPrincipalPaid > 0truetrue
Y7 debtPayments > 0truetrue
Y7 debtInterest > 0truetrue
Y7 debtPrincipalPaid > 0truetrue
Y8 debtPayments > 0truetrue
Y8 debtInterest > 0truetrue
Y8 debtPrincipalPaid > 0truetrue
Y9 debtPayments > 0truetrue
Y9 debtInterest > 0truetrue
Y9 debtPrincipalPaid > 0truetrue
Y10 debtPayments > 0truetrue
Y10 debtInterest > 0truetrue
Y10 debtPrincipalPaid > 0truetrue
Y11 debtPayments === 0truetrue
Y11 debtInterest === 0truetrue
Y11 debtPrincipalPaid === 0truetrue
Y12 debtPayments === 0truetrue
Y12 debtInterest === 0truetrue
Y12 debtPrincipalPaid === 0truetrue
Y13 debtPayments === 0truetrue
Y13 debtInterest === 0truetrue
Y13 debtPrincipalPaid === 0truetrue
Y14 debtPayments === 0truetrue
Y14 debtInterest === 0truetrue
Y14 debtPrincipalPaid === 0truetrue
Y15 debtPayments === 0truetrue
Y15 debtInterest === 0truetrue
Y15 debtPrincipalPaid === 0truetrue
Y16 debtPayments === 0truetrue
Y16 debtInterest === 0truetrue
Y16 debtPrincipalPaid === 0truetrue
Y17 debtPayments === 0truetrue
Y17 debtInterest === 0truetrue
Y17 debtPrincipalPaid === 0truetrue
Y18 debtPayments === 0truetrue
Y18 debtInterest === 0truetrue
Y18 debtPrincipalPaid === 0truetrue
Y19 debtPayments === 0truetrue
Y19 debtInterest === 0truetrue
Y19 debtPrincipalPaid === 0truetrue
Y20 debtPayments === 0truetrue
Y20 debtInterest === 0truetrue
Y20 debtPrincipalPaid === 0truetrue
Y21 debtPayments === 0truetrue
Y21 debtInterest === 0truetrue
Y21 debtPrincipalPaid === 0truetrue
Y22 debtPayments === 0truetrue
Y22 debtInterest === 0truetrue
Y22 debtPrincipalPaid === 0truetrue
Y23 debtPayments === 0truetrue
Y23 debtInterest === 0truetrue
Y23 debtPrincipalPaid === 0truetrue
Y24 debtPayments === 0truetrue
Y24 debtInterest === 0truetrue
Y24 debtPrincipalPaid === 0truetrue
Y25 debtPayments === 0truetrue
Y25 debtInterest === 0truetrue
Y25 debtPrincipalPaid === 0truetrue
Y26 debtPayments === 0truetrue
Y26 debtInterest === 0truetrue
Y26 debtPrincipalPaid === 0truetrue
Y27 debtPayments === 0truetrue
Y27 debtInterest === 0truetrue
Y27 debtPrincipalPaid === 0truetrue
Y28 debtPayments === 0truetrue
Y28 debtInterest === 0truetrue
Y28 debtPrincipalPaid === 0truetrue
Y29 debtPayments === 0truetrue
Y29 debtInterest === 0truetrue
Y29 debtPrincipalPaid === 0truetrue
Y30 debtPayments === 0truetrue
Y30 debtInterest === 0truetrue
Y30 debtPrincipalPaid === 0truetrue
Y31 debtPayments === 0truetrue
Y31 debtInterest === 0truetrue
Y31 debtPrincipalPaid === 0truetrue
Y32 debtPayments === 0truetrue
Y32 debtInterest === 0truetrue
Y32 debtPrincipalPaid === 0truetrue
Y0 roth > 0truetrue
Y0 preTax > 0truetrue
Y0 preTaxSpouse === 0truetrue
Y1 roth > 0truetrue
Y1 preTax > 0truetrue
Y1 preTaxSpouse === 0truetrue
Y2 roth > 0truetrue
Y2 preTax > 0truetrue
Y2 preTaxSpouse === 0truetrue
Y3 roth > 0truetrue
Y3 preTax > 0truetrue
Y3 preTaxSpouse === 0truetrue
Y4 roth > 0truetrue
Y4 preTax > 0truetrue
Y4 preTaxSpouse === 0truetrue
Y5 roth > 0truetrue
Y5 preTax > 0truetrue
Y5 preTaxSpouse === 0truetrue
Y6 roth > 0truetrue
Y6 preTax > 0truetrue
Y6 preTaxSpouse === 0truetrue
Y7 roth > 0truetrue
Y7 preTax > 0truetrue
Y7 preTaxSpouse === 0truetrue
Y8 roth > 0truetrue
Y8 preTax > 0truetrue
Y8 preTaxSpouse === 0truetrue
Y9 roth > 0truetrue
Y9 preTax > 0truetrue
Y9 preTaxSpouse === 0truetrue
Y10 roth > 0truetrue
Y10 preTax > 0truetrue
Y10 preTaxSpouse === 0truetrue
Y11 roth > 0truetrue
Y11 preTax > 0truetrue
Y11 preTaxSpouse === 0truetrue
Y12 roth > 0truetrue
Y12 preTax > 0truetrue
Y12 preTaxSpouse === 0truetrue
Y13 roth > 0truetrue
Y13 preTax > 0truetrue
Y13 preTaxSpouse === 0truetrue
Y14 roth > 0truetrue
Y14 preTax > 0truetrue
Y14 preTaxSpouse === 0truetrue
Y15 roth > 0truetrue
Y15 preTax > 0truetrue
Y15 preTaxSpouse === 0truetrue
Y16 roth > 0truetrue
Y16 preTax > 0truetrue
Y16 preTaxSpouse === 0truetrue
Y17 roth > 0truetrue
Y17 preTax > 0truetrue
Y17 preTaxSpouse === 0truetrue
Y18 roth > 0truetrue
Y18 preTax > 0truetrue
Y18 preTaxSpouse === 0truetrue
Y19 roth > 0truetrue
Y19 preTax > 0truetrue
Y19 preTaxSpouse === 0truetrue
Y20 roth > 0truetrue
Y20 preTax > 0truetrue
Y20 preTaxSpouse === 0truetrue
Y21 roth > 0truetrue
Y21 preTax > 0truetrue
Y21 preTaxSpouse === 0truetrue
Y22 roth > 0truetrue
Y22 preTax > 0truetrue
Y22 preTaxSpouse === 0truetrue
Y23 roth > 0truetrue
Y23 preTax > 0truetrue
Y23 preTaxSpouse === 0truetrue
Y24 roth > 0truetrue
Y24 preTax > 0truetrue
Y24 preTaxSpouse === 0truetrue
Y25 roth > 0truetrue
Y25 preTax > 0truetrue
Y25 preTaxSpouse === 0truetrue
Y26 roth > 0truetrue
Y26 preTax > 0truetrue
Y26 preTaxSpouse === 0truetrue
Y27 roth > 0truetrue
Y27 preTax > 0truetrue
Y27 preTaxSpouse === 0truetrue
Y28 roth > 0truetrue
Y28 preTax > 0truetrue
Y28 preTaxSpouse === 0truetrue
Y29 roth > 0truetrue
Y29 preTax > 0truetrue
Y29 preTaxSpouse === 0truetrue
Y30 roth > 0truetrue
Y30 preTax > 0truetrue
Y30 preTaxSpouse === 0truetrue
Y31 roth > 0truetrue
Y31 preTax > 0truetrue
Y31 preTaxSpouse === 0truetrue
Y32 roth > 0truetrue
Y32 preTax > 0truetrue
Y32 preTaxSpouse === 0truetrue
Y0 niitTax === 0truetrue
Y1 niitTax === 0truetrue
Y2 niitTax === 0truetrue
Y3 niitTax === 0truetrue
Y4 niitTax === 0truetrue
Y5 niitTax === 0truetrue
Y6 niitTax === 0truetrue
Y7 niitTax === 0truetrue
Y8 niitTax === 0truetrue
Y9 niitTax === 0truetrue
Y10 niitTax === 0truetrue
Y11 niitTax === 0truetrue
Y12 niitTax === 0truetrue
Y13 niitTax === 0truetrue
Y14 niitTax === 0truetrue
Y15 niitTax === 0truetrue
Y16 niitTax === 0truetrue
Y23 niitTax === 0 (post-LTC singleton)truetrue
Y0 tax === fedTax + stateTax + ficatruetrue
Y1 tax === fedTax + stateTax + ficatruetrue
Y2 tax === fedTax + stateTax + ficatruetrue
Y3 tax === fedTax + stateTax + ficatruetrue
Y4 tax === fedTax + stateTax + ficatruetrue
Y5 tax === fedTax + stateTax + ficatruetrue
Y6 tax === fedTax + stateTax + ficatruetrue
Y7 tax === fedTax + stateTax + ficatruetrue
Y8 tax === fedTax + stateTax + ficatruetrue
Y9 tax === fedTax + stateTax + ficatruetrue
Y10 tax === fedTax + stateTax + ficatruetrue
Y11 tax === fedTax + stateTax + ficatruetrue
Y12 tax === fedTax + stateTax + ficatruetrue
Y13 tax === fedTax + stateTax + ficatruetrue
Y14 tax === fedTax + stateTax + ficatruetrue
Y15 tax === fedTax + stateTax + ficatruetrue
Y16 tax === fedTax + stateTax + ficatruetrue
Y17 tax === fedTax + stateTax + ficatruetrue
Y18 tax === fedTax + stateTax + ficatruetrue
Y19 tax === fedTax + stateTax + ficatruetrue
Y20 tax === fedTax + stateTax + ficatruetrue
Y21 tax === fedTax + stateTax + ficatruetrue
Y22 tax === fedTax + stateTax + ficatruetrue
Y23 tax === fedTax + stateTax + ficatruetrue
Y24 tax === fedTax + stateTax + ficatruetrue
Y25 tax === fedTax + stateTax + ficatruetrue
Y26 tax === fedTax + stateTax + ficatruetrue
Y27 tax === fedTax + stateTax + ficatruetrue
Y28 tax === fedTax + stateTax + ficatruetrue
Y29 tax === fedTax + stateTax + ficatruetrue
Y30 tax === fedTax + stateTax + ficatruetrue
Y31 tax === fedTax + stateTax + ficatruetrue
Y32 tax === fedTax + stateTax + ficatruetrue
Y0 ssdi === 0truetrue
Y0 withdrawal >= 0truetrue
Y0 withdrawalForSpending >= 0truetrue
Y1 ssdi === 0truetrue
Y1 withdrawal >= 0truetrue
Y1 withdrawalForSpending >= 0truetrue
Y2 ssdi === 0truetrue
Y2 withdrawal >= 0truetrue
Y2 withdrawalForSpending >= 0truetrue
Y3 ssdi === 0truetrue
Y3 withdrawal >= 0truetrue
Y3 withdrawalForSpending >= 0truetrue
Y4 ssdi === 0truetrue
Y4 withdrawal >= 0truetrue
Y4 withdrawalForSpending >= 0truetrue
Y5 ssdi === 0truetrue
Y5 withdrawal >= 0truetrue
Y5 withdrawalForSpending >= 0truetrue
Y6 ssdi === 0truetrue
Y6 withdrawal >= 0truetrue
Y6 withdrawalForSpending >= 0truetrue
Y7 ssdi === 0truetrue
Y7 withdrawal >= 0truetrue
Y7 withdrawalForSpending >= 0truetrue
Y8 ssdi === 0truetrue
Y8 withdrawal >= 0truetrue
Y8 withdrawalForSpending >= 0truetrue
Y9 ssdi === 0truetrue
Y9 withdrawal >= 0truetrue
Y9 withdrawalForSpending >= 0truetrue
Y10 ssdi === 0truetrue
Y10 withdrawal >= 0truetrue
Y10 withdrawalForSpending >= 0truetrue
Y11 ssdi === 0truetrue
Y11 withdrawal >= 0truetrue
Y11 withdrawalForSpending >= 0truetrue
Y12 ssdi === 0truetrue
Y12 withdrawal >= 0truetrue
Y12 withdrawalForSpending >= 0truetrue
Y13 ssdi === 0truetrue
Y13 withdrawal >= 0truetrue
Y13 withdrawalForSpending >= 0truetrue
Y14 ssdi === 0truetrue
Y14 withdrawal >= 0truetrue
Y14 withdrawalForSpending >= 0truetrue
Y15 ssdi === 0truetrue
Y15 withdrawal >= 0truetrue
Y15 withdrawalForSpending >= 0truetrue
Y16 ssdi === 0truetrue
Y16 withdrawal >= 0truetrue
Y16 withdrawalForSpending >= 0truetrue
Y17 ssdi === 0truetrue
Y17 withdrawal >= 0truetrue
Y17 withdrawalForSpending >= 0truetrue
Y18 ssdi === 0truetrue
Y18 withdrawal >= 0truetrue
Y18 withdrawalForSpending >= 0truetrue
Y19 ssdi === 0truetrue
Y19 withdrawal >= 0truetrue
Y19 withdrawalForSpending >= 0truetrue
Y20 ssdi === 0truetrue
Y20 withdrawal >= 0truetrue
Y20 withdrawalForSpending >= 0truetrue
Y21 ssdi === 0truetrue
Y21 withdrawal >= 0truetrue
Y21 withdrawalForSpending >= 0truetrue
Y22 ssdi === 0truetrue
Y22 withdrawal >= 0truetrue
Y22 withdrawalForSpending >= 0truetrue
Y23 ssdi === 0truetrue
Y23 withdrawal >= 0truetrue
Y23 withdrawalForSpending >= 0truetrue
Y24 ssdi === 0truetrue
Y24 withdrawal >= 0truetrue
Y24 withdrawalForSpending >= 0truetrue
Y25 ssdi === 0truetrue
Y25 withdrawal >= 0truetrue
Y25 withdrawalForSpending >= 0truetrue
Y26 ssdi === 0truetrue
Y26 withdrawal >= 0truetrue
Y26 withdrawalForSpending >= 0truetrue
Y27 ssdi === 0truetrue
Y27 withdrawal >= 0truetrue
Y27 withdrawalForSpending >= 0truetrue
Y28 ssdi === 0truetrue
Y28 withdrawal >= 0truetrue
Y28 withdrawalForSpending >= 0truetrue
Y29 ssdi === 0truetrue
Y29 withdrawal >= 0truetrue
Y29 withdrawalForSpending >= 0truetrue
Y30 ssdi === 0truetrue
Y30 withdrawal >= 0truetrue
Y30 withdrawalForSpending >= 0truetrue
Y31 ssdi === 0truetrue
Y31 withdrawal >= 0truetrue
Y31 withdrawalForSpending >= 0truetrue
Y32 ssdi === 0truetrue
Y32 withdrawal >= 0truetrue
Y32 withdrawalForSpending >= 0truetrue

Per-Person LTC 9/9

TestExpectedActualResult
T1 primary age 82 (idx 22) ltcCost292,526292,526
T1 primary age 85 (idx 25) ltcCost338,635338,635
T1 primary age 86 (idx 26) ltcCost — window 82-85 closed00
T2 spouse-insured, primary age 82 (idx 22) ltcCost — spouse only 7700
T2 spouse-insured, primary age 87 (idx 27) ltcCost — spouse 82373,346373,346
T2 spouse-insured, primary age 90 (idx 30) ltcCost — spouse 85432,194432,194
T2 spouse-insured, primary age 91 (idx 31) ltcCost — spouse 86, window closed00
T3 two streams sum, age 82 (idx 22) ltcCost526,547526,547
T4 insurance offset, age 82 (idx 20) ltcCost228,090228,090