## Sprint 22 acceptance matrix | # | Condition | Status | Evidence / assessment | |---|---|---|---| | 1 | Read-only model; no schema migration or new performance engine | **PASS** | New `modelled_wealth_daily_v1` composes existing snapshots/readers. Schema remains 51; no migration files or write path added. | | 2 | Periods `since_anchor`, `1m`, `3m`, `1y`, `all` | **PASS** | Backend schema/router, TypeScript contract, UI selector, and focused tests cover all five; compatibility aliases remain accepted. | | 3 | Forward-only history; no later/current quote applied backward | **PASS** | `_event_at_or_before()` and crypto regression explicitly prove 25→26 carry and prevent the 27th’s valuation from entering the 26th. | | 4 | PostFinance official total vs depot + settlement cash, exactly once | **PASS** | Official anchor replaces same-day model event; subsequent model days require all depot and cash accounts and sum them once. Focused regression confirms CHF 1,000 → CHF 1,030, not double-counted. | | 5 | True Wealth official/modelled compatibility | **PASS** | Only allowlisted official sources and `truewealth_modelled_daily` are read; official value wins the day. Source/quality fail-closed tests present. | | 6 | Crypto canonical and legacy source compatibility | **PASS** | Reader imports canonical `daily_valuations.SOURCE_KEY` (`daily_crypto_valuation_v1`) and supports legacy `daily_crypto_current_valuation_v1`; same account/day resolves deterministically. No provider refresh is triggered. | | 7 | Four cash evidence modes | **PASS** | Focused tests exercise `reconciliation`, `manual_balance`, `csv_anchor_balance`, and calculated confirmed-ledger balance. Same-day precedence is `reconciliation > manual > CSV > calculated`. | | 8 | Account-specific confirmed movements; no duplicate ledger addition | **PASS** | Active budget projection takes precedence over canonical transactions; both are never summed. Regression with duplicate representations returns CHF 110, not CHF 120. | | 9 | No evidence remains unknown, not CHF 0 | **PASS** | Empty evidence returns `value_chf=None`, `quality=unavailable`; UI regression rejects a false CHF 0 display. | | 10 | Account-specific import metadata | **PASS** | Metadata is bound through canonical budget-account lineage or private source-reference hash; unattributable provider totals are not inherited by siblings. | | 11 | Raiffeisen `••••5632` / `••••5031` separation | **PASS** | Synthetic regression proves only the mapped account receives import rows. Production read-only evidence confirms `5632` has its own CHF 29,062.37 snapshot/metadata while `5031` remains unknown with no inherited balance or counters. | | 12 | Mixed dates/unknown account do not suppress known total or chart | **PASS** | Regression returns a usable incomplete total and visible chart with one unknown account. Production-copy payload likewise reports one unknown while retaining the known total. | | 13 | Immutable correction markers | **PASS** | Prior-day and same-day-before-official model cases produce `official − predecessor model`; stored model rows remain unchanged. | | 14 | GET is provider-free, write-free, deterministic, and model chart independent of TTWROR/XIRR | **PASS focused / runtime pending** | Endpoint regression blocks socket connections, validates the closed Pydantic response, compares `total_changes`, and verifies deterministic replay. Production-copy rehearsal additionally found an unchanged DB digest. Productive deployed GET evidence still awaits deployment. | ## Additional focused evidence - The formerly hidden daily-job scenario is now a real pytest test: - exactly **one collected test node** for `test_daily_job_uses_confirmed_chf_eur_usd_decimal_fx_and_unadjusted_close_idempotently`; - its file is now explicitly included in both relevant CI workflow gates. - Targeted backend gate reported by the parent: **74 passed**. - Production-copy read-only rehearsal: - known total: **CHF 627,381.98**; - unknown accounts/components: **1**; - database digest: **unchanged**; - runtime: approximately **60.159 seconds**. - Frontend full unit suite: **54 files / 244 tests passed**. - `git diff --check`: **passed**. - Candidate scope at final inspection: **15 tracked modified files plus 3 untracked candidate files**; no files were modified by this audit. ## Release blockers 1. **Full backend gate is not green.** Two attempts ended without a pytest summary or exit result: - first stopped around **54%**; - replacement stopped around **68%**. No failure traceback was emitted, so this is currently an incomplete/abnormally terminated gate—not yet a demonstrated product regression, but still release-blocking. 2. **Static/build gate evidence is incomplete.** Frontend tests are explicitly green, but typecheck/build exit evidence was not captured independently. Final Ruff, compileall, candidate/secret safety, and aggregate `make ... verify` results are also not yet available for the final tree. 3. **No real browser UAT evidence yet.** Vue unit tests and `min-h-11` 44px styling exist, but there is no real-browser 1440px/820px proof for: - console/page errors; - network/provider calls; - horizontal overflow; - rendered chart/markers; - collapsed diagnostics; - actual 44px controls; - DB digest before/after. This is a mandatory pre-release gate. 4. **Candidate is not immutable or published.** It remains a dirty working tree based on `572ef44…`; PR, hosted CI, merge SHA, deployment, productive GET sentinel, and productive daily-job idempotency/double-counting checks have not occurred. ## Non-blocking release follow-ups - The daily-job scenario is now executed both directly by pytest and again through the legacy scenario aggregator. This is redundant but not a correctness blocker. - After merge/deployment, rerun productive GET and daily-job replay with all-table sentinels and exact source/account totals. - Preserve private 0600 screenshots only long enough to extract aggregate UAT evidence, then remove them. - PR/CI/deployment and final release reporting remain operational follow-ups once the blocking local gates are green. **Verdict:** the focused Sprint 22 contracts and production-copy rehearsal are acceptance-ready, with no concrete P0/P1 code defect found in the inspected tree. The candidate is **not release-ready** until the full backend/static gates complete successfully and browser UAT plus PR/CI/deployment evidence exists.