Calculation catalog › Cash flow and summary
Sustainable spending result spending slack dollars
The published solved spending (rounded down to $100) minus current base spending, in today's dollars; negative means today's spending is above the published amount, which by less than $100 can still be a plan that sustains its own spending.
Field: spendingSlackDollars Unit: US dollars Basis: today's dollars (real) Computed by: Engine Status: Complete chain
Appears in: solver-page (spending feasibility slack); insights (spending-headroom card after Preview "$Y/yr above your current level"); scenarios-page (Spending capacity "Slack vs. current base spending"); mcp (solve_max_spending.spendingSlackDollars)
Calculation records
-
Sustainable spending bisection Model record, justified by derivation
Purpose: Find a feasible lower bound for constant annual base spending within a simulation budget.
Statement: decisions/spendingSolver.ts#solveMaxSustainableSpending finds a lower-bound maximum feasible annual base spending in today's dollars using deterministic integer-dollar bracketing and bisection, where feasibility means no depletion and nominal ending after-tax estate at least the inflated today-dollar floor. Each bisection probe is the half-sum of the bracket rounded to the nearest dollar, a half rounded up. The highest level that passed, a whole number of dollars, is published as feasibleBaseAnnual; the published answer maxBaseAnnual is that level rounded down to $100 when that level is known to pass (the record solved-spending-rounding), and spendingSlackDollars is measured from maxBaseAnnual.
Formula:
probe integer midpoint; keep feasible lower and infeasible upper until upper-lower <= resolution; feasibleBaseAnnual = best feasible lower; maxBaseAnnual = its $100 floor when that level is known to pass, else feasibleBaseAnnual-
spending: Probed annual base spending (unit: today USD/year) (domain: nonnegative integer) -
resolution: Maximum bracket width (unit: USD/year) (domain: positive)
Timing: whole-plan deterministic evaluations
Rounding: integer-dollar midpoint
Limits:
- simulationCount has its own record (sustainable-spending-result-simulation-count); the count enters the published result, so this record feeds its family rather than computing it.
- The public API generates its own bracket. Evidence seeds 40000, brackets at 80000, and verifies the first two midpoints reach the worksheet bracket 60000/70000 before checking its four probes and 62500 result, then runs the same search at a $100 resolution, which probes three more levels and passes 62969. It isolates the stated feasible predicate with an evaluation double, not an invented ledger oracle. Monotone feasibility is assumed at fixed-target spending (under guardrails it does not hold; see below); budgets can stop convergence.
- A Marketplace year whose premium tax credit the ledger could not price (aca.readiness nonActionable) counts its full premium, as the ledger funds it; the credit lies between 0 and that premium (26 U.S.C. 36B(b)(2)). The solver always evaluates its probes with nonActionableAca 'disclose' (its options leave callers no way to ask for 'refuse'), so such a year is a disclosed limit, not a refusal. Those years of the run the result rests on (the best feasible probe; with no answer, the probe the failure diagnostic describes: the floor probe when it ran, else the seed), the codes that blocked pricing (every code but the informational ones, INFORMATIONAL_ACA_SUPPORT_CODES, the list the ledger's readiness reads) and acaGrossPremiumDirection are published, and the last diagnostic names them.
- acaGrossPremiumDirection is 'conservative' only at fixed-target spending: at fixed spending a lower premium lowers what that year must withdraw, so a credit would likely leave room to spend more. That is measured, not proven for every plan: an independent check priced the stand-in years in a counterfactual and re-solved the 20 fixed-target example answers at $1 resolution (about 6,700 grid points) without finding a credit-priced answer below the gross one (gaps 0 to $6,357 a year). Under guardrails it is 'uncertain': a lower cost keeps the withdrawal rate under the upper guardrail longer, so cuts start later, and the same check found credit-priced ledgers that solve lower (the aggressive-saver example under 125/90/20 guardrails with raises: $76,707 on the gross premium, $75,170 with the credit priced) or deplete at the gross answer (the barista-fire example under the same 125/90/20 guardrails with raises).
- Under an adaptive spending policy (guardrails) feasibility is not monotone in the base amount, so the answer is a level the search found feasible and a higher feasible level can exist. Measured with no Marketplace year at all: the example-couple plan with no Marketplace premium or credit, withdrawal-rate guardrails (upper 125%) and an $86,400 required floor depletes in 2059 at a base of $164,391 and never depletes at $166,971, because the higher base makes its first cut a year earlier (2030 against 2031). The independent check of 2026-09-26 also found it on Marketplace plans, under both the gross-premium and the credit-priced ledgers.
- The published answer is rounded down to $100 (owner decision R4, the record solved-spending-rounding). In this record's first evidence case the level that passed, $62,500, is already a whole $100, so it is both feasibleBaseAnnual and the published answer; in the second the level that passed is $62,969 and the published answer $62,900, so the two figures differ and each is asserted.
- When the seed is infeasible the downward bracket starts at the required spending floor (expenses.requiredAnnual rounded up, 0 when the plan has none), the lowest level the plan checks accept; no probe goes below it, and a failure there is reported as the floor failing, naming the constraint that failed. The seed itself is raised to that floor when the base spending would round below it. zeroSpendingDepletes is true only when a probe at 0 ran and depleted.
Provenance: derived by
codex, implemented byclaude-subagent.Independent review:
grokGates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass
Worksheet: sustainable-spending-bisection.md Mutation receipt: sustainable-spending-bisection.mutation.md
Evidence tests: spendingSolver.evidence.test.ts
Implemented in: spendingSolver.ts
Is the number of: sustainable-spending-result-max-base-annual, sustainable-spending-result-spending-slack-dollars, sustainable-spending-result-feasible-base-annual
Feeds: sustainable-spending-result-simulation-count, solved-initial-withdrawal-rate-pct, solved-spending-rounded-to-hundred
-
Records that feed this number
-
Sustainable spending rounded down to the hundred Formula record, justified by derivation
Purpose: The one amount every surface shows, applies and measures slack from once the spending solver has found the highest level that passed.
Statement: decisions/spendingSolver.ts#roundSolvedSpending floors a nonnegative amount to a whole multiple of SOLVED_SPENDING_STEP_DOLLARS (100): floor(x / 100) × 100, refusing an amount that is negative or not finite. The solver publishes feasibleBaseAnnual, the highest level that passed (a whole number of dollars), and maxBaseAnnual, that level rounded down to $100, and measures spendingSlackDollars as maxBaseAnnual minus the current base (owner decision R4: one slack everywhere, from the amount shown). Under fixed-target spending the rounded amount is published without a run of its own, on the decision's assumption that a lower base does not fail where a higher one passed (measured, not proven; see the limits). Under withdrawal-rate or risk-based guardrails a lower base can fail, so the rounded amount is published only on a run at it that passed: the search's own probe at that level when it made one, else one more run after the search; otherwise the solver publishes feasibleBaseAnnual itself, sets maxBaseAnnualRounding to none and adds a sentence to its diagnostics saying why. A rounded amount below the plan's required spending is never published. Whether today's spending is sustained is sustainsCurrentBase, the verdict of the first probe (today's base rounded to a whole dollar, or the required floor rounded up when that is higher), never the sign of the slack. When the rounded amount is published, bestEvaluation and the unpriced premium-credit years still describe the run at feasibleBaseAnnual. For the worksheet's case A (levels up to $62,850 pass, current base $40,000) the probes end at $62,813, the published amount is $62,800 and the slack $22,800; under guardrails, with the rounded amount failing, it is $62,813 and $22,813. Units: today's dollars per year. Rounding: down to a whole $100.
Formula:
M = floor(F / 100) · 100 when that level is known to pass, else M = F; slack = M − current-
F: feasibleBaseAnnual, the highest level that passed (unit: today USD per year) (domain: nonnegative whole number) -
M: maxBaseAnnual, the published answer (unit: today USD per year) (domain: nonnegative; a multiple of 100 unless published as F) -
current: The base spending the solve started from, after any base patch (unit: today USD per year) (domain: nonnegative)
Timing: once per solve, after the search
Rounding: down to a whole $100; the page prints whole dollars
Limits:
- Under fixed-target spending the rounded amount is not run on its own. That it passes is the decision's assumption, measured and not proven: every one of the 109 published amounts of the example plans and their shape solves re-simulates feasible, as do 210 fixed-target balance variants (0.70 to 1.30 times) of ten Marketplace-heavy or early-retirement examples, and a scan of every $10 level in the $3,000 below the answer on six Marketplace examples found none that fails. The mechanism it does not exclude is a lower spend dropping the household's income below 100 percent of the poverty line, where the premium tax credit is lost and the full premium is budgeted.
- When the rounded amount is published, the evidence figures on the spending page and the unpriced premium-credit years describe the run at feasibleBaseAnnual, not a run at the published amount (under guardrails that run also passed, but its own evidence is not published).
- Under guardrails a check of the rounded amount that the search did not already make is one more simulation after the search, outside maxSimulations, and it is counted in simulationCount.
- A published amount under the current base by less than $100 can belong to a plan that sustains its own spending (the current base passed and is the answer, rounded down); the spending page judges that on feasibleBaseAnnual, and so should any other reader of the slack.
- The search resolves to about $500, so answers less than $100 apart can publish the same amount, and a comparison of two plans can tie there.
Provenance: derived by
claude, implemented byclaude-subagent.Independent review:
codexGates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass
Worksheet: solved-spending-rounded-to-hundred.md Mutation receipt: solved-spending-rounded-to-hundred.mutation.md
Evidence tests: spendingSolver.rounding.evidence.test.ts
Implemented in: spendingSolver.ts
Is the number of: solved-spending-rounded-to-hundred, sustainable-spending-result-max-base-annual
Feeds: sustainable-spending-result-spending-slack-dollars, solved-initial-withdrawal-rate-pct, spending-shape-delta-vs-flat
-
-
Annual real spending drift compiled to five-year phase rows Model record, justified by derivation
Purpose: Turns a steady %/yr real spending change into the editable phase multipliers a plan stores.
Statement: deltaPct = 0 returns no phases. startAge = min(max(round(retirementAge), 40), 105). For age = startAge + 5, startAge + 10, ... while age <= 100: multiplier = (1 + deltaPct/100)^(age - startAge), rounded to two decimals as Math.round(x x 100)/100 and clamped into [0, 3]; each row is { fromAge: age, multiplier }. Units: fromAge in years of the person the phases follow (expenses.phasesAgeOf; spending-phase-person); multiplier a factor on baseAnnual. Rounding: two decimals per row, as stated.
Formula:
m(age) = clamp(round2((1 + d/100)^(age - a0)), 0, 3) for age = a0 + 5k <= 100, k >= 1, a0 = clamp(round(retirementAge), 40, 105)-
d: Annual real spending change (unit: percent/year) (domain: finite; 0 emits no rows) -
a0: Rounded, clamped retirement age the steps count from (unit: years) (domain: 40 <= a0 <= 105) -
age: A phase row's fromAge (unit: years) (domain: a0 + 5, a0 + 10, ... <= 100) -
m(age): Multiplier on baseAnnual from that age (unit: 1) (domain: 0 <= m <= 3, two decimals)
Timing: compiled once when the shape is chosen; the rows then hold flat between step ages
Rounding: two decimals per multiplier (Math.round(x x 100)/100)
Limits:
- On the amortization-based-withdrawal path the compiled phases do not reach spending-base-annual: annualLifestyleLayers scales the base by the phase multiplier and then, when ABW is active, replaces it with abwAnnualPayment and zeroes the other lifestyle layers. The feed holds on the ordinary lifestyle path, for spending-shape-delta-vs-flat and for the sustainable-spending solver, which run shapes as plan data.
- Five-year steps hold the fully compounded multiplier flat between step ages, an editable approximation to annual drift
- The first row is one step after retirement, never at retirement age itself
- Retirement age is rounded and clamped into [40, 105] so every row satisfies the phase schema (fromAge 40..110, multiplier 0..3)
- The rows are plan data: the planner-ui SpendingSection writes them into expenses.phases and the solver page runs the sustainable-spending solver per shape; no engine module calls this function, so the named families are fed through the plan the UI writes
Provenance: derived by
codex, implemented byclaude-subagent.Independent review:
cursorGates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass
Worksheet: spending-shape-annual-delta-phases.md Mutation receipt: spending-shape-annual-delta-phases.mutation.md
Evidence tests: shapePresets.evidence.test.ts
Implemented in: shapePresets.ts
Feeds: spending-base-annual, spending-shape-delta-vs-flat, sustainable-spending-result-max-base-annual, sustainable-spending-result-spending-slack-dollars
-
Engine source: engine/src/decisions/spendingSolver.ts
(SustainableSpendingResult.spendingSlackDollars)
The evidence links on this page (each record's worksheet, mutation receipt, evidence tests
and implementation, and the source links) are pinned to engine commit
2624dbdba9fd, committed 2026-10-11.
The live calculation index and
output-family census links point at the repository's main
branch, so you can check this snapshot against them.