## Review findings ### P0 - None. ### P1 - **Non-CHF duplicate candidates can be confirmed with a fabricated 1:1 CHF conversion.** `src/jarvis_finance/services/household_review_corrections.py:244-249` validates the category but not CHF currency or supported FX data. The write at `:450-470` then hard-codes `fx_rate_to_chf='1'` and copies the original amount into `amount_chf`. A synthetic EUR candidate was accepted and persisted as `EUR -100.00`, FX `1`, CHF `-100.00`. Reject unsupported currencies or use validated FX conversion before confirmation. - **Duplicate proof ignores transaction direction and permits an income/refund candidate to be excluded as a duplicate of an expense.** `src/jarvis_finance/services/household_review_corrections.py:152-166` compares absolute amounts and accepts several broad transaction types without requiring compatible signs/financial semantics. A `+25 CHF` candidate was successfully previewed as a duplicate of a `-25 CHF` expense. Require matching direction and compatible transaction semantics. - **Credit-card settlement completeness is declared current without proving card-statement/purchase coverage.** `src/jarvis_finance/services/household_review_corrections.py:186-231` derives `complete` solely from finding one amount/date counterpost; the 45-day purchase query has no statement-range or import-completeness proof. A payment/counterpost of CHF 100 with only CHF 50 of mapped purchases returned `completeness_status='complete'`, `data_status='current'`, and required no partial acknowledgement. Fail closed as partial unless statement coverage is established by durable import metadata. - **The reopen-duplicate contract is not reachable from the public read model after exclusion.** `src/jarvis_finance/services/household_import.py:2388-2394` and `:2570-2575` expose only `needs_review` candidates. Once excluded, the duplicate disappears, while reopening requires its new candidate version and baseline (`src/jarvis_finance/services/household_review_corrections.py:127-135,262-271`). The confirm response at `:646-657` does not return those updated fields, and transaction detail cannot address a closed candidate. Add a closed-duplicate history/detail surface that provides the current item token, version, baseline, and data version. ### P2 - None. ### Verification - Targeted tests: **8 passed**. - `git diff --check`: **passed**. - No files created or modified.