# TODO Work still queued, for whoever picks it up next, human or agent. Ordered. Each item says enough to act on without re-deriving the reasoning. Finished work is not listed here. It is in the commit messages, and the decisions behind it are in `docs/specs/` — one spec per sub-project, each recording the alternatives that were rejected. Rules that outlived their task moved to `AGENTS.md`. **Current feature worktree state:** budget folders and recurring cost placement are implemented. 712 tests passing across 55 files. `bunx tsc --noEmit` is clean; `bun run --bun build` succeeds using the committed seed rates when live-fetch is unavailable. The runtime override bypasses a broken local Bun shim. **Schema is at version 8.** v1 -> v2 made allocation rules a dated series; v2 -> v3 moved currencies into the dataset; v3 -> v4 drops a stored rate-service URL that can no longer work; v4 -> v5 adds sterling to an existing dataset; v5 -> v6 collapses per-currency decimals into one dataset-wide setting; v6 -> v7 adds `Dataset.recurring`; v7 -> v8 adds budget folders and assigns existing posts and recurring bills a deterministic mixed sibling order under Unfiled. All seven are behaviour-preserving by construction — not one changes a stored figure — and are tested as such. A migration applies **on load, in memory**; it is written back on the next mutation, not by `load()` itself. So a freshly migrated dataset shows the new shape immediately while IndexedDB still holds the old version for a while. That is not a bug, but it will mislead you if you verify a migration by reading IndexedDB instead of the app. --- ## Optional monthly income forecast Add a user-controlled toggle that predicts a month's income from earlier months. For each earlier month, divide its recorded income by that month's number of workdays; average those per-workday figures, then multiply by the target month's workdays. Let the owner adjust the prediction when income changes, for example after a raise, without rewriting recorded income or earlier months. Show predicted and entered income distinctly, and keep budgeting based on entered income unless the owner explicitly chooses otherwise. Before implementation, settle whether workdays mean Monday–Friday only or exclude local holidays, and whether an adjustment applies to one month or all future predictions. ## 1. Folder rename blur during an in-flight save A folder name draft can remain unsaved if the owner changes it while a rename save is in flight and then blurs the field before that save finishes. Preserve the newer draft and ensure the blur requests a subsequent save after the pending write completes. Cover the delayed-write sequence with a UI interaction test, including the final persisted name and any surfaced write error. ## 2. Recurring split editor interaction coverage `RecurringSplitEditor` has coverage for destination selection and dedicated post creation, but its rendered split mode and value controls lack a focused interaction test. Exercise the real controls to switch percentage/fixed mode and edit a split value, then assert the resulting splits and remainder behavior. Keep this scoped to the editor's user interaction; domain split calculations already have their own tests. ## 3. Visual redesign, sub-project 3 — Year, Summary, Post detail The owner's brief for the whole redesign: *"right now it looks a bit boring, simple and ugly. We want sleek, modern, and nice to use."* On scoping: both themes with a toggle, a full rethink of every screen, purchases compact and grouped by date, ship a webfont — and *"override everything you want for this step."* Sub-projects 1 (design foundation, `bb3c661`) and 2 (month view, `7b71811`) are done, each with a spec in `docs/specs/`. These three screens are on the new foundation but have not been rethought. The open question is the 12-month matrix: it only fits by scrolling, and compact number formatting may be what replaces that rather than a scroll container. **The diagnosis that shaped the decomposition, which still applies:** a design system already existed and was never wired up. `src/index.css` defined the paper/ink/teal palette with a contract document behind it, while the app painted shadcn's default white and near-black; the tokens reached the screen in two places only. Doing the foundation last is how that happened. Do not repeat it — extend the foundation rather than styling a screen locally. **Three things sub-project 2 settled that these screens should inherit rather than re-decide** (spec: `2026-09-02-month-view-design.md`): - **Meter geometry lives in `src/ui/meterSegments.ts`**, pure and tested, with `` as the only thing that paints it. A third meter belongs there too, not inline in a component. Negatives clamp rather than invert, because a segment of negative width puts the gradient's stops out of order and paints something arbitrary instead of failing. - **Two markups, not one reflowing grid.** The post table is a real `` from `sm:` up and a list of two-line blocks below it. At 390px the layout genuinely stops being a table, and `role="table"` on it would describe rows and columns that no longer exist on screen. The year matrix faces the same question with more columns to lose. - **State the currency once per table, not per cell.** Every figure in the post table is base currency, so `formatSignedAmount` prints bare numbers and the legend names DKK once. This is what stopped "+4,219.61 DKK" wrapping on a phone. `formatMoney` is still right wherever an amount can be in some other currency — every purchase row, for one. ## 4. Visual redesign, sub-project 4 — dialogs and fast entry Untouched. Native `