@retiregolden/engine
Pure-TypeScript retirement-planning engine — the calculation core of RetireGolden. It projects a household's finances year by year and models federal + state taxes, Social Security (claiming, spousal/survivor, PIA from earnings), RMDs, Roth conversions, withdrawal strategies, insurance, Monte Carlo, and an LP-based optimizer.
Source of truth: github.com/RetireGolden/RetireGolden
(packages/engine). Engineering docs live in the repo's DOCS/.
Runtime contract
- ESM, Node ≥ 20 (also bundles cleanly for browsers). No CommonJS build.
- No browser globals, no ambient network, no persistence. The engine never
touches
fetch,localStorage,indexedDB, or the DOM — enforced by lint. IO always crosses an injection seam owned by the consumer:- anything stochastic takes an injected seedable RNG (
montecarlo/rng); - the optimizer loads the HiGHS wasm via an optional
locateFileoption (strategies/optimizer); - FedInvest TIPS prices: the engine only parses CSV text
(
ladder/fedInvest); fetching and caching are the consumer's job.
- anything stochastic takes an injected seedable RNG (
- Deterministic. Same plan + same options ⇒ bit-identical results.
- Parameters (tax brackets, limits, SSA tables, Medicare/FPL) are versioned
data packs under
params/, with provenance.
Usage
Deep subpath imports are the primary API; the root export covers the core validate-and-project loop:
import { planSchema, simulatePlan } from '@retiregolden/engine'
const plan = planSchema.parse(JSON.parse(planJson))
const result = simulatePlan(plan, { startYear: 2026 })
import { runMonteCarlo } from '@retiregolden/engine/montecarlo/run'
import { packForYear } from '@retiregolden/engine/params'
A versioned JSON Schema for the Plan document is derived from planSchema and
shipped both as a constant and as a static file, so a non-TypeScript consumer can
learn the plan format:
import { planJsonSchema, PLAN_SCHEMA_VERSION } from '@retiregolden/engine/schema'
This subpath is zod-free — it resolves only to the generated constant and
plain metadata, so importing it pulls in neither zod nor the plan model. The same
bytes ship as @retiregolden/engine/schema/plan.v1.json for offline, no-import
reads. The schema describes the plan's structure; it is necessary but not
sufficient — cross-field rules (id references, funding rules, allocation weights
summing to 100%, …) live only in parsePlan, which stays the full validator.
Those dropped rules are summarized in the schema's description and carried as a
machine-readable x-retiregolden-unrepresentableConstraints array on the schema
itself (also exported as PLAN_SCHEMA_UNREPRESENTABLE_CONSTRAINTS). The zod-backed
generator behind the artifact is @retiregolden/engine/schema/generate
(generatePlanJsonSchema), used by the build-time npm run generate:schema.
Test fixtures used by the RetireGolden apps' own suites ship under
@retiregolden/engine/testing/* — framework-free (no vitest or other
test-runner dependency), but not part of the supported runtime API.
Layout
| Subpath | Contents |
|---|---|
model/ |
Plan schema (Zod), types, migrations |
schema/ |
Derived, versioned JSON Schema for the Plan document (planJsonSchema, PLAN_SCHEMA_VERSION) + the shipped schema/plan.v1.json artifact |
params/ |
Annual parameter packs (tax brackets, limits, RMD, Medicare, SS, state) + typed accessors |
tax/ |
Federal + state tax engine, ACA credit, Medicare/IRMAA |
rmd/ |
Required minimum distributions (SECURE 2.0) |
socialSecurity/ |
Claiming factors, NRA/FRA, PIA from earnings, spousal/survivor/family-maximum, disability |
longevity/ |
SSA 2022 period life table + shared types |
strategies/ |
Roth-conversion sizing (fill-to-target), withdrawal ordering, SEPP, inherited-IRA, the optimizer |
projection/ |
Deterministic annual ledger + summaries/comparison |
montecarlo/ |
Seedable RNG, market models (lognormal, historical bootstrap), path runner + aggregation, mortality/survival |
scenarios/ |
Scenario patch apply/diff + side-by-side comparison |
decisions/, insights/ |
Candidate evaluation, recommendation detectors |
ladder/ |
TIPS ladder math, Social Security bridge, FedInvest CSV parsing |
allocation/, spending/ |
Asset classes, spending shape presets |
testing/ |
Plan fixtures and money matchers for consumer test suites |
License
AGPL-3.0-only (see LICENSE). The engine is free and un-gutted — the full math ships in the free web app.
RetireGolden, LLC also ships a commercial desktop edition built from this same engine under a separate commercial license, which funds the free one. That dual-license arrangement is why contributions to the upstream repo require a one-time Contributor License Agreement — you keep your copyright; the CLA lets the LLC also ship your contribution in the commercial edition. See CONTRIBUTING.md.