Skip to content

Releases

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 09 Nov 13:59
9723643

Added

  • retiretui-desktop, a second binary that opens the planner in a window: the
    tui command's arguments and --light for a theme family's light variant,
    Inconsolata embedded as its face, a grid of cells the shell lays itself out in
    as it does in a terminal, the close button asking what q asks over an
    unsaved draft, and its log in desktop.log. The window shows the shell's
    chrome in its own dress - the tabs as text over a baseline, the chosen one
    underlined, switched by digit or click, a pill at the row's end switching
    between today's and future dollars, the status, the key row two rows tall over
    a hairline with its keys in from the edge as far as the tabs, a margin around
    the body, each pane's frame inset from its neighbours with its title centred
    on a two-row header and what it holds padded in from its line, a pane sized by
    what it holds grown by the header so it keeps its rows, the sidebars, toasts,
    the message drawer, the dialog and the pickers as sheets with a shadow - the
    whole frame dimmed under whichever of them stands highest. No title says the
    dollar basis; the switch does. Of the pages, it draws the Ledger: the years
    under their headers, the flows, the money panes and the so-far table, each
    scrolled on the wheel with a bar beside it, stepped by the keys, a row chosen
    by a click and banded under the pointer. It draws the Plan tab's editing
    domains the same way: each domain's table with its read-out beside it, a row
    opened by a click and a column sorted by a click on its header, and the form
    over it - its labels, headings and help, a text field typed into in a box
    ringed while it holds the keyboard, a flag ticked by space or a click, a
    slider moved by the arrows or a press on its track, a select as a box across
    its row with its menu opened over the form and picked from by key or click,
    and the buttons as boxes, the primary answer filled - scrolled with a bar as
    the terminal's is. It draws what finds and makes a document: the file picker,
    its path typed, completed and climbed as in the terminal, its listing scrolled
    with the cursor and a row chosen by a double click; the new-plan form; and the
    issues panel, scrolled with its cursor. It draws the Overview: a raised card
    saying whether the money lasts, its mark on a disc of its colour, how surely
    and what the plan rests on first, four more cards - what it ends with, the
    least it holds after the last salary, what it spends and what it pays in tax,
    each a figure at twice the size under its title and over a line of context -
    the three lists, and the chart, picked by name from a pill in its pane's
    header, with a row and a cell kept clear around the plot - its labels as text,
    its key dotted in each band's colour, its plot through bevy's renderer, ruled
    across at each quarter, each band filled deeper than its line under the lines,
    the salary's end and zero ruled - read out under the pointer and opening the
    Ledger on a click, as in the terminal. Every list the window scrolls shows the
    terminal's bar beside it, and the pointer reaches every widget as in the
    terminal: what lights up under it lights up, the wheel scrolls any list, and a
    press in a text field places its caret and a drag selects. It draws the tools
    and Compare: every table - the options a search ranks, the ladder, the people,
    the expenses, the assumptions, the years, the proposals, the records, the tax
    table and the compared plans - as the Ledger's, the help line under each page,
    and the market tools' Ends With view as rows of bars. The window draws every
    frame while a search runs and otherwise wakes for input and once a second, for
    the file watch, focused or not. Known issue: under niri the window stays blank
    while its height in pixels is fractional at the output's scale, as at a scale
    of 1.6; fullscreen, or a height the scale divides, draws.

  • Releases for Windows and macOS: every release archive holds the retiretui
    command and the retiretui-desktop window, the Linux tarballs beside a zip of
    the two Windows executables, the window's with its icon, and a zip of a
    universal RetireTui.app with the command, ad-hoc signed. Neither is signed
    by a publisher, so the README says what each platform asks on the first open.

Changed

  • The app icon is a shell prompt: Inconsolata's dollar beside an amber block
    cursor on the terminal's near-black, in the web app's manifest and on the
    Windows executable.
  • A click anywhere in a pane hands it the keyboard: to the widget the click
    landed in, or the pane's first.
  • Lists wrap at their ends and move on Left and Right too, but for a sidebar's
    Right, which still goes into the page. A list that loses the keyboard draws no
    cursor, and a menu closes when the keyboard leaves it.
  • The file picker climbs to the parent on alt+up; left and right move the
    caret in its path.
  • The terminal wears the embedded github theme family by default,
    github-light or github-dark as the screen is. The terminal's own colours
    are no longer a theme: the picker and retiretui theme do not list
    terminal, and a settings file naming it is told so and wears the default. A
    theme file states every colour as #rrggbb, and a role it leaves out takes
    the github family's in its variant.

Removed

  • ctrl+c no longer copies the row under the cursor in any table.
  • A theme file can no longer name a colour by an ANSI name or palette index, nor
    set transparent; one that does is reported as unreadable and the default
    family is worn.
  • A form taller than the body scrolls on a wheel tick over any of its fields,
    not only as the keyboard moves between them.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 28 Oct 16:44
37378c4

Added

  • An expense's amount can change at triggers of its own, as
    [[expenses.phases]] rows of a from trigger and the amount from then on, so
    a cost that changes with a move or with age is one expense rather than one per
    period. The year a phase fires in is split by months where the trigger has
    one; start, end and on keep their whole-year meaning, and on excludes
    phases. The Expenses form offers a phase after the last one filled, the
    read-out lists the filled ones alone, the table counts them, the Overview
    marks an implausible phase amount, and the spending ceiling scales every phase
    with its expense.

  • A Spending Estimate tool proposes the plan's expenses from a bank's CSV, OFX
    or QFX exports - the latest twelve months, a partial month counted by its
    days, one proposal per expense with its categories beneath it. A category
    lands in the expense named for it, else in one of its family, a new one, or a
    bucket that also takes unnamed payees, as an optional [estimate] table leans
    (existing only, new past a share of spending, or always new); the table also
    names the bucket and assigns categories outright. Each expense shows its
    amount now, proposed and the change and the payees behind it, each category
    why it landed there and the transactions behind it; unnamed payees sit under
    the bucket, refunds marked. Proposals can be edited and taken or written as a
    scenario, in the terminal, the web app, retiretui estimate and
    estimate_spending over MCP. A payee can be named, merged with its variants
    under one name, or ignored, as can a single record; ignored records are
    counted nowhere and listed last, after the bucket. In the terminal i ignores
    and c moves a payee to a category typed by its number, or to the bucket as
    0, and ⏎ on a record offers these and sorting every payee containing its
    words; the web gives each record the same menu. The terminal keeps these in
    estimate/patterns.toml in the config directory, whose rules can also test
    the exact payee, a regex, the amount, the export and the date, the most
    specific match winning over the bank's own category; a space at either end of
    a match marks the edge of a word. A file that does not read is left out, and
    said. retiretui estimate --category, --payee, --unnamed or --ignored,
    and estimate_records over MCP, list those records, each with the rule, bank
    category, transaction type or embedded entry that sorted it. --patterns is
    read beside the config directory's file (--no-user-patterns leaves it out),
    and MCP reads that file too, and exports and rules by path, each export named
    by its path.

  • A self-employment income kind: net earnings that pay self-employment tax on
    92.35% of net, Social Security's part up to what the wage base leaves over the
    owner's wages, half of it deducted from ordinary income, and record that share
    as covered earnings. It may be covered by a workplace plan.

  • A salary may state pretax, what the employer takes out before tax - health
    premiums, an FSA - which reaches neither cash, tax, the FICA base nor the
    earnings record; the Ledger lists it where the year's money went, and the
    year's pretax reports it. A salary may say social_security = false for a
    non-covered public job: no Social Security tax, Medicare's still, and nothing
    recorded as covered earnings. The Income form offers both; the mid-career
    couple example shows a pre-tax deduction.

  • The Tax Tables page lists the year's payroll rates. [payroll] in a tax table
    carries them, the statutory rates where a table leaves it out.

  • A 414k account takes by = "after-tax" contributions, as a 401(k) and a
    403(b) do: a public pension's individual account can carry the member's
    after-tax self-pay beside the employer's share. The money is kept as basis,
    held to the plan's yearly cap after the other payers, and comes back untaxed
    pro rata on every draw, through a rollover too.

Fixed

  • The header's palette button is named with the "Ctrl K" it shows, as the
    label-in-name rule asks.

Changed

  • Breaking: every salary pays the employee's payroll tax out of cash -
    Social Security to the year's wage base, Medicare on all wages, and the
    Additional Medicare Tax on the household's wages over $200,000 or $250,000 -
    so a salaried plan's working-year surplus falls by about 7.65% of each salary
    below the base. It lands as payroll in the year's taxes, inside their total,
    and as a "Payroll" line in the Ledger's Tax pane. A payroll HSA contribution
    comes off the FICA base and the earnings record; a 401(k) deferral does not.
  • retiretui_engine: Expense gains phases, ScaledExpense each phase's
    amount at the ceiling, and spending_overlay takes the plan it restates.
    Taxes gains payroll, YearRow pretax and covered - what each person's
    earnings record gained in the year - Income pretax and social_security,
    IncomeKind SelfEmployment, and TaxParams payroll; tax::payroll is
    new.
  • Breaking: building needs Rust 1.97.1. retiretui_tui is built on plurimus
    0.9.0, plurimus_filepicker 0.3.0 and bevy 0.20, and retiretui_client's
    bevy feature on bevy_ecs 0.20, so an app that embeds either moves with it.

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 09 Oct 18:48
9f8d7a5

Changed

  • The Overview's charts are keyed alike in the terminal and the web app. In the
    terminal, Balances keys only the treatments the plan holds, taxable first and
    at the bottom of the stack, then net worth, and lines are "Net worth",
    "Income" and "Taxes". In the web app the market runs' bands are "10th to 90th"
    and "25th to 75th" and their middle line "median". Compare's table of plans
    leads each row with the same light stroke as the Overview's key.

Fixed

  • In the web app a throw on the start screen, in a draft notice or in a group's
    page chips is said in the page's place, the header, the navigation and the
    footer still around it. It took them with it. Opening a plan or going to
    another page tries again.
  • In the web app a page scrolled down stays there when a switch is turned, a row
    is highlighted, or a form is opened or closed. It went back to the top.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 08 Oct 05:16
5bc2987

Added

  • An income may say that its amount is what it pays in its first year, with
    cola_from = "start", and its cola then runs from that year rather than
    from the plan's start. A pension estimate or an annuity contract states a
    benefit that way - a sum payable from a date, with a cost-of-living rate after
    it - and until now a fixed-rate cola also compounded over the years before
    the income began, so a pension of 20,000 at 2% starting five years into the
    plan paid 22,082 in its first year and stayed that far ahead for life. With
    cola_from = "start" it pays 20,000, then 20,400. The first year follows the
    income's start or on wherever a scenario moves it, and an income already
    being paid when the plan starts escalates from the plan's start as before.
    cola_from is "plan" unless stated, is left out of a saved file while it
    is, and no plan that does not state it projects differently. A Social Security
    income is refused it: a benefit is stated in today's dollars and takes its
    cost-of-living adjustments whether or not it is claimed. Expenses, conversions
    and contributions escalate from the plan's start as they did.

    • The Income form, in the terminal and in the web app, asks it as "Grows from"
      beside Growth - "Plan start" or "Its first year" - and not of a Social
      Security income.
    • The MCP server's schema reference says it under Escalation.
    • The public-pension example states Dana's pension this way, so it pays
      42,000 in its first year rather than 45,462.
  • In the terminal planner, and the canvas page that shares its shell, what
    stands over the page no longer vanishes on the frame it closes. A dialog, a
    picker, an item's form and the file picker break up into the page beneath over
    150 ms, and the Messages drawer and the Issues panel slide out through the
    bottom of the body over 180 ms. The page is live again at once: the keyboard
    and the pointer come back on the frame the overlay closes, the dim lifts with
    them, and only what the overlay last drew lingers. Nothing leaves this way
    when motion is reduced or off, when an overlay is replaced by another of
    its kind, or when one closes beneath another that still stands. Menus and
    toasts are as they were.

  • The terminal planner's keys can be rebound. A [tui.keys] table in
    config.toml, beside theme and motion in the user's config directory,
    names a command as the palette lists it and states every key it answers to:

    [tui.keys]
    save = "ctrl-w"
    quit = ["q", "alt-q"]
    sort = []
    ledger = "L"
    • An entry replaces the command's keys whole, and an empty list leaves it with
      none; the command is still run from the palette. The first key stated is the
      one shown.
    • A key is spelled as the key row shows it: ctrl-, alt- and shift- ahead
      of a character or a name - esc, space, backspace, delete, insert,
      home, end, pageup, pagedown, f1 to f12 - with tab, enter,
      up, down, left and right typed for the keys shown as ⇥, ⏎ and
      the arrows. A shifted character is written as itself, G or ?, and
      shift-g is refused saying so.
    • A key another command holds by default is taken from it, which keeps its
      others, and the shell says so once at launch: "[tui.keys] q now runs save,
      not quit". A key two entries state goes to the command the palette lists
      first, and the other entry is left out. A command particular to a page may
      share a key with one of the shell's, as the defaults do, and runs in its
      place while that page is shown.
    • The palette always keeps a key: an entry that empties it, or states the key
      it holds, is left out.
    • An entry that names no command, or states anything that does not read as a
      key, is left out whole, the command keeps its keys, and the shell says which
      and why.
    • Everything that names a key names the one in force: the key row, the help
      picker, the tab bar, a tool's help line. A command left with no key is not
      hinted. A tab names its key only where one cell holds it, so a tab bound to
      alt-1 shows none.
    • The keys a form, a list or a dialog answers to by itself - ⏎, esc and ⇥
      inside them, the arrows in a list - are not commands and are not rebound.
      The canvas page reads the same table from the page's storage, which nothing
      on the page writes.
  • The terminal planner wears themes of your own. A file in themes/, beside
    config.toml in the user's config directory, is a theme named by its file
    name - themes/dusk.toml is dusk - written as the built-in ones are: a
    family, a variant of "dark" or "light", and a colour for each role it
    names, the rest left as the terminal's own, its tables unbanded unless it
    names stripe. It is chosen from the theme picker or by [tui.theme] name
    like any other, and by its family where it states one, the variant following a
    light or dark terminal.

    • retiretui theme list names every theme with its variant, its family and
      where it comes from, and retiretui theme dump <name> prints one's file,
      taking a name as [tui.theme] name does, to start another from:
      retiretui theme dump nord > ~/.config/retiretui/themes/mine.toml.
    • A file named as a built-in theme takes its place, list saying so. A file
      named terminal.toml is left out and said, since terminal is the
      terminal's own colours.
    • The theme picker reads the directory again each time it opens, and puts what
      is worn on afresh, so a theme being written shows without leaving the
      planner. It marks a theme of the user's yours.
    • A file that does not read is said with its path and the reason, at launch
      and as the picker opens. It is listed dimly as does not read, is not kept
      when chosen, and stands for no family, so it hides no other theme.
    • The README has a Settings section: where config.toml is, what [tui]
      holds, and how to start a theme.
  • A Spending Ceiling tool answers how much a plan could spend. It scales every
    expense the household could cut alike and projects the plan whole at each
    step, so tax, Medicare and every other interaction is priced in, and answers
    twice: the most that lasts in the plan's own market, and the most that lasts
    in a target share of its random markets, 90% unless another is set. A run
    lasts as the Monte Carlo tool counts it: never short, and ending with at least
    [market] leave_at_least where the plan states one. Every candidate is walked
    through the same markets, so the answers differ by spending alone. A plan that
    falls short as it stands is answered with less than it spends.

    • An expense may say essential = true: spending the household could not cut,
      which the tool leaves as stated. A one-time expense is left either way. The
      rest is the flexible spending it scales. The key is left out of a saved file
      while false, and no plan projects differently for it. The Expenses form, in
      the terminal and in the web app, ticks it as "Essential".
    • The search judges at most 16 plans for each answer, settles within $100 a
      year of flexible spending, and stops at eight times what the plan spends,
      which it says as "at least". It refuses a plan with no flexible spending,
      and one that falls short even with none.
    • retiretui optimize spending <plan> prints the plan as it stands and both
      ceilings - the flexible spending, its change, the share of markets it lasts
      in and the headline figures - over each expense now and at each ceiling.
      --success sets the target as a fraction, and --write writes the ceiling
      at the target as a scenario that restates each scaled expense's amount. It
      takes --nominal, --format json, --history and --tax-dir as the other
      searches do.
    • The MCP server gains optimize_spending, which replies both ceilings with
      the scenario and stores it with write_to, and its schema reference
      documents essential.
    • The terminal planner has a Spending Ceiling page among its tools, between
      Historical and Tax Tables: both ceilings under the plan's own row, the
      highlighted one's expenses now and at the ceiling, and the target, edited in
      a form and held for the session rather than saved with the plan. The cursor
      starts on the ceiling at the target. It takes what the Overview has already
      found rather than searching again. t or ⏎ takes the highlighted ceiling
      into the plan after asking, as one step that undo takes back, and w writes
      it as a scenario and compares it; the commands are take-spending and
      write-spending. Where the plan asks to leave nothing, the ceiling in its
      own market says that it spends everything by the plan's end.
    • The web app has the same page, the highlighted ceiling kept in the address,
      with a link from that note to Leave at least on the Market page.
    • The mid-career-couple example marks its mortgage essential and
      retired-couple its Medicare premiums; both project as they did.
  • A projected year says how much of its spending was essential and how much
    flexible: expenses_essential and expenses_flexible stand beside expenses
    in each year of retiretui project --format json and of the MCP server's full
    projection. What is neither was spent once.

Changed

  • Breaking. No plan key is removed or renamed, and a plan written for 0.3.0
    projects as it did. What breaks is the Rust API, and the workspace is 0.4.0:
    • The engine's Income gains cola_from, a ColaAnchor, so a struct literal
      of one written outside the engine must add it.
    • The client's Vocabulary gains ColaAnchor, so a match over it written
      outside the client must cover it.
    • The engine's Expense gains essential, so a struct literal of one written
      outside the engine must add it.
    • The engine's YearRow gains expenses_essential,...
Read more

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 02 Oct 22:14
cf56b4c

Added

  • A web app for phones and desktop browsers, at
    https://kenianbei.github.io/retiretui/, published to GitHub Pages at the
    site's root with each release: a page over the engine's JavaScript bindings,
    the unpublished retiretui_wasm crate, and over retiretui_client, the crate
    of what every interface shares, new with this release. It keeps its plans in
    the browser's own storage and never sends them anywhere. The canvas page - the
    terminal planner drawn in a browser, which 0.2.0 published at the root - is
    beside it at /ratzilla/ and keeps its plans apart from the app's: a plan
    made in the 0.2.0 page is still there, and reaches the app by a download from
    that page and an upload to the app.
    • Start. The Start page opens with a sentence on what RetireTui does. A
      first plan is made from a few questions asked a step at a time - the
      household, then each person - which read every answer back to be changed
      before the plan is named, made and opened on the Overview; a blank age,
      start of work or Social Security benefit reads as what the plan will
      assume - Blank is 65 while answered, 65, the default read back - and the
      answers survive a reload until the plan is made. The example plans and an
      upload are offered beside them. The app reopens the plan last open, and
      downloads the open plan; a plan that does not open is said on the Start page
      by the file that failed, the line and why, with that file to download or
      replace by an upload, and its text as written beneath, the failing line
      marked.
    • Overview. It reads as the ledger's first page. It leads with how long
      the money lasts, the share of a thousand random markets it survives - run
      off the page's thread, and leading to the Monte Carlo tool - what it ends
      with and what it pays in tax, in today's or future dollars and in the
      terminal's words, as rows of a label and a figure on a phone; a plan that
      runs short is noted above them with the year it first does and what it
      leaves uncovered, leading to that year in the Ledger and to Expenses, and
      how long the money lasts then reads the last year it covers. Beneath is what
      to do in the year shown, in the dollars shown and said as the terminal says
      it: today's by default, stepped by button or the arrow keys, or chosen with
      a click on a chart, and leading to that year in the Ledger. Then what needs
      attention - the worst historical start the plan does not survive and how
      many fail, as the terminal says it, leading to the Historical tool on that
      start; the years the plan pays Medicare's surcharges, contributions held
      back, a benefit estimated without its earnings record, an amount too large
      to be likely - and what could do better, each row leading to its year in the
      Ledger, its item or its tool. Could do better gives each Roth owner's best
      ladder, the household's best claims and the best withdrawal order against
      the plan as it stands, each leading to its tool, a ladder's aimed at that
      owner's account; what it finds is what the tools then show without searching
      again. What to do, the milestones, what needs attention and what could do
      better sit four across on a wide page, two on a narrower one. Beneath them,
      all shown at once and two across on a wide page, the plan's balances by tax
      treatment under its net worth, its net worth, its income against its taxes,
      and its net worth through the random markets as percentile bands, each
      salary's end marked and listed under its chart, each chart read as one image
      with the Ledger as its table.
    • Ledger. It shows the plan year by year, the year column staying in view
      as the table scrolls sideways, and the chosen year's flows through each
      account - where each came from or went, with the year's warnings - and its
      income and what it paid, beneath the table on a wide screen and above it on
      a phone, where no page scrolls sideways but its tables. The year and the
      dollars are in the page's address, kept between the Overview, the Ledger,
      Compare and the tools and across a reload.
    • Plan pages. They edit the plan: each domain's items are a table sortable
      by its columns, or rows with a Sort by on a phone, beside the highlighted
      item read out in the form's words - a field left blank read as what it
      stands for, muted, such as Earns nothing or 6%, the default, and the
      Market's fields under headings - and a domain there is one of is that
      read-out alone. Edit, Add and Delete work one item at a time; the form is a
      sheet, full screen on a phone, whose fields are entered by their kind -
      picks from the schema's sets and the plan's own ids, a searched list for a
      country or U.S. state, a slider beside a rate, a trigger as its kind and
      sentence - and applying stores the whole item or says why not. Every applied
      item or deletion is a step Undo and Redo walk, by button or Ctrl/Cmd+Z, and
      Save or Ctrl/Cmd+S writes the plan back through the same validation as every
      other surface; Save as… writes it under another name. A scenario opens
      read-only. Unsaved edits are asked about before a form closes, another plan
      opens, or the page is left, and a file changed in another tab under them is
      reported rather than overwritten. A plan with issues counts them in the
      header and lists each by the page, item and field it is about, each a link
      to that field in its form, while the figures keep the last ones it had
      without issues. A Social Security statement downloaded from ssa.gov is
      imported onto a person from the People page as one step of history.
    • Roth Conversions. The tool searches every fillable bracket's conversion
      ladder, ranks them under the plan as it stands, each saying what it ends
      with against the plan, and shows the highlighted one's conversions year by
      year beside them on a wide page, in either dollar basis, over the
      constraints it searched under, read out and edited in a sheet; it searches
      again whenever the plan or the constraints change, and takes the plan's one
      Roth account as the destination where there is only one. The highlighted
      ladder is taken into the plan after asking, as one step of history in place
      of any ladder taken before, or written as a scenario beside the saved plan,
      compared with it at once and offered to open.
    • SSA Benefits. The tool ranks every claim age for the household's
      computed Social Security benefits under the plan as it stands, each against
      the plan as a ladder is, beside each person's earnings record, how their
      benefit is set and the benefit estimated at 62, full retirement age and 70,
      with what can be done for the highlighted person: import a statement,
      estimate a record from their salary, compute a stated benefit from their
      record, clear the record or remove the benefit - the last two asked first -
      each one step of history, or hold their claim as the plan states it while
      the others are searched. The highlighted claims are taken into the plan
      after asking or written as a scenario, as a ladder is; the claims
      highlighted, the person and who is held are kept in the address.
    • Withdrawal Order. The tool ranks the orders the plan can withdraw in, by
      the search said further down, under the plan as it stands, the highlighted
      one taken into the plan after asking, as one step of history, or written as
      a scenario and compared at once. The highlighted order is kept in the
      address.
    • Monte Carlo and Historical. The tools run the plan through a thousand
      random markets, or from every historical start year worst first, and say how
      it fared in one sentence - Money lasts in 87% of 1,000 markets - in the
      colour of its zone - as the Overview's figure is coloured - beside what the
      runs were made under, each a link to the Market field it is edited at;
      beneath the runs singled out, all shown at once, are the spread of net
      worth - percentile bands in a neutral - under the highlighted run's line,
      the share still funded, what the runs end with, and net worth by year at
      each percentile (Monte Carlo only). The highlighted run opens in the Ledger,
      replayed through its market and named by it - a random market's number, or
      the year retired into - kept in the address through the year, the dollars
      and edits, with a link back to the plan's own.
    • Compare. It sets the plan beside the plans chosen for it from the
      workspace, the plan files the app keeps. It shows each plan's figures and
      its success through random markets - each plan searched in a worker of its
      own - or its differences from the one chosen as the baseline, what the
      highlighted plan changes of the baseline, and one of eight metrics year by
      year, charted beside its table. A plan alone is offered another from the
      workspace, or, where there is none, an example written beside it and
      compared at once. The plans compared, the baseline and the metric are kept
      in the address, the plans compared carried by every link; opening a compared
      plan puts it in the open plan's place with that plan joining the compared,
      and opening any other plan leaves nothing compared.
    • Tax Tables. The tool reads out the tables the plan's projection applies
      in the year shown - brackets, deductions, long-term gains, Social Security's
      thresholds and benefit formula, the contribution limits, Medicare
      surcharges, the RMD divisors and the state's income tax - in columns as many
      as the page holds - for the plan's filing status and the state it lives in
      that year, grown past the last published table at the plan's inflation, or
      for any status or modeled state picked.
    • Plans and files. The header names the open plan, marked with a dot while
      it has unsa...
Read more

v0.2.0: chore: release 0.2.0 (#13)

Choose a tag to compare

@github-actions github-actions released this 27 Sep 17:05
729fa93

Added

  • A form too tall for the terminal scrolls: its fields scroll above a help line
    and buttons that stay put, the field holding the keyboard is kept in view, the
    mouse wheel scrolls it, and a scrollbar on its right edge shows where it is.
  • An account's glide path is edited as up to six steps, each step offered once
    the one before it is filled; a file's steps past the sixth are kept as they
    are.
  • A mix's cash, and each glide step's, is shown beside its stocks and bonds as
    what they leave, following them as they are edited and marked when they leave
    less than none.
  • The Market form edits the stocks-cash and bonds-cash correlations.
  • A new plan can start from one of the ten example plans, picked at the top of
    the new-plan form and saved under the example's name.
  • The new-plan form asks when each person started working, and takes a retired
    person's salary as what they last earned, so a retiree's Social Security is
    computed from their career as a worker's is. A retiree who has not reached
    their claim age claims at it.
  • On the Monte Carlo and Historical pages the cursor rests on "As planned", and
    ⏎ there shows the plan's own projection in the Ledger.
  • The planner runs in a browser page, published to GitHub Pages with each
    release. Its workspace is kept in the browser's own storage and never leaves
    it; the page reopens the plan last open, follows the browser's light or dark
    preference, and Quit starts it over. upload and download, in the page's
    command palette, bring plans, scenarios and Social Security statements in -
    asking before one replaces a file of the same name - and take the open
    document's file back out as saved. Searches run on the page between frames, so
    a large Monte Carlo run holds the page until it answers.

Changed

  • A form stands only as tall as the fields the item has a use for, and the
    smallest terminal the planner takes no longer grows with its tallest form.

  • The Roth Conversions tool converts into the plan's one Roth account without
    asking, so its ladders are ranked on a first look.

  • The Ledger's detail is as tall as the cursor year needs, up to half the page,
    and Income & Tax leaves out what the year paid nothing on.

  • The key row's words are shorter, so more of each page's keys fit at 128
    columns, and a tool's write and take keys are shown only once there is
    something to write or take.

  • A table too narrow for its columns cuts a long header before any cell, and one
    with room to spare uses all of it. A tool table's message wraps rather than
    being cut off.

  • The status bar cuts a long file name in the middle, keeping its end.

  • Every built-in theme colours the good and caution zones from its own palette,
    and draws a text caret in its accent. The market runs table's title carries
    the zone colour.

  • Roth Conversions, SSA Benefits and Historical, opened on a plan the Overview
    has already searched, show the Overview's answer at once rather than searching
    the same plan again.

  • The minimum versions of the engine's and the binary's dependencies are now the
    versions they are built and checked against.

  • Validation names the entry at fault in a list: a negative prior-year MAGI is
    reported at medicare.prior_magi[i] and a repeated withdrawal class at
    plan.withdrawal_order[i], rather than at the whole list.

  • An item open in a form while the plan changes underneath is followed to
    wherever it now sits: applying no longer refuses because an undo or a reload
    moved it. It is still refused when the item itself was changed or renamed.

  • optimize conversions and MCP sweep_conversion_brackets list the brackets
    best first - the least left unfunded, then the most left at the end - as the
    Roth Conversions tool does, rather than by rate.

  • The conversion source is optional: without --from on the CLI, or from over
    MCP, a ladder converts from every deferred account of the destination's owner,
    as the Roth Conversions tool does when its source is left blank. Where that
    owner holds none, the search says there is no deferred account to convert
    from.

  • The new-plan form numbers the ids it makes from a person's name, as new items
    are numbered: Alice is alice-1, a second Alice alice-2, and their
    retirement and workplace account follow as retire-alice-1 and
    alice-1-401k.

  • MCP project_plan and tax_parameters describe their replies with full
    output schemas - summary or full rows, and every tax table - and an issue in
    any reply is described as the engine's own. Replies are unchanged.

  • A computed Social Security benefit is priced at the claim's age in months, not
    whole years: a claim on a date is priced from that date's month, and a claim
    on an event or another income from the month of the date or age it rests on. A
    claim at 62 starts in the first month 62 is held throughout, the month after
    the birthday unless it falls on the 2nd, so most claims at 62 are 59 months
    early rather than 60. A computed benefit claimed before the month 62 is
    attained is refused.

  • Every Social Security income's first year, typed or computed, is paid from the
    month it starts, not only one started on its owner's age.

  • Credits for delaying past full retirement age that are earned in the claim
    year are paid from the next January, as SSA pays them, except for a claim
    at 70.

  • A benefit whose owner turned 62 before the plan starts is carried to the
    plan's first year by the COLAs SSA published, truncated to the dime after
    each, rather than at the plan's inflation. The tax tables carry every COLA
    from 1975 to 2025.

  • A person with no earnings record is taken to have worked from 22 until the
    plan at the salary its first year pays them, so a computed benefit counts the
    years before the plan; a stated record, even a partial one, is used as it
    stands. The Overview says the benefit comes from an estimated career.

  • An earnings statement row stating several years as one sum is spread evenly
    over them rather than refused, and the import says which years it spread; MCP
    import_earnings says so in a new note.

  • A tax parameter file for a year that leaves out a state takes that state from
    the latest earlier year that has it, inflated, so a plan living there is no
    longer refused.

  • The engine is 0.2.0: tax::social_security_benefit takes an age in months and
    the COLAs to carry the benefit through, tax::claim_year_share takes the
    first paid month, BenefitParams gains cola, Statement gains grouped,
    and StatementError::Grouped is gone. optimize::optimize_claims and
    optimize::sweep_brackets take a Progress and answer a RunError, which
    now live in a search module and are still re-exported from market.

  • A conversion sweep searches its brackets side by side on the machine's
    threads, so optimize conversions without --bracket, MCP
    sweep_conversion_brackets and the Roth Conversions tool answer in about half
    the time.

  • A claim or ladder search that a newer one replaces - an edit made while the
    Overview, SSA Benefits or Roth Conversions page is searching - stops rather
    than running to its end, and the SSA Benefits page works out each person's
    estimates off the main thread.

  • Turning back to an editing page whose plan has not changed keeps its table as
    it was rather than rebuilding it, typing in a picker rewrites its rows rather
    than making them anew, and tab finds the page's panes without visiting every
    row of its tables.

  • The interactive planner is its own library crate, retiretui_tui, which the
    tui subcommand and the browser page both run; the CLI and MCP take their
    plan-file reading and the words their tables and actions are said in from it.
    It reads and writes every plan file through a Store - the disk, or keys in a
    browser's storage - and is built on plurimus 0.7.2 and plurimus_filepicker
    0.1.1.

Fixed

  • A computed Social Security benefit claimed before the plan starts is priced at
    the age it was claimed at, not at the age its owner has reached in the plan's
    first year.
  • Taking a searched Roth conversion ladder no longer removes a conversion of
    your own whose id happens to start with opt-; only the optimizer's own
    opt-<account>-<year> conversions are replaced.
  • After a reload fails, the planner and the Compare page watch the files the
    plan now reads, so fixing a newly named base plan is picked up without
    pressing r.
  • An issue against one place of a list in a form - one year's prior income -
    marks and names that row alone, not every row of the list.
  • A list a form refuses keeps its amounts written as money once the keyboard
    leaves them, rather than as bare digits.
  • A value an item has no use for, cleared by hand, leaves the form once the
    keyboard leaves its row.
  • A trigger's kind menu lists its blank - the plan's start, say - first.
  • The new-plan form refuses to write a plan that does not validate, as every
    save does.
  • An issue against one step of a glide path marks that step's row in the form.
  • A mix whose stocks are written as a whole number, stocks = 1, no longer
    gains a full share of cash when applied.
  • The Ledger's warnings state their amounts in the dollars on show, not always
    in nominal dollars.
  • A click in a table whose pane has grown, after a terminal resize say, lands on
    the row drawn under the pointer.
  • A person's claim held out of the claim search is no longer held for a person
    of the same id in the next document opened.

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Sep 23:19
688f3ba

Added

Plans

  • Plan files: a TOML description of a one- or two-person household - people,
    accounts, income, expenses, contributions, transfers, conversions and events.
  • Accounts: 401(k), 403(b), 457(b), 414(k), traditional and Roth IRAs, HSA,
    brokerage and cash, with cost basis, locks and a withdrawal order.
  • Triggers: anything starts or stops on a date, an age, or a named event or
    income, with a year offset.
  • Escalation: each amount grows with inflation, stays flat in nominal dollars,
    or grows at a rate of its own.
  • Contributions: fixed dollars, a share of salary, the legal maximum, or an
    employer match, held to each year's IRS limits.
  • Residency: where the household lives over time; state income tax follows a
    move.
  • Scenarios: a file naming a base plan and stating only what differs from it.
    Scenarios can build on other scenarios.
  • Market assumptions: per-account stock, bond and cash mixes or glide paths, and
    a [market] table of returns, volatility and inflation.
  • Social Security: a benefit stated as an amount, or computed from the person's
    earnings record with SSA's formula.
  • Opt-in Medicare IRMAA surcharges, and MAGI cliffs such as ACA premium credits.

Engine

  • Federal tax: brackets, capital gains, taxation of Social Security, RMDs,
    early-withdrawal penalties and contribution limits, with 2026 tables built in.
  • State income tax for Oregon and the states without one.
  • Year-by-year projection in nominal dollars, readable in today's dollars, with
    tax-aware withdrawals.
  • Each projected year lists the actions taken: contributions, transfers, RMDs,
    conversions, withdrawals and surplus saved.
  • Monte Carlo runs from the plan's assumptions or resampled history, and
    historical runs from every start year since 1871.
  • Tax tables and market history can be replaced by files in the user config
    directory.

Command line

  • validate, project (text or JSON), actions (one year's to-dos) and
    compare (plans side by side).
  • optimize conversions: finds the Roth conversion ladder that fills a tax
    bracket, optionally under an IRMAA tier or MAGI cap.
  • optimize claims: ranks Social Security claim ages for the household.
  • Both optimizers can write their result as a scenario.
  • monte-carlo and historical: how often the plan's money lasts, with
    percentile runs.
  • import-earnings: records the earnings from an ssa.gov statement on a
    person.
  • mcp: the same tools for AI agents over the Model Context Protocol, limited
    to one directory, with a plan schema reference.

Interactive planner

  • retiretui tui: a keyboard- and mouse-driven planner for a plan, a scenario
    or a directory.
  • Overview: whether the money lasts, milestones, warnings, the year's to-dos,
    balance charts and suggested improvements.
  • Ledger: every year's totals, and each account's flows, income and taxes for
    the selected year.
  • Compare: the open plan beside other plans, with their differences and charts
    by year.
  • Tools: the conversion and claim-age searches, Monte Carlo and historical runs.
    A result can be applied to the plan or saved as a scenario.
  • Editing: a page per plan section and a form per item, validated on apply, with
    undo and redo.
  • A new-plan form that builds a starting plan from a few answers.
  • A file picker for opening and saving; open files reload when they change on
    disk.
  • A command palette, key hints, a message log, themes and reduced motion.

Project

  • Example plans in examples/.
  • Crates on crates.io and prebuilt binaries for x86_64 and aarch64 Linux.