## Review outcome **P0:** None. ### P1 findings 1. **Incomplete portfolio coverage still displays authoritative performance values and graph.** - Backend intentionally marks portfolio TTWROR/XIRR/attribution unavailable when any required source is missing: `src/jarvis_finance/services/portfolio_performance.py:214-225`. - Frontend ignores that coverage state for portfolio scope and renders `investment_result`, XIRR, TTWROR, and the “Belegter Performanceverlauf” directly from the performance response: `frontend/src/components/performance/PortfolioPerformancePanel.vue:50-63,93`. - Result: the page can simultaneously say setup is incomplete and present returns as proven. Metrics and graph should be gated by the selected coverage/quality state. 2. **Two of the three setup links are not direct links to their stated tasks.** - Links use `/portfolio/data?source=postfinance...` and `?source=truewealth...`: `PortfolioPerformancePanel.vue:87-89`. - `DataIngestionReconciliationPanel` never reads the route query and always initializes `sourceKey` to `postfinance_etrading`: `DataIngestionReconciliationPanel.vue:96,106,155,162`. - True Wealth is not even a supported `PortfolioIngestionSource`: `frontend/src/api/portfolio.ts:117`. - Consequently both links open the same default PostFinance importer; the True-Wealth task has no direct destination. `/crypto` is likewise only a generic page link, not a task-specific target. 3. **The “Umfang” selector does not actually load source-specific performance.** - Changing scope only alters local display branches; `load()` never sends an account/scope identifier: `PortfolioPerformancePanel.vue:77,97`. - For PostFinance/True Wealth/Krypto, the five metric cards continue showing whole-wealth totals, “Anlageergebnis” becomes unavailable, percentages become status words, and the graph is hidden: `PortfolioPerformancePanel.vue:48-63,93`. - This makes the selector misleading rather than a truthful source progression/view control. ### P2 findings 1. **The graph is minimally drawable but weak as a performance graph.** `PortfolioPerformancePanel.vue:55-62` provides no axes, dates, values, tooltip, or endpoint labels, so users cannot determine magnitude or timing from it. The accessible label also names the series but conveys no values. 2. **Acceptance coverage is incomplete.** Existing tests do not render at the required 1440/820/390 viewports, and the test named “without provider calls” only verifies local API wrapper arguments—it does not assert browser/backend outbound-network behavior. ## Verified - Focused frontend tests: **8/8 passed** - `npm run typecheck`: **passed** - `npm run build`: **passed** - `git diff --check`: **passed** - Code inspection confirms render invokes only local API endpoints; no direct frontend market-provider request was introduced. **Files modified:** No source or tracked files. Build regenerated ignored `frontend/dist` artifacts.