Calculation catalog › Spending and withdrawals

Display upside spending annual

Ideal plus excess spending intended above the target layer.

Field: Upside spending Unit: US dollars Basis: nominal dollars Computed by: UI transformation Status: Complete chain

Appears in: results-table (Upside column (layered spending))

Calculation records

  • Upside spending: intended spending above the target layer Composition record, justified by derivation

    Purpose: The ideal and excess spending a layered plan intended in the year, as the Upside column shows it.

    Statement: projection/yearFigures.ts#upsideSpending publishes expenses.idealSpending + expenses.excessSpending for the year: intended spending above the target layer. Units: nominal USD of the year. Rounding: none.

    Formula: upsideSpending = idealSpending + excessSpending

    • idealSpending: Ideal layer intended above target (unit: usd per year) (domain: nonnegative)
    • excessSpending: Excess layer intended above ideal (unit: usd per year) (domain: nonnegative)

    Timing: annual

    Rounding: none

    Limits:

    • Intended, not funded: a guardrail cut or a portfolio shortfall does not reduce it; the unfunded part is display-upside-shortfall-annual

    Provenance: derived by claude, implemented by claude-subagent.

    Independent review: codex

    Gates (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: display-upside-spending-annual.md Mutation receipt: display-upside-spending-annual.mutation.md

    Evidence tests: yearFigures.evidence.test.ts

    Implemented in: yearFigures.ts; yearLedger.ts

    Is the number of: display-upside-spending-annual

Records that feed this number

  • Today's dollars by the ledger's own inflation factor Formula record, justified by derivation

    Purpose: How a year's nominal amount becomes start-year dollars on every page, and how a start-year figure such as the FI target is placed in a year's dollars.

    Statement: projection/dollarBasis.ts converts a nominal amount x of projection year y to start-year dollars as x / f(y), and a start-year amount to year-y dollars as x * f(y), where f(y) is the ledger's published YearResult.inflationScale: the left-to-right product of (1 + inflationPct/100) taken y - startYear times from 1, exactly 1 in the start year. projectionDollarBasis reads the factors from a projection's rows; planDollarBasis runs the same recurrence for a page that holds no projection rows and is bit-identical to a deterministic run's factors. nominalForDisplay shows a nominal amount in the page's mode (converted in today's-dollar mode, unchanged in nominal mode) and todayForDisplay shows a start-year amount (unchanged in today's-dollar mode, times f(y) in nominal mode), so the FI target line is fiNumber itself in today's-dollar mode and fiNumber * f(y) in nominal mode. A year outside the projection, or a fractional year, is refused. Units: USD. Rounding: none.

    Formula: f(s) = 1; f(y) = f(y - 1) * (1 + i/100); today(y, x) = x / f(y); nominal(y, x) = x * f(y); FI target in year y = fiNumber (today mode) or fiNumber * f(y) (nominal mode)

    • i: General inflation rate, plan.assumptions.inflationPct (unit: percent per year) (domain: finite, above -100)
    • s: Projection start year, the first ledger row (unit: calendar year) (domain: integer)
    • y: Year of the amount (unit: calendar year) (domain: integer in [s, endYear])
    • x: Amount converted (unit: usd) (domain: finite)
    • f(y): Cumulative general-inflation factor, YearResult.inflationScale (unit: ratio) (domain: f(s) = 1)

    Timing: annual; one factor per calendar year, applied to every amount of that year

    Rounding: none

    Limits:

    • planDollarBasis is the plan's assumed rate and matches only a deterministic run: a Monte Carlo path grows by its own inflation series, so its rows are converted with projectionDollarBasis on that path's own result
    • Start-year dollars in whole-year steps: an amount paid in December and one paid in January of the same year carry the same factor
    • General inflation only: the healthcare inflation premium and the Social Security cost-of-living adjustment are separate assumptions and are never the basis
    • Years outside the projection are refused, never extrapolated; a projection whose horizon ends before its start year has an empty basis in which every year is refused
    • Owner decision R19 (2026-09-25): the planner pages used to compound the plan's rate with Math.pow from the page's start year. The ledger's factor is a product built one year at a time, which differs from the power in the last binary digit in some years (21 of 41 years at 2.5 percent, one unit each), so a whole-dollar figure can change only on an exact half-dollar tie; the FI target in today's-dollar mode becomes exactly fiNumber instead of fiNumber * f / f
    • The FI target is recorded here rather than in a record of its own: it is projection-summary-fi-number placed in a year through todayForDisplay
    • Since B2-P1 slice 2 the spending page converts nothing itself: each published withdrawal rule's ending estate is converted by that rule's own run (decisions/swrComparator.ts#compareSwrRules publishes endingAfterTaxEstateTodayDollars), and the solver's evidence estate by the answer run's own factors; planDollarBasis remains for the relocation page

    Provenance: derived by claude, implemented by claude-subagent.

    Independent review: codex

    Gates (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: display-dollar-basis-conversion.md Mutation receipt: display-dollar-basis-conversion.mutation.md

    Evidence tests: swrComparator.evidence.test.ts; dollarBasis.evidence.test.ts

    Implemented in: dollarBasis.ts; detectorProjection.ts; result.ts; swrComparator.ts

    Is the number of: display-dollar-basis-conversion, display-fi-target-annual

    Feeds: display-balance-by-category-annual, display-net-care-cost-annual, display-tax-free-gains-room-annual, display-tax-plus-penalties-annual, display-total-spending-annual, display-upside-shortfall-annual, display-upside-spending-annual

  • Annual excess-layer requested spending Composition record, justified by derivation

    Purpose: The incremental opportunistic layer above ideal spending.

    Statement: projection/internal/annualExpenseSummary.ts#annualExpenseSummary publishes YearExpenses.excessSpending as excessSpendingBase + skippedExcessNominal, with excessSpendingBase = excessLifestyle + excessGoalsFunded. It is an increment above ideal, so the identity the worksheet derives holds exactly: excessSpending = intendedSpending - targetSpending - idealSpending. Units: nominal USD per year. Rounding: none.

    Formula: excessSpending = excessLifestyle + excessGoalsFunded + skippedExcessNominal = intendedSpending - targetSpending - idealSpending

    • excessLifestyle: Annual opportunistic lifestyle layer above ideal (unit: usd/year) (domain: nonnegative)
    • excessGoalsFunded: Excess-classified goals funded this year (unit: usd/year) (domain: nonnegative)
    • skippedExcessNominal: Nominal amount of excess-classified goals the scheduler skipped (unit: usd/year) (domain: nonnegative)

    Timing: once per projection year, at the expense summary

    Rounding: none

    Limits:

    • Asserted at the annualExpenseSummary seam, which is the function that computes all five layer fields at once, because the worksheet states its inputs as published year-row components. The seam call is given inputs that realize the worksheet's stated requiredSpending, targetSpending, idealSpending and intendedSpending exactly, and the published excessSpending is then read
    • The identity is asserted against the same call's other published fields rather than re-entered constants
    • Failing to remove the ideal increment, or treating excess as everything above required, are the worksheet's two wrong readings and are asserted against

    Provenance: derived by codex, implemented by claude.

    Independent review: cursor

    Gates (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-excess-requested-annual.md Mutation receipt: spending-excess-requested-annual.mutation.md

    Evidence tests: annualExpenseSummary.evidence.test.ts

    Implemented in: annualExpenseSummary.ts

    Is the number of: spending-excess-requested-annual

    Feeds: display-upside-spending-annual

  • Annual ideal-layer requested spending Composition record, justified by derivation

    Purpose: The incremental ideal layer above target spending.

    Statement: projection/internal/annualExpenseSummary.ts#annualExpenseSummary publishes YearExpenses.idealSpending as idealSpendingBase + skippedIdealNominal, with idealSpendingBase = idealLifestyle + idealGoalsFunded. It is an increment, not a cumulative summary, so the identity the worksheet derives from the field comments holds exactly: idealSpending = intendedSpending - targetSpending - excessSpending, because intendedSpending adds the target base, the ideal base, the excess base and all four skipped amounts while targetSpending carries the target base with the target and required skips and excessSpending carries the excess base with the excess skip. Units: nominal USD per year. Rounding: none.

    Formula: idealSpending = idealLifestyle + idealGoalsFunded + skippedIdealNominal = intendedSpending - targetSpending - excessSpending

    • idealLifestyle: Annual ideal lifestyle layer above target (unit: usd/year) (domain: nonnegative)
    • idealGoalsFunded: Ideal-classified goals funded this year (unit: usd/year) (domain: nonnegative)
    • skippedIdealNominal: Nominal amount of ideal-classified goals the scheduler skipped (unit: usd/year) (domain: nonnegative)

    Timing: once per projection year, at the expense summary

    Rounding: none

    Limits:

    • Asserted at the annualExpenseSummary seam, which is the function that computes all five layer fields at once, because the worksheet states its inputs as published year-row components. The seam call is given inputs that realize the worksheet's stated requiredSpending, targetSpending, excessSpending and intendedSpending exactly, and the published idealSpending is then read
    • The identity is asserted against the same call's other published fields, not against re-entered constants, so the subtraction is evidence about this year row rather than about the worksheet's arithmetic
    • Ideal is an increment above target; treating it as the cumulative amount through the ideal layer is one of the worksheet's wrong readings

    Provenance: derived by codex, implemented by claude.

    Independent review: cursor

    Gates (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-ideal-requested-annual.md Mutation receipt: spending-ideal-requested-annual.mutation.md

    Evidence tests: annualExpenseSummary.evidence.test.ts

    Implemented in: annualExpenseSummary.ts

    Is the number of: spending-ideal-requested-annual

    Feeds: display-upside-spending-annual

Transformations

  • Add expenses.idealSpending and expenses.excessSpending in projection/yearFigures.ts#upsideSpending, then apply the selected dollar basis.

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.