TODO.md carries the remaining work with the reasoning already settled, so the next agent does not re-derive decisions: tasks 3-6 of the versioned-rules plan, the designed-but-unbuilt baked FX rates, the queued visual redesign, the small residuals, and an explicit list of what only a human with a browser can check. ARCHITECTURE.md explains the layer rules, the single-implementation fold, the mutation pipeline's three deliberate properties, and the gotchas that each cost a real bug — reading a deferred event.target.value, an unset BUN_PUBLIC_* var reaching the browser, and overriding shadcn's --accent. CLAUDE.md gains those gotchas, the dated-rule model that replaced standingRule, the validation this project deliberately omits, and an explicit statement that visual and offline behaviour cannot be verified in the agent environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4.8 KiB
TODO
Work queued for whoever picks this up next, human or agent. Ordered. Each item says enough to act on without re-deriving the reasoning.
Current state: branch feature/versioned-rules, 6 commits ahead of main,
not merged, not pushed. 270 tests passing, bunx tsc --noEmit clean,
bun run build succeeds. The branch is coherent to stop at: SCHEMA_VERSION is
2 and its migration exists, so existing data opens.
1. Finish time-versioned allocation rules (Tasks 3-6 of 6)
Spec: docs/superpowers/specs/2026-09-02-versioned-allocation-rules-design.md
Plan: docs/superpowers/plans/2026-09-02-versioned-allocation-rules.md
Ledger + extracted briefs: .superpowers/sdd/2026-09-02-versioned-allocation-rules/
Tasks 1-2 are done and reviewed clean: Post.rules: RuleVersion[] replaced
Post.standingRule, and the v1 -> v2 migration landed.
| Task | What | Brief |
|---|---|---|
| 3 | setRuleFrom / removeRuleFrom actions |
task-3-brief.md |
| 4 | JSON import validation for the rule series | task-4-brief.md |
| 5 | Rule-history editor in Settings | task-5-brief.md |
| 6 | "Change from here" control in the month view | task-6-brief.md |
To resume: read the ledger's handoff section, then execute with
superpowers:subagent-driven-development (or by hand — the briefs are complete,
with real code in every step).
Watch for: Task 3 must make setRuleFrom REPLACE an existing version for the
same month rather than append. Two versions sharing a from make the effective
rule ambiguous, and ruleAt would resolve arbitrarily.
2. Baked FX rates — designed and approved, not built
So a fresh install can convert a EUR purchase on day one instead of erroring.
build.tsfetches DKK/USD/EUR at build time and embeds them viadefine; on any network failure it falls back to committed constants rather than failing the build. Fetched rates getsource: "api"with the build date; the fallback constants getsource: "manual", so Settings never claims a hardcoded number came from an API.- They seed a new dataset only. They must NOT act as a fallback whenever a
rate is missing — that would undo a deliberate decision: clearing a rate
removes the row so
MissingRateErrorsurfaces, instead of silently converting money at a number the user never chose. - Domain purity forces the shape:
createSeedDatasettakes the rates as an argument; the env read lives in a newsrc/store/bakedRates.ts, in the store layer, using thetry/catchaccessor pattern (see CLAUDE.md gotchas).
3. Visual redesign
The owner's words: "right now it looks a bit boring, simple and ugly. We want sleek, modern, and nice to use." Sequencing was their explicit choice: finish all six rules tasks first, then redesign everything.
PRODUCT.md exists and holds product truth. There is no DESIGN.md; the
incumbent visual world is the --budget-* tokens in src/index.css plus the
design contract summarised in ARCHITECTURE.md. A redesign should treat that as
evidence and anti-reference, not as something to preserve.
4. Smaller items, in no particular order
confirmImporthas no.catch(src/ui/routes/settings/DataSection.tsx). A failed import write is an unhandled rejection with no error shown. One line.- PNG icons 192/512 are not shipped, so Chrome's install prompt is incomplete. Binary assets cannot be generated in the agent environment; a human needs to add them.
round2insrc/store/actions.tshardcodes 2 decimals rather than readingCURRENCY_DIGITS. Correct for DKK/USD/EUR; silently wrong the day a non-2dp currency is added. Same latent issue insliceTotal(src/domain/plans.ts).EMPTY_FIGURES(src/domain/fold.ts) is exported non-frozen and returned by shared reference fromfiguresFor. No consumer mutates it today;Object.freezeis a one-line hardening.buildWorkbookcallsmonthViewper (post, month), making a full ODS export O(posts x months^2). Fine at personal-budget scale.- The dev-only
src/manifest.webmanifestplaceholder hardcodesscope: "/". Harmless in production, misleading if you dev-serve under a subpath.
5. Needs a human with a browser
Nothing in the agent environment can run a browser, so these have never been seen by anyone:
- the carry meter under each post row in the month view — the signature design element, verified only as a CSS gradient expression;
- offline behaviour, the install prompt, and the update prompt;
- the generated
.odsopening in a real spreadsheet (validated structurally: mimetype first and stored, well-formed XML, numeric cells); - keyboard flow in fast entry — Tab traversal, Backspace-to-remove, and focus placement after a row auto-appends;
- GitHub Actions has never been executed.