Handoff: Finances Phase D, surface rebuild passes (start 2026-07-06)¶
For: a fresh agent working WITH Justin, live on a dev slot.
Plan: finances-native-rebuild-2026-07-05, Tasks 20-32.
Module reference: reference_creatortrack_finance_module (read this first).
Boundary + design contract: creatortrack/docs/FINANCES-APP-SPEC.md (eslint enforces the import boundary).
State you inherit (do NOT redo)¶
Phases A-C shipped and pushed (origin/main a19e1dc, 2026-07-05 night). finance.*
Postgres is the source of truth; all ingest jobs are TypeScript (lib/finance-jobs/),
all writes are native routes, the Flask app + finance.db are retired (archived), the
timers are forge-creatortrack-finance-*. Prod is live and healthy: check
select job, ok, detail from finance.job_runs order by id desc limit 10.
The actual job: rebuild each surface WITH Justin, one pass = one commit¶
The 13 surfaces in app/finances/* are 1:1 ports of the old Flask app (its CSS,
Outfit font, dark Material markup). Justin explicitly does NOT want a polished port;
he wants each surface rebuilt in CreatorTrack's native design system with him
driving scope and look:
components/uiprimitives + workspace shell patterns (study how Habits/Tasks render in.ws-appsurface)- Geist / Geist Mono, CreatorTrack tokens; NO
finances.css, NO Outfit - Recharts is in the deps (Food Log trends use it) for charts
- Data layer stays:
lib/finance.tsloaders are ported and correct; restyle/rethink the presentation, reuse the queries (extend where Justin wants new views)
Order (Justin approves each on the dev slot before commit; commit feat(finances): <surface> iteration pass):
Dashboard, Net Worth, Investments, Spending, Budget, Business, Recurring, Cash Flow,
Accounts, Transactions, Categorize, Receipts, Alerts.
Task 32 (Alerts, last) also deletes app/finances/finances.css + the Outfit import.
Fold these into the relevant passes¶
- Receipts (Task 31): the old phone-upload capture surface died with Flask. Build native capture (upload ->
finance.receipts+ image store); the reconcile job (lib/finance-jobs/receipts.ts) already matches + attaches to ERPNext. Zero receipts exist, clean slate. - Transactions (Task 29): wire the edit/bulk-edit UI to
POST /api/finance/transactions(route exists, has no UI yet). - Budget (Task 24): wire targets/autoset to
POST /api/finance/budgets(route exists). - Net Worth / Accounts: manual value edits ->
POST /api/finance/manual-values(route exists). - Investments (Task 22): SSGA
as_ofsometimes lands empty (xlsx date-serial parse inlib/finance-jobs/holdings.tsconsSsga); fix while restyling. - Alerts (Task 32): render
finance.alert_feedat the top (table exists, feed is live).
Dev-slot workflow¶
- Bootstrap per reference_creatortrack_dev_testing: branch
feat/finances-surfaces(or per-surface), worktree atforge-suite-wt/<branch>, clone DBct_<branch>fromcreatortrack_dev_base(template already has the 3 finance migrations; seed user_rules if the pass needs them: scratch seed lives only in prod now, re-derive fromfinance.user_rulesin lifeos). - Worktree needs
ln -s /home/justinwieb/forge-suite/node_modules <wt>/node_modulesandnext dev --webpack/next build --webpack(Turbopack rejects the cross-root symlink). - NO new npm deps on the branch: the shared node_modules gets pruned by other agents' npm runs (fflate lesson). Merge ONCE at the end.
- tsx testing:
env -u PGPASSWORD PGDATABASE=ct_<branch> npx tsx <file>.mts;server-onlyimports need lazy import. Drizzle:in ${arr}, never= any(${arr}). - Icons: ALWAYS key by
iconKeyfromlib/finance-icons.ts, never raw merchant_norm.
Open reminders for Justin¶
- PNC Bank needs re-auth at bridge.simplefin.org (SimpleFIN warns every sync).
- Post-confidence cleanup (not urgent): delete legacy forge-finance-* unit files, retire the 8096 tunnel ingress entries, remove finance.db from the active tree.
[Claude Code, 2026-07-05 night]