docs: refresh current behavior and outstanding work
Continuous Integration / lint-and-test (push) Successful in 18s
Continuous Integration / docker-build-and-push (push) Successful in 1m11s

This commit is contained in:
Lucas Winther committed 2026-10-03 16:50:58 +02:00
1 parent c250bbe476
commit 5c6cee0f0b
4 files changed
+60 -24

No files matched your search

+7 -1
View File
@@ -67,9 +67,15 @@ in a field, those shortcuts use the browser's text undo. History holds up to
Both destructive actions there — Import, and "Reset everything" — download a
backup of your current data before replacing it, and abort if that download
fails. Reset puts the app back to a brand-new install: the three starter posts,
the DKK/USD/EUR currency table, this month at zero income, no purchases.
the DKK/USD/EUR/GBP/JPY/AUD/CAD/MXN currency table, this month at zero income,
no purchases. Decimal places are one setting for the whole budget.
Import and reset clear session undo history after they succeed.
The month page shows Actual available beside Spent: entered income minus actual
spending for that month. Show chart and Expected's Expand/Collapse controls
remember their state in this browser. Add purchase can create a new recurring
cost; enable choosing existing bills under Settings → Recurring costs.
## Known limitations
- **Data is per-browser.** There is no account and no sync. If you clear this
+29 -5
View File
@@ -32,6 +32,14 @@ record.
## Money and the data model
- **Actual available is this month's income minus actual spending.** Unpaid
bills, allocations and carry are separate figures. Purchases still count
before the envelope fold's start.
→ [`specs/2026-10-03-month-and-purchase-refinements.md`](specs/2026-10-03-month-and-purchase-refinements.md)
- **JPY, AUD, CAD and MXN seed new budgets only.** Existing currency tables
remain under the owner's control; all currencies use the dataset's precision.
→ [`specs/2026-10-03-month-and-purchase-refinements.md`](specs/2026-10-03-month-and-purchase-refinements.md)
- **Money is a float, not an integer of minor units.** Made safe by two rules
rather than by the type: round at every boundary, and compute a distributed
last part as `total - sum(others)`.
@@ -53,7 +61,7 @@ record.
code change. The compile-time safety is replaced by validation at the
boundaries — `parseDatasetJson` rejects a code no currency defines.
→ `src/domain/types.ts`, commit `cdece63`
- **Every derived number comes from one left fold.** `src/domain/fold.ts` is the
- **Envelope rollover has one left fold.** `src/domain/fold.ts` is the
only implementation; year and summary views aggregate over it rather than
recomputing. Two screens disagreeing about someone's money is the worst
failure this app has. → [`ARCHITECTURE.md`](ARCHITECTURE.md)
@@ -89,6 +97,12 @@ record.
## Recurring costs
- **Creating a recurring cost is the default recurring action in Add purchase.**
Choosing an existing bill is enabled explicitly in Settings; ordinary purchases
still start unlinked, and editing preserves an existing link. Chosen over
showing existing bills on every new purchase.
→ [`specs/2026-10-03-month-and-purchase-refinements.md`](specs/2026-10-03-month-and-purchase-refinements.md)
- **A recurring cost may have no post.** It still appears as due, while no
envelope projection moves; confirming it records an unassigned purchase.
This lets the purchase dialog turn an unassigned charge into a bill without
@@ -150,6 +164,11 @@ record.
## Design system
- **Chart visibility and Expected's expanded state persist per browser.**
Chosen over resetting on every visit or moving display choices with a JSON
budget export, following the theme's storage boundary.
→ [`specs/2026-10-03-month-and-purchase-refinements.md`](specs/2026-10-03-month-and-purchase-refinements.md)
- **Two token layers.** `--budget-*` is the app's own vocabulary; shadcn's
entire variable set points at it, so every primitive inherits both themes.
→ [`specs/2026-09-02-design-foundation-design.md`](specs/2026-09-02-design-foundation-design.md)
@@ -194,6 +213,11 @@ record.
## Build, offline and deploy
- **Colophon shows a source ref and a separate UTC build date.** A ref alone
cannot tell when the artifact was built; the browser's current day cannot
describe it. Source archives do not invent a Git ref.
→ [`specs/2026-10-03-month-and-purchase-refinements.md`](specs/2026-10-03-month-and-purchase-refinements.md)
- **Bun is the runtime, package manager, bundler and test runner.** shadcn/ui
components are vendored into the repo and owned by this project.
→ [`specs/2026-09-01-budget-app-design.md`](specs/2026-09-01-budget-app-design.md)
@@ -251,8 +275,8 @@ Not oversights. Each was decided against, and reopening one needs a reason.
amounts are all **allowed**. Adding validation is a regression.
→ [`AGENTS.md`](../AGENTS.md) §3
- The income field and the split editor's fixed-amount fields **do not parse a
currency**; only the purchase total does. → [`TODO.md`](TODO.md) §5
- **No currency picker.** Adding a currency means typing code, name, symbol and
decimals by hand. → [`TODO.md`](TODO.md) §5
currency**; only the purchase total does. → [`TODO.md`](TODO.md) §7
- **No currency picker convenience.** Adding a currency means typing its code,
name and symbol by hand. Precision is dataset-wide. → [`TODO.md`](TODO.md) §7
- **Symbol collisions resolve to the first currency defined with that symbol.**
Tested and documented rather than solved. → [`TODO.md`](TODO.md) §5
Tested and documented rather than solved. → [`TODO.md`](TODO.md) §7
+4 -2
View File
@@ -74,8 +74,10 @@ Confirmed and in place:
- The month header shows actual available: that month's entered income minus
actual spending, including unassigned purchases and refunds. Monthly breakdown
can be hidden and Expected collapsed; these choices persist in this browser.
- Multi-currency (DKK/USD/EUR) against a user-maintained exchange-rate table,
with an optional on-demand fetch that fails soft and is never required.
- Multi-currency against a user-maintained exchange-rate table. New budgets
start with DKK, USD, EUR, GBP, JPY, AUD, CAD and MXN; existing currency tables
stay under the owner's control. An optional on-demand fetch fails soft and
is never required. Decimal places are one setting across all currencies.
- JSON export/import and ODS (spreadsheet) export, both generated in the
browser. On each app start, a separate browser-stored session backup is made
before editing is available; recent daily, weekly and monthly checkpoints can
+20 -16
View File
@@ -8,9 +8,9 @@ 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 state:** the anchored model is merged with budget folders and
placement. The month pie showcase, browser-stored session backups, and
unassigned recurring costs are implemented. 911 tests pass across 66 files;
**Current state:** the month and purchase refinements landed in `c250bbe`,
building on the merged anchored model, budget folders and session backups.
911 tests pass across 66 files;
`bunx tsc --noEmit` is clean, and `SKIP_FX_FETCH=1 bun run build` succeeds
using the committed seed rates.
@@ -156,11 +156,12 @@ folders, placement and nested bills. Everything below is known and unfinished.
### A bill created from the purchase dialog has no folder choice
Settings' new-bill form picks a folder; the dialog's "+ New recurring cost…"
does not. The new bill nests under its post when it has exactly one split
(the same default Settings applies), otherwise it lands in Unfiled and has to
be moved from Budget folders. Decide whether the dialog needs the picker or
whether moving it afterwards is fine for an occasional action.
Settings' new-bill form picks a folder; the dialog's "Create a recurring cost
for this purchase…" does not. The new bill nests under its post when it has
exactly one split (the same default Settings applies), otherwise it lands in
Unfiled and has to be moved from Budget folders. Decide whether the dialog
needs the picker or whether moving it afterwards is fine for an occasional
action.
### "Unlink from bill" was replaced by the Recurring cost select
@@ -178,12 +179,14 @@ absence.
The merge was checked by the full suite, `tsc`, a build, and screenshots of
the month page and Settings with demo data (both render, no console errors,
Car insurance shows "Next 2026-10-19" after charges on 3 and 19 September).
Not yet clicked through by anyone:
The October round verified purchase save/reopen, creation of a new bill with its
first charge, and the Settings toggle for selecting existing bills. Remaining
browser checks:
- tagging a new purchase to an existing anchored bill and seeing its next due
date move in the Budget tree and in Expected;
- "+ New recurring cost…" end to end, including where the new bill appears in
Budget folders;
- placement of newly created bills in Budget folders, including both a bill
nested under its one post and a multi-post bill in Unfiled;
- untagging an edited purchase via "None";
- the Settings anchoring control switching a never-charged monthly bill to
"the last charge" (its month-only start should expand to the 1st and the
@@ -232,9 +235,10 @@ than re-decide** (spec: `2026-09-02-month-view-design.md`):
## 6. Visual redesign, sub-project 4 — dialogs and fast entry
Untouched. Native `<select>` elements are still browser-default, and
`up` / `down` / `archive` in Settings are bare text buttons. Covers the purchase
dialog, the split editor, the plan editor and bulk entry.
The broader visual redesign of the purchase dialog, split editor, plan editor
and bulk entry is still queued. Existing selects are themed, and the October
round made the purchase dialog scroll within a phone viewport; those targeted
changes do not complete the redesign.
There is already a spec for fast-entry *behaviour* —
`2026-09-02-fast-entry-refinements-design.md`. Read it before restyling, so the
@@ -250,8 +254,8 @@ reason.
same three-line pattern. The income field is arguably wrong to make
multi-currency at all, since a month has one income.
- **No currency picker convenience.** Adding a currency means typing the code,
name, symbol and decimals by hand. A bundled ISO 4217 list would be nicer, and
is pure data.
name and symbol by hand. Precision is dataset-wide. A bundled ISO 4217 list
would be nicer, and is pure data.
- **Symbol collisions resolve to the first currency defined with that symbol.**
Fine for one "$" currency; if the owner adds two, typing the code
disambiguates and nothing warns them. Tested, documented, not solved.