## Verdict: **CHANGES REQUIRED** ### P0 - None found. ### P1 1. **CSV “preview” does not expose the imported data for review before confirmation.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:70,73-74,137-139` The API returns normalized `entries` and `expected_changes`, but the UI displays only a row count and immediately enables **Explizit bestätigen**. In a synthetic two-row CSV probe, neither filename, dates, directions, amounts, currencies, nor evidence references were visible. This does not satisfy a meaningful preview→confirm workflow. 2. **Editing manual rows does not invalidate an existing preview.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:61-68,74,134-140` Row fields use `v-model` without calling `resetTrueWealthPreview()`. Runtime probe: after previewing two rows, changing the first amount from `100` to `999` left the confirm button visible. The backend will reject this as stale, but the UI presents an apparently valid confirmation action that can only fail. 3. **The CSV picker has no visible keyboard focus.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:70` The focusable file input is `sr-only`, while its visible label has no `focus-within` treatment. Browser measurement showed focus on a clipped `1×1px` input with no rendered outline. Keyboard users cannot see where focus is before opening the file chooser. 4. **The setup card is not compact at the required widths.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:30-36,49-78` True Wealth is forced open on every render, including the full cashflow form. Measured setup-card heights were approximately: - 1440px width: **654px** - 820px width: **702px** - 390px width: **1102px** At 390px it exceeds the entire 844px viewport before metrics are reached. Keep the single card, but default to compact source summaries and explicitly expand the required workflow. 5. **Cashflow coverage statuses are collapsed into an inaccurate binary label.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:45` Every value other than `complete` renders as **Fehlt**. A legitimate `partial` status is therefore presented as wholly missing, violating the requirement to communicate source status accurately. ### P2 - **Multi-row controls are difficult to distinguish with assistive technology.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:61-68` Repeated rows have identical labels and identical **Entfernen** accessible names, with no fieldset/legend or row number. Announce “Cashflow 1”, “Cashflow 2”, and uniquely name removal actions. - **Several interactive targets are undersized.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:62-72,77` Runtime measurements at 390px found manual row controls/buttons at **40px** high, the checkbox at approximately **13×16px**, and technical-diagnostics summaries at **16px** high. These miss the project’s 44px touch-target baseline. - **The entire interactive setup is an assertive semantic status surface.** `frontend/src/components/performance/PortfolioPerformancePanel.vue:30,73` The outer `role="status"` contains all disclosures and form controls, with a nested message `role="status"`. Since the card appears asynchronously, screen readers may announce the whole form. Use a normal section and reserve a dedicated live region for concise request results. - **Tests do not cover the acceptance-critical UX failures above.** `frontend/src/components/performance/PortfolioPerformancePanel.test.ts:35-62` Current tests verify only preview call/count and absence of automatic confirmation; they do not assert normalized CSV rows, filename/selection feedback, stale-preview invalidation, manual-row accessibility, target sizes, or required responsive widths. ### Positively verified - Exactly one setup card. - Runtime source order is True Wealth → Crypto → PostFinance. - Source status and next-action text are present. - Technical diagnostics start collapsed. - Manual multi-row addition works. - Initial render made no confirmation POST or provider request. - Preview made only the preview POST; confirmation was not automatic. - No horizontal overflow at 1440, 820, or 390px. ### Verification run - Full frontend suite: **52 files / 223 tests passed** - Sprint 20C backend unit tests: **9 passed** - Typecheck: passed - Production build: passed - `git diff --check`: passed - Browser probes: Chromium with synthetic API data at 1440, 820, and 390px - Repository files modified by review: **none**