diff --git a/TODO.md b/TODO.md index 9329bde..b6b8a25 100644 --- a/TODO.md +++ b/TODO.md @@ -198,6 +198,70 @@ Cache store reads entire files into memory (`readFileAlloc` with 50MB limit). For portfolios with 10+ years of daily candles, this could use significant memory. Keep current approach unless memory becomes a real problem. +## Audit: manual-check accounts mechanism (NYL, Kelly's ESPP, etc.) + +Some accounts/positions can't be reconciled from broker CSVs and need a +human-in-the-loop reminder at the audit step. Examples: + +- **NY Life** — no CSV export at all. Values only live in periodic + statements. +- **Kelly's ESPP** — accrued payroll-deduction cash doesn't appear in the + Fidelity positions CSV until the purchase date hits (typically every + 6 months). Between purchases the cash is a real contribution that + `zfin audit` can't see. +- Future: treat as an open category. + +The existing `update_cadence::weekly|monthly|quarterly|none` field already +sort-of covers this, but has two gaps: + +1. It fires off the last *git-detected change*, not the last *human + review*. For NYL, the value sometimes hasn't changed in months — so + git never fires, cadence never trips. +2. ESPP needs weekly-ish attention while accumulating cash between + purchases, but the accrued balance is invisible to the CSV audit. + +### Options + +A. **New `update_cadence::manual` variant** — always fires every audit + run until silenced. Blunt but zero design work. + +B. **`last_refreshed::YYYY-MM-DD` field on `accounts.srf`** — explicit + human-review timestamp, decoupled from git-detected changes. Audit + compares `today - last_refreshed` against the cadence. User bumps + the field when they check the statement. Probably the most + correct fit for NYL. + +C. **Sticky TODO list** — a `todos.srf` or `todo::` field on accounts + that audit always surfaces until cleared. General-purpose; also + covers "remember to rebalance on 5/15". + +### ESPP-specific follow-through + +ESPP is also a contribution-attribution blind spot. If Kelly's paystub +deducts $X/week but the cash lot doesn't reach `portfolio.srf` until +the purchase date, the attribution math is under-counting contributions +and over-counting the purchase-week gain. Possible fixes are discussed +in the "Contributions diff" TODO below — option C there (per-account +`cash_is_contribution`) would make manually-entered ESPP +cash additions count correctly. + +## Audit: tax-loss account persistent discrepancy (~-$897.59) + +The tax-loss account consistently shows a small discrepancy (around +-$897.59 at time of writing) that requires manual tweaking in the +ratio-updates section — either adjusting shares or `price_ratio` each +week. The account is a weird one and requires careful hand-updating; +not something the runbook can safely automate. + +Consider introducing an **"expected discrepancy tolerance"** field per +account so audit only flags deltas exceeding the known drift. Would +keep the audit output signal-to-noise high for this and any other +accounts with known-unfixable drift. + +Careful: a tolerance should never silently swallow real discrepancies. +Probably render as muted (still visible, just not warning-colored) +until the delta exceeds the tolerance, rather than filtering entirely. + ## Torn SRF files from server sync (recurring bug) **Status:** First-layer fix done — 2026-05-02. `syncFromServer` @@ -214,4 +278,3 @@ will try the provider fallback. - Read-path self-heal: on SRF parse failure during read, invalidate the cache entry so a subsequent refresh can repair without user intervention. -