CLAUDE.md, AGENTS.md, ARCHITECTURE.md and TODO.md all said no browser exists
in this environment, so appearance had never been verified by anyone. Chrome
is on PATH. Its own --screenshot flag is what fails: it fires on the load
event, before this app's async IndexedDB read resolves, and captures a blank
page — which is presumably how the claim took hold.
scripts/screenshot.ts drives CDP instead: waits past the load event, seeds
IndexedDB via --eval-file and reboots the app with --reload, clicks with
--click, applies shadcn's class-based dark palette with --dark, and reports
console errors and uncaught exceptions. A page that renders blank from a
thrown error looks identical to an empty one, so the console output is half
the value.
Two defects found by simply looking:
- The month table's numeric columns had no horizontal padding, so figures ran
into each other: "+7,175.00 DKK4,200.00 DKK". Now padded.
- Dev logged "The script has an unsupported MIME type ('text/html')" on every
boot, because registerServiceWorker asks for sw.js and the "/*" catch-all
answered with the HTML shell. Dev now serves an inert worker.
Confirmed working, first time seen: the carry meter (including red where a post
is overspent), the Task 5 rule-history editor, the Task 6 "change from here"
control, and baked FX rates showing as "manual - 2026-09-01" in Settings.
Recorded in the docs, with the limits stated: this container's fontconfig maps
every generic family to a monospace face, so screenshots need a FONTCONFIG_FILE
override or you will chase a font bug that does not exist; Chrome starts from
an empty profile each run; and no screenshot can judge how a design feels.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
107 lines
5.4 KiB
Markdown
107 lines
5.4 KiB
Markdown
# 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`, 9 commits ahead of `main`,
|
|
not merged, not pushed. 288 tests passing, `bunx tsc --noEmit` clean,
|
|
`bun run build` succeeds. Versioned allocation rules are COMPLETE, all six
|
|
tasks. Neither new editing surface has been seen in a browser — see section 5.
|
|
|
|
---
|
|
|
|
## 1. ~~Time-versioned allocation rules~~ — DONE, all six tasks
|
|
|
|
**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/`
|
|
|
|
| Task | What | Commit |
|
|
|---|---|---|
|
|
| 1 | `Post.rules: RuleVersion[]` replaces `standingRule` | `68712e7` |
|
|
| 2 | v1 -> v2 migration | `15dcf93`, `1214d2b` |
|
|
| 3 | `setRuleFrom` / `removeRuleFrom` actions | `de128e3` |
|
|
| 4 | JSON import validation for the rule series | `1cb91d3` |
|
|
| 5 | Rule-history editor in Settings | `e3023d0` |
|
|
| 6 | "Change from here" control in the month view | `f94e458` |
|
|
|
|
Tasks 3-6 were executed by hand rather than dispatched. Every deviation from
|
|
the briefs is recorded in the ledger's task log with its reasoning; four of
|
|
them fixed real defects in the brief code (JSX that would not compile, a
|
|
component that pre-filled the previous post's rule, a number field that could
|
|
not be cleared, and missing validation that let a NaN allocation into the
|
|
fold). Worth a read before reviewing the diff.
|
|
|
|
Not yet done for this feature: nobody has independently reviewed tasks 3-6, and
|
|
no browser has seen the two new editing surfaces.
|
|
|
|
## 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.ts` fetches DKK/USD/EUR at build time and embeds them via `define`;
|
|
on any network failure it falls back to **committed constants** rather than
|
|
failing the build. Fetched rates get `source: "api"` with the build date;
|
|
the fallback constants get `source: "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 `MissingRateError` surfaces, instead of silently
|
|
converting money at a number the user never chose.
|
|
- Domain purity forces the shape: `createSeedDataset` takes the rates as an
|
|
**argument**; the env read lives in a new `src/store/bakedRates.ts`, in the
|
|
store layer, using the `try/catch` accessor 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
|
|
|
|
- **`confirmImport` has 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.
|
|
- **`round2` in `src/store/actions.ts` hardcodes 2 decimals** rather than
|
|
reading `CURRENCY_DIGITS`. Correct for DKK/USD/EUR; silently wrong the day a
|
|
non-2dp currency is added. Same latent issue in `sliceTotal`
|
|
(`src/domain/plans.ts`).
|
|
- **`EMPTY_FIGURES` (`src/domain/fold.ts`) is exported non-frozen** and returned
|
|
by shared reference from `figuresFor`. No consumer mutates it today;
|
|
`Object.freeze` is a one-line hardening.
|
|
- **`buildWorkbook` calls `monthView` per (post, month)**, making a full ODS
|
|
export O(posts x months^2). Fine at personal-budget scale.
|
|
- **The dev-only `src/manifest.webmanifest` placeholder hardcodes `scope: "/"`.**
|
|
Harmless in production, misleading if you dev-serve under a subpath.
|
|
|
|
## 5. Still needs a human
|
|
|
|
`scripts/screenshot.ts` drives headless Chrome, so the list here is much
|
|
shorter than it was. **Seen and confirmed working:** the carry meter (it
|
|
renders, and shows red where a post is overspent), the rule-history editor in
|
|
Settings, the "change from here" control, the baked FX rates arriving in a
|
|
fresh dataset, and every route at desktop and mobile widths.
|
|
|
|
Genuinely outstanding:
|
|
|
|
- **How it looks and feels.** A screenshot proves a layout is not broken. It
|
|
cannot tell you the design is good, and the container's fonts are not the
|
|
owner's fonts.
|
|
- **Offline behaviour**, the **install prompt**, and the **update prompt**. The
|
|
dev server now serves a deliberately inert `sw.js`, so dev exercises
|
|
registration but nothing else.
|
|
- the generated **`.ods` opening 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. Drivable over CDP in principle;
|
|
not yet done.
|
|
- **GitHub Actions** has never been executed.
|