CLAUDE.md gains the traps a new session would otherwise re-discover: - Rules: a zero-condition rule matches everything (rule 43 would split all ~3,700 transactions); preview-then-apply-by-id is the safe pattern and why it beats auto-applying on ingestion; how run provenance works. - Shared expenses: transaction_splits.settled is dead data; getParticipantBalances is correct and must not be 'fixed'; settlement cannot be attributed per trip. - The shared loan: separate ledger, fixed 50% with a tracked receivable, why the share must not be derived from actual payments, and why interest stays as spend. - Extraction: balance assertions are the check that works, do not derive opening_balance or add a totals assertion (both would be tautological), Gemini invents summary fields it was not given, empty statements must not throw, FX is per-date, and CSV comparisons need millisecond ordering. The design doc records Phase 0 as done - including that the original Phase 0 plan was wrong, since reading the code first is what prevented breaking a working balance page. Known Gaps lists what is open: the unbuilt phases, 11 failing assertions, the uncategorised Up rows, and the CSVs sitting in 030490e's history.
This commit is contained in:
@@ -144,16 +144,59 @@ payment did. A percentage-of-actual model would silently redefine her share as
|
||||
|
||||
## Migration path
|
||||
|
||||
1. **Fix the trip settlement bug first** — make `getTripAnalytics` and
|
||||
`getParticipantBalances` agree. Low risk: all splits are currently unsettled,
|
||||
so honouring the flag changes nothing today.
|
||||
2. Add contexts; put every existing split in "Household"; every payment likewise.
|
||||
3. Backfill `linked_transaction_id` for the four exact matches; flag the other
|
||||
four for manual linking.
|
||||
4. Create the "Pre-2026" closed context. Apply household split rules to
|
||||
pre-cutoff transactions into it — fixes ~$97,627 of the trailing 12 months
|
||||
currently shown as 100% yours.
|
||||
5. Loan contributions and equity — last, and only after the questions below.
|
||||
### Phase 0 — DONE (2026-07-26, commit `3f04cbd`)
|
||||
|
||||
Stop the trip view reporting a settlement breakdown it cannot compute.
|
||||
|
||||
The original plan was "make `getTripAnalytics` and `getParticipantBalances`
|
||||
agree". **That plan was wrong** and reading the code before building is what
|
||||
caught it:
|
||||
|
||||
- `getParticipantBalances` is *not* buggy. It computes `splits − payments`,
|
||||
which is coherent. Excluding settled splits there while still subtracting the
|
||||
payments that settled them would have double-counted and broken a working page.
|
||||
- The real defect was narrower: the trip view showed Settled/Unsettled from
|
||||
`transaction_splits.settled`, which nothing sets. A correct per-trip figure is
|
||||
not computable at all, because `split_payments` has no trip attribution.
|
||||
|
||||
So the fix was **subtractive**: the trip view now shows each participant's share
|
||||
and points at Shared for what is actually owed.
|
||||
|
||||
Also removed `/api/splits/settle` — unreachable from the UI but live on its URL,
|
||||
where one call with `participant_id` would mark every one of that person's splits
|
||||
settled, writing a flag nothing reads.
|
||||
|
||||
`transaction_splits.settled` / `settled_at` still exist and are now pure dead
|
||||
data. Phase 1 either repurposes them ("is my context closed?") or drops them.
|
||||
|
||||
### Phase 1 — settlement contexts
|
||||
|
||||
Add contexts; put every existing split in "Household"; every payment likewise.
|
||||
Balance queries group by context. Touches `queries.ts` (both balance CTEs),
|
||||
`shared/page.tsx`, `trips/[id]/page.tsx`, `split-payments/route.ts`. ~1 day.
|
||||
|
||||
### Phase 2 — link payments to transactions
|
||||
|
||||
Backfill `linked_transaction_id` for the four exact matches; flag the other four
|
||||
for manual linking. On ingestion, propose a matching credit as a settlement
|
||||
rather than silently categorising it `transfers`. ~half a day.
|
||||
|
||||
### Phase 3 — retroactive pre-2026 split
|
||||
|
||||
Create the "Pre-2026" closed context. Apply household split rules into it via the
|
||||
rule preview (`/api/rules/[id]/matches`, built 2026-07-26) — fixes ~$97,627 of
|
||||
the trailing 12 months currently shown as 100% yours. Then delete the `splitFrom`
|
||||
cutoff entirely.
|
||||
|
||||
**Validate the ratio first.** This assumes today's 50/50 held through 2025. The
|
||||
SplitMyExpenses CSVs should be used to *check* that assumption — not to
|
||||
reconcile, since transactions were sometimes combined and exact matching is
|
||||
impossible.
|
||||
|
||||
### Phase 4 — loan ledger
|
||||
|
||||
Contribution schedule, contributions recognised from `emi` credits, running
|
||||
receivable. Independent of contexts — the loan is a separate ledger. ~1–2 days.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user