Skip to content

Commit 0845d2b

Browse files
feat(money-mirror): issue-010 dashboard scope, transactions, coaching facts (#17)
- Transactions panel, filters, merchant rollups, scope APIs - Coaching facts expanded, Gemini narrative, schema/index updates - Split dashboard.ts and useDashboardState for 300-line policy - Pipeline artifacts, agent updates, and project-state for issue-010 Verified: npm run lint, test, build; smoke GET / and /login on next start. Made-with: Cursor
1 parent f847b64 commit 0845d2b

80 files changed

Lines changed: 6090 additions & 691 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
# Changelog
22

3+
## 2026-04-05 — MoneyMirror Phase 3 T4 (VIJ-41): facts-grounded AI coaching
4+
5+
**App:** `apps/money-mirror`
6+
7+
**What:** Layer A facts (`src/lib/coaching-facts.ts`, Zod + `buildLayerAFacts`), Gemini 2.5 Flash structured narratives with `cited_fact_ids` validation (`src/lib/gemini-coaching-narrative.ts`), `attachCoachingLayer` (`src/lib/coaching-enrich.ts`) wired into `GET /api/dashboard` and `GET /api/dashboard/advisories`, `POST /api/dashboard/coaching-facts-expanded` for `coaching_facts_expanded` telemetry, `FactsDrawer` + updated `AdvisoryFeed`, `dashboard.signals` for food/subscription heuristics, dependency `zod`. README, `docs/COACHING-TONE.md`, `CODEBASE-CONTEXT.md`, `manifest-010.json` PostHog list updated.
8+
9+
---
10+
11+
## 2026-04-05 — MoneyMirror Phase 3 T2 (VIJ-39): unified dashboard scope
12+
13+
**App:** `apps/money-mirror`
14+
15+
**What:** Implemented the unified scope model from `experiments/plans/plan-010.md` Phase B: shared `src/lib/scope.ts`, extended `GET /api/dashboard` and `fetchDashboardData` (legacy single statement vs `date_from`/`date_to`/`statement_ids`), `statement_ids` filter on `GET /api/transactions`, `ScopeBar` UI with `POST /api/dashboard/scope-changed` for PostHog `scope_changed`, and aligned `TransactionsPanel` with the same scope. Mirror “perceived” uses `profiles.perceived_spend_paisa` (single baseline). README and `project-state.md` updated.
16+
17+
---
18+
19+
## 2026-04-05 — Issue Created: issue-010
20+
21+
- **Type**: Enhancement
22+
- **Title**: MoneyMirror Phase 3 — Unified multi-source dashboard, transaction-native insights, and expert AI coaching
23+
- **App**: apps/money-mirror
24+
- **Status**: Discovery
25+
26+
---
27+
328
## 2026-04-05 — Docs: MoneyMirror added to root README + app README updated for Phase 2
429

530
**What:** Closed remaining documentation gaps after Phase 2 ship and VIJ-24 closure.

agents/backend-architect-agent.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,26 @@ Before finalizing the architecture, answer all of the following. Any gap must be
248248
→ Server must return HTTP 4xx on invalid enum input — not silently sanitize to null or a default. Silent sanitization gives users false confidence their input was saved.
249249
→ Schema must include a CHECK constraint for the column.
250250
→ Specify all three in the architecture spec: (1) client control type, (2) server validation response code, (3) schema CHECK constraint.
251+
251252
# Added: 2026-04-04 — MoneyMirror Phase 2
252253

254+
15. **Financial headline metrics (aggregates vs lists)**: For any finance dashboard, advisory pipeline, or AI facts layer:
255+
→ The plan must state that totals, category sums, and inputs to rules/AI are computed from **database aggregates** over the full user scope (`SUM` / `COUNT` with the same filters as scope), **not** from `LIMIT`-capped row scans.
256+
→ List/pagination queries for UI tables are separate from aggregate queries for headline numbers — never reuse the list query result as the source of summed totals.
257+
258+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
259+
260+
16. **Batch repair / backfill termination**: For any maintenance route that fixes nullable derived fields in batches (cursor + loop):
261+
→ Document **termination proof**: cursor advances monotonically; rows that cannot be processed in one pass (e.g., normalization returns null permanently) are skipped or marked so they are not re-selected forever.
262+
→ "Process until no rows" without poison-row handling is a blocking omission.
263+
264+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
265+
266+
17. **Heavy authenticated read APIs**: For any authenticated endpoint that scans large row sets, runs expensive `GROUP BY`, or could be abused by rapid UI actions:
267+
→ State an explicit strategy: pagination/cursor guarantees, per-user rate limits, query caps, or an explicit **MVP / trusted-client** assumption with documented risk acceptance.
268+
→ Auth + ownership alone are not sufficient when the query is O(n) in user data.
269+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
270+
253271
# Added: 2026-03-19 — SMB Feature Bundling Engine
254272

255273
# Updated: 2026-03-21 — Ozi Reorder Experiment (items 4–7)
@@ -260,6 +278,8 @@ Before finalizing the architecture, answer all of the following. Any gap must be
260278

261279
# Updated: 2026-04-04 — MoneyMirror Phase 2 (items 13–14)
262280

281+
# Updated: 2026-04-05 — MoneyMirror Phase 3 (items 15–17)
282+
263283
---
264284

265285
## Anti-Sycophancy Mandate

agents/backend-engineer-agent.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,17 @@ Experiment Integrity & Telemetry: Ensure cryptographic salts for A/B testing are
163163

164164
# Added: 2026-04-03 — MoneyMirror (issue-009)
165165

166+
**Monetary totals vs list queries**: Never use `LIMIT` on the query whose rows are aggregated into headline totals, category sums, advisory inputs, or AI fact inputs. Paged list endpoints may use `LIMIT`; totals must use a separate aggregate query (SQL `SUM`/`COUNT`) over the full scope.
167+
168+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
169+
166170
**Infrastructure Provisioning is a hard deliverable** — not a README suggestion. Before execute-plan can be marked DONE, the Backend Engineer must confirm all of the following are complete:
167171

168172
1. **Database project exists** — Neon/Supabase project created and `DATABASE_URL` is a real connection string in `.env.local` (not a placeholder).
169173
2. **Schema applied**`schema.sql` has been run against the live DB. Verify by querying `information_schema.tables` — every expected table must exist.
170174
3. **Auth provider provisioned** — If the app uses Neon Auth, `NEON_AUTH_BASE_URL` must be obtained from the Neon console Auth section and filled in `.env.local`. OTP login must work locally before execute-plan closes.
171175
4. **All non-optional env vars filled** — Every variable in `.env.local.example` that is not explicitly marked `# Optional` must have a real value in `.env.local`. Empty strings (`VAR=`) are a blocking violation.
172-
5. **Sentry project created**Create a Sentry project (free tier), run `npx @sentry/wizard@latest -i nextjs`, and fill `NEXT_PUBLIC_SENTRY_DSN`, `SENTRY_AUTH_TOKEN`, `SENTRY_ORG`, `SENTRY_PROJECT` in `.env.local`. This is a backend setup task, not a deploy-check task.
176+
5. **Sentry project created**Unless `project-state.md` Decisions Log documents monitoring keys as optional/out of scope for the current gate: create a Sentry project (free tier), run `npx @sentry/wizard@latest -i nextjs`, and fill `NEXT_PUBLIC_SENTRY_DSN`, `SENTRY_AUTH_TOKEN`, `SENTRY_ORG`, `SENTRY_PROJECT` in `.env.local`. When the PM has explicitly deferred Sentry, do not treat empty DSN/org/project as an execute-plan blocker.
173177
6. **`npm run dev` boots clean** — The app starts without errors and the core user flow works end-to-end. Auth, DB reads/writes, and the primary feature must all function before the task is closed.
174178

175179
Infra gaps discovered at `/deploy-check` are Backend Engineer failures. Ship infra, not just code.

agents/code-review-agent.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,23 @@ For every API route that writes a parent record followed by child records:
134134

135135
# Added: 2026-04-03 — MoneyMirror (issue-009)
136136

137+
**Financial copy vs active scope** (required when reviewing money-related UI, advisories, or analytics strings):
138+
139+
- Verify phrases like `/mo`, `per year`, `this month`, and any ×12 annualization match the **active date scope** (single calendar month vs multi-month vs arbitrary range).
140+
- Flag **HIGH** if copy implies a monthly frame when the scope is not a single month, unless the string explicitly derives from a monthly estimate stated in the spec.
141+
142+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
143+
144+
**Competing async loads on scope/filter change** (required for `"use client"` data loads):
145+
146+
- For any `fetch` driven by scope, date range, or filter changes that can fire in quick succession, verify `AbortController` (or equivalent stale-response guard) so an older response cannot overwrite newer UI state. Ignore `AbortError` in handlers.
147+
148+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
149+
150+
**Repair / backfill loops**: For any `while` or `for` loop that batches DB updates until "done," verify rows that cannot be processed are skipped or marked so the loop cannot run until timeout on the same poison rows.
151+
152+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
153+
137154
---
138155

139156
## 5 Performance Risks

agents/deploy-agent.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ error logging
9191
request logging
9292
performance metrics
9393

94+
**Optional monitoring keys**: When verifying Sentry (or similar), check `project-state.md` Decisions Log and the active deploy-check artifact for a **documented PM exception** that exempts specific env vars from the blocking gate. If exempted keys are listed, empty values for those keys must not alone justify a Block Deployment verdict.
95+
96+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
97+
9498
---
9599

96100
## 5 Rollback Plan

agents/design-agent.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,7 @@ Minimize number of screens.
140140
Avoid unnecessary UI complexity.
141141

142142
Focus on fast user success.
143+
144+
**Date range and labels**: When wireframes or component copy include money or time rates (`/mo`, `per year`, `this month`), specify whether the screen assumes a **single month** or a **variable range**. For variable ranges, prefer neutral period language in mocks so engineering does not inherit a misleading monthly frame.
145+
146+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)

agents/frontend-engineer-agent.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,11 @@ Optimize for fast MVP development.
155155
Browser Storage & Network Safety: Always wrap `JSON.parse` of `localStorage`/`sessionStorage` in a try/catch block. Always use an `AbortController` for asynchronous `fetch` calls triggered by user input (e.g., search) to prevent network race conditions. Clean up AbortController on component unmount or before issuing a new request to prevent memory leaks.
156156

157157
# Added: 2026-03-28 — Nykaa Personalisation (issue-008)
158+
159+
**URL as canonical scope**: When filters, date range, or statement scope are encoded in the URL (search params), any modal, drawer, or inline editor that edits that scope must **re-initialize local form state from parsed search params** whenever the canonical scope in the URL changes. Never let modal defaults diverge from the active URL.
160+
161+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
162+
163+
**Dashboard and scope loads**: Treat main data loads triggered by scope changes like search — use `AbortController`, abort the prior request when issuing a new one, and ignore `AbortError` so stale responses cannot overwrite the UI.
164+
165+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)

agents/peer-review-agent.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ large user growth
6767
heavy AI processing
6868
database bottlenecks
6969

70+
**Heavy authenticated reads**: For APIs that scan large per-user tables or run expensive aggregations (`GROUP BY`, unbounded filters), verify the architecture documents a strategy per **backend-architect-agent** Mandatory Pre-Approval Checklist item 17 (pagination, rate limits, caps, or explicit MVP trusted-client assumption). If none is stated, file a scalability finding — non-blocking only if the review explicitly accepts MVP risk with documented rationale.
71+
72+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)
73+
7074
---
7175

7276
## 3 Edge Case Analysis
@@ -210,14 +214,15 @@ Each stance must produce at least one finding. If a stance produces no findings,
210214
**Step 4 — Prompt Autopsy Check**
211215

212216
For each agent prompt gap identified:
217+
213218
- Name the exact agent file (e.g., agents/backend-architect-agent.md)
214219
- Name the exact section to modify (e.g., ## 6 Technical Risks)
215220
- Write the exact text to add — not a direction, but the actual sentence or rule
216221

217222
Format as:
218-
File: agents/[agent-name]-agent.md
219-
Section: [section name]
220-
Add: "[exact text]"
223+
File: agents/[agent-name]-agent.md
224+
Section: [section name]
225+
Add: "[exact text]"
221226

222227
This output is consumed directly by /learning to update agent files.
223228
Vague directions ("add a timeout rule") are not acceptable outputs.

agents/product-agent.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,7 @@ Avoid over engineering.
165165
Prefer experiments over full product builds.
166166

167167
Always clarify assumptions.
168+
169+
**Scope-aware copy**: If the MVP supports user-configurable or multi-month date ranges, default analytics and coaching copy must use **period-neutral** labels (`this period`, `in your selected range`) unless the screen is explicitly scoped to a single calendar month. Do not standardize on `/mo`, `this month`, or ×12 annualization in template strings without a **Scope → Copy** rule that states which phrases apply to which scope shapes.
170+
171+
# Added: 2026-04-05 — MoneyMirror Phase 3 (issue-010)

0 commit comments

Comments
 (0)