- delete root test-functional.js (imported uninstalled 'playwright' —
could never run) and run-functional-test.js (legacy pre-Playwright)
- delete postcss.config.js + autoprefixer/postcss devDeps (tailwind v4's
vite plugin owns the pipeline; the config had no plugins left)
- client/lib/money.ts: drop unused SUPPORTED_CURRENCIES; keep
dollarsToCents exported + @public-tagged (API symmetry with
centsToDollars — the sanctioned unit crossing)
- client/lib/billDrafts.ts: drop unused BillDraft type export
- move the two runtime seed JSONs (advisory filters, merchant-store
matches; 7 MB) out of docs/ into db/data/ next to their loader;
fresh-DB seed verified (5000+5000 rows); Dockerfile COPY . covers it
- knip.json: apply config hints, ignore the two CSS-side tailwind deps;
npx knip exits 0 — added to CI as a BLOCKING step so unused
files/exports/deps fail instead of rotting (this is how the WebAuthn
ghost feature survived four QA cycles)
NOT deleted: client/public/img/doingmypart.jpg — flagged unused by the
code grep but actually referenced from HISTORY.md markdown that the
release-notes renderer serves (user catch). Lesson encoded in the QA
plan: asset-reference sweeps must include rendered markdown content.
Full ci green (252 server / 52 client / build / knip 0).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Currency/Date-format dropdowns were decorative (nothing read them). Wire
them into the formatters, display-only (single active currency, no conversion):
- money.ts: activeCurrency/activeLocale read synchronously from localStorage at
load (correct first paint), setMoneyFormat() write-through; formatUSD/
formatUSDWhole/formatCentsUSD honor them. Default USD/en-US is byte-identical,
so money.test + the probe stay green.
- utils.ts: fmtDate honors an activeDateFormat (MM/DD/YYYY | DD/MM/YYYY |
YYYY-MM-DD) with setDateFormat() write-through.
- FormatSync (mounted in Layout) reconciles the server settings → localStorage/
module and re-renders once only on a genuine cross-device divergence.
- Settings selects write through on change, currency list expanded (AUD/CHF/JPY/
INR), "Regional" section, tooltips clarifying display-only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Converted client/lib/money.js -> money.ts with branded types:
type Cents = number & { __unit: 'cents' }
type Dollars = number & { __unit: 'dollars' }
plus asCents/asDollars/centsToDollars/dollarsToCents. The formatters now require
the correct branded unit (a bare number won't do), so a typed caller physically
cannot format cents as dollars (the 100×-too-big bug) or vice-versa. Existing
.jsx callers are unaffected (checkJs off) — gradual adoption.
money.type-test.ts is a compile-time guard (never imported/bundled): its
@ts-expect-error lines assert each unit mixup is a real error, so typecheck
fails loudly if the branding ever regresses. Verified: removing a guard makes
tsc error 'Argument of type 1234 is not assignable to DollarsInput'.
typecheck + build (with React Compiler) + 48 client tests all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>