## Review-Ergebnis: **BLOCK** ### P0 - Keine P0-Funde. ### P1 1. **Partial-/Failed-Zähler vermischen unterschiedliche Läufe und können die UI fachlich falsch darstellen.** - `valued_assets` stammt aus dem letzten erfolgreichen Lauf, `missing_assets` dagegen aus dem neuesten Lauf: `src/jarvis_finance/services/performance_activation.py:115-116`. - Bei einem unvollständigen Lauf wird `price_stored` immer als `0` persistiert, selbst wenn ein Teil der Assets erfolgreich bepreist wurde: `src/jarvis_finance/services/crypto_market_recovery.py:343-365`. - Die UI bezeichnet den Zustand dennoch als „Teilweise erfolgreich“ und zeigt diese inkonsistenten Zähler als „bewertet/fehlend“: `frontend/src/components/performance/PortfolioPerformancePanel.vue:37-45,174-176`. - Folge: Ein erster Lauf mit beispielsweise 1 von 2 gültigen Preisen erscheint als „Teilweise erfolgreich · 0 bewertet · 2 fehlend“. Nach einem früheren Erfolg können sogar alte bewertete Assets mit aktuellen Fehlern kombiniert werden. 2. **Das neue API-Statusmodell meldet bestehende Daily Sources unabhängig von Timer und Laufergebnis immer als pausiert.** - `daily_market_fx_v4` und der historische Crypto-Pfad erhalten hartkodiert `source_enabled=False`: `src/jarvis_finance/services/performance_activation.py:40-43`. - `active`, `partial` oder `failed` sind nur erreichbar, wenn sowohl globales Gate als auch `source_enabled` wahr sind: `src/jarvis_finance/services/performance_activation.py:60-75`. - Damit kann selbst ein aktivierter, vollständig oder fehlgeschlagen gelaufener PostFinance-Marktjob API-seitig nur `paused` sein. Das verletzt die eingeführte API-Semantik für `active|paused|partial|failed`: `src/jarvis_finance/api/schemas/performance_activation.py:101-119`. ### P2 - **Fehlender Status wird im Performance-Panel lautlos ausgeblendet.** Jeder API-/Schemafehler setzt lediglich `dailyJob=null`; es gibt keinen sichtbaren „Status nicht verfügbar“-Zustand: `frontend/src/components/performance/PortfolioPerformancePanel.vue:216`. - **Testabdeckung ist zu schmal:** Der neue UI-Test deckt nur `paused` ab: `frontend/src/components/performance/PortfolioPerformancePanel.test.ts:49-57`. Es fehlen aktive, partielle und fehlgeschlagene Läufe, gemischte Last-success/Last-attempt-Daten, konkrete Europe/Zurich-Ausgabe, API-Response-Validierung und responsive Browser-Smokes. - Leere Zeitwerte werden unabhängig vom Feld als „Nicht geplant“ formatiert; für „Letzter Erfolg“ und „Ältester verwendeter Preis“ ist das irreführend: `frontend/src/components/performance/PortfolioPerformancePanel.vue:42-45,196`. ### Positiv bestätigt - Dashboard-Render ruft keinen Marktprovider auf: Frontend lädt nur `GET /api/portfolio/performance/daily-job`; die Route delegiert ausschließlich an die gespeicherte DB-Projektion: `frontend/src/api/portfolio.ts:177`, `src/jarvis_finance/api/routers/overview.py:232-235`. - Swiss-Timezone ist explizit auf `Europe/Zurich` gesetzt: `frontend/src/components/performance/PortfolioPerformancePanel.vue:196`. - Neues Status-Panel ist grundsätzlich responsiv aufgebaut (`flex-wrap`, gestaffelte Grid-Breakpoints): `frontend/src/components/performance/PortfolioPerformancePanel.vue:33-46`. - Keine rohe JSON-Darstellung im neuen Status-Panel. ### Verifikation - Backend Sprint-20E: **10 Tests bestanden** - Frontend-Zieltests: **21 Tests bestanden** - Frontend Production Build: **bestanden** - Ruff für geänderte Python-Dateien: **bestanden** - `git diff --check`: **bestanden** - Vollständiges `make verify` war in der verfügbaren Umgebung nicht ausführbar: Makefile ruft ein nicht vorhandenes direktes `pytest` auf; der alternative Lauf scheiterte während Collection an fehlenden API-Testextras (`httpx2`), nicht an einer Test-Assertion. **Dateien geändert:** Keine Source-/Track-Dateien; Review war read-only. Lokale ignorierte Build-/venv-Artefakte wurden durch die Verifikation erzeugt.