PlanViewer's DisplayValuation.action JSON already gives us current
fund units + unit price; we were parsing it and throwing it away,
emitting only a single 'unrealised-gains-offset' DEPOSIT to make
Wealthfolio's totals match the dashboard. That hack double-counted
the gain as a cash contribution, hiding £35k of pension growth from
every contribution/growth/ROI panel.
New flow:
- FidelityPlanViewerProvider exposes last_holdings + last_total_contribution
after fetch() drains.
- fidelity-ingest CLI converts to a ManualSnapshotPayload (cost basis
allocated proportionally by current fund value share) and posts to
WF /api/v1/snapshots/import. WF auto-creates unknown fund symbols
with kind=INVESTMENT, quoteMode=MANUAL, quoteCcy=GBP.
- The gains-offset emission is removed entirely. Historical offset
rows already in WF are corrected at the dashboard layer by the
dav_corrected view shipped in infra@2841347e.
WealthfolioSink gains push_manual_snapshots() + ManualSnapshotPayload /
SnapshotPosition wire types. 11 sink tests (3 new) + 9 fidelity
provider tests (2 changed, 1 new) all green; mypy + ruff clean.