Skip to content

Handoff: Finances Phase D surface passes, continuation (2026-07-06)

URL: https://mkdocs.justinsforge.com/memory/handoffs/finances-phase-d-continuation-2026-07-06/

For: the next agent continuing the finances native surface rebuild Plan (canonical task list): finances-phase-d-surface-passes-2026-07-06 Merged to main + deployed to prod: merge 3065fa7 (2026-07-06 ~14:05 CDT)

State

DONE (merged): Task 0 shell/single-door, Task 1 Dashboard, Task 2 Net Worth, Task 3 Investments, Task 9 Accounts (pulled forward, per-account profiles), plus emergent platform work: shared SidePeek, full-screen detail views, icon system overhaul, charts polish. Details in the plan's Progress block and the commit messages (c59e771..1362c1b on the merged branch).

REMAINING: Task 4 Spending, Task 5 Budget, Task 6 Business, Task 7 Recurring, Task 8 Cash Flow, Task 10 Transactions, Task 11 Categorize, Task 12 Receipts, Task 13 Alerts + delete finances.css, Task 14 register/document.

Workflow (unchanged, per plan)

One surface per pass on a dev slot; Justin approves live in chat before each commit; commit exactly feat(finances): <surface> iteration pass. Spawn a fresh slot with ~/forge/scripts/forge_creatortrack_agent_bootstrap.sh <branch> <port> (the old feat/finances-surfaces branch is merged; start a NEW branch, e.g. feat/finances-surfaces-2). Verify on http://100.97.43.104:<port>/justin/finances-5421?view=<surface> (the node face is the ONLY door; /finances/* are redirect shims). Dev auth: WORKSPACE_DEV_AUTH=1 bypass is already in slot .env.local.

Established patterns the remaining passes MUST follow

  • Styles: fs-* classes in components/finance/surfaces/native.css, design tokens only. finances.css shrinks; it dies in Task 13.
  • Charts: ONLY through components/Charts/Charts.tsx. It has: xLabelKey (pretty point labels), dragCompare (scrub), moneyAxis, mount-only animation, y-gridlines on by default. Never re-enable per-chart animation on resize.
  • Detail views: side peek by default + full-screen with &full=1, both rendering ONE shared body component (TxProfile, RecProfile, AccountProfile, SymProfile in components/finance/). New drill-downs (e.g. Spending category detail) should follow this. SidePeek reference: creatortrack-sidepeek. Peeks render OUTSIDE .fin-root: unscoped styles only.
  • FinanceApp.tsx owns peek routing: param priority tx > rec > sym > acct, qsWithout() for close hrefs, <param>Inline guards when view + full=1 render the detail in-surface instead.
  • Links: query-relative always (?view=...&...), scroll={false} for same-surface peek toggles; FinanceShell resets the inner scroll container when view/acct/full change.
  • Icons: chips are dark circles (--fs-chip-bg) with white 2.4-stroke glyphs; logos urlfill: cover-fit, library icons url: contain-fit; icon editing ONLY in peeks/profiles via IconPicker (hover pencil). Icon keys via iconKey(); ALWAYS _icon_key, never merchant_norm.
  • Gotchas: postgres.js returns bigint ids as strings; Number() every id before comparison or POST (bit us 3x). Yahoo lib (lib/finance-yahoo.ts) is fail-quiet enrichment with module caches; don't make surfaces depend on it.

Justin's standing UI preferences (learned this session, apply to new passes)

No gradients on heroes (flat cards). Horizontal y-gridlines on all charts. Month-prefixed tooltip labels ("Jun 8" not "8"). No hover-highlight on non-link heroes. Click-to-toggle on rows that own an open peek. Everything drills down (rows are links). No em dashes anywhere.

Environment notes

  • Dev slot from this session (feat/finances-surfaces on :3062) can be torn down: ~/forge/scripts/forge_creatortrack_agent_teardown.sh feat/finances-surfaces (branch is merged; safe).
  • Old Flask app was temporarily resurrected for comparison: forge-finances.service (user scope) serving :8096 at finances.justinsforge.com. Frozen finance.db; do NOT press Sync there. Stop it when Justin is done comparing: systemctl --user stop forge-finances.service.
  • SSGA as-of parse hardened in lib/finance-jobs/holdings.ts (parseSsgaAsOf, smoke-tested); nothing further needed for Task 3's fix.

[Claude Code, 2026-07-06]