## Review result **P0: 0** ### P1: 7 1. **Canonical rows can be marked original-verified without an original/content-review gate.** `scripts/health/health_dashboard_action_worker.py:1754-1785` Transfer requires candidate state/revisions but never requires `original_reviewed_at`, reviewed pages, or `content_status='reviewed'`. It then writes `validierungsstatus='validiert'` and `verified_against_original=1`. **Counterexample:** synthetic execution transferred OCR CRP while document state was `(original_reviewed_at=None, content_status='partial')`; resulting canonical row was `('<4.2', ..., 'validiert', 1)`. This is operator-triggered but falsely asserts verification against the original. 2. **Document date is promoted into both specimen and report dates.** `scripts/health/dashboard_v5/document_reconciliation.py:184-195` `scripts/health/health_dashboard_action_worker.py:1781-1783` Reconciliation uses `d.document_date` as the laboratory observation day; transfer writes that same day to both `abnahme_datum` and `befund_datum`. **Counterexample:** a report dated June 10 with no documented collection date becomes “sampled June 10” and “reported June 10,” inventing two provenance facts. 3. **The advertised preview hash is accepted but never enforced.** `scripts/health/health_dashboard_action_worker.py:449-458` `scripts/health/health_dashboard_action_worker.py:1832-1840` Only `expected_candidate_revision` is checked; `preview_revision` is format-validated but never recomputed or compared. **Counterexample:** after the displayed preview, changing `normalized_date`, `reference_text`, and `comparison_digest` without changing `candidate_revision` was accepted; the stage used the changed date/reference rather than the operator-reviewed preview. 4. **Reference-range parsing can corrupt canonical bounds and ignores unit consistency.** `scripts/health/health_dashboard_action_worker.py:1735-1741` `scripts/health/health_dashboard_action_worker.py:1781-1783` **Counterexamples:** `0-5 mg/L` is parsed as lower `0`, upper `-5`; `>5` loses the lower bound; a candidate in `mg/L` with reference text `0–5 mg/dL` is accepted without detecting the unit conflict. The raw reference text is not retained in the canonical row. 5. **Qualitative laboratory results are modeled but cannot complete the confirmation path.** `scripts/health/dashboard_v5/lab_review.py:123-150` `scripts/health/assets/health-assets/dashboard-v5-record.js:633-637` `scripts/health/health_dashboard_action_worker.py:1765-1769` Qualitative results without units are classified incomplete; even with a unit, the UI enables preview only for `kind==='numeric'`, and transfer requires a numeric substring. **Counterexample:** a documented `ANA: negativ` with no unit can only be deferred/rejected/marked incomplete, never preserved as a confirmed qualitative observation. 6. **Censored/operator values become exact numeric points outside the history display.** `scripts/health/dashboard_v5/read_api.py:652-681` `scripts/health/dashboard_v5/read_api.py:3650-3665` `scripts/health/assets/health-assets/dashboard-v5-api-explorer.js:224-248` `scripts/health/assets/health-assets/dashboard-v5-record.js:791-802` The API separates `<` from numeric `4.2`, but computes numeric deltas without checking the operator; Explorer tables/charts and doctor-report charts consume only `point.value`. **Counterexample:** `<4.2 mg/L` is plotted and tabulated as `4.2`, can receive an exact delta/reference comparison, and loses `<` in the doctor chart. 7. **Duplicate handling can collapse distinct source-specific observations.** `scripts/health/health_dashboard_action_worker.py:1771-1779` An exact same-day/value/unit match reuses the existing canonical row ID and does not create a canonical provenance link for the second document or its observation-specific reference. **Counterexample:** two distinct reports documenting the same CRP value but different source documents/reference ranges become one canonical observation; the second provenance survives only in review staging/audit data despite the UI claim of “Keine stille Zusammenführung.” ### P2: 1 1. **Thematic grouping is inferred by hard-coded medical-name heuristics, not supplied by the catalog.** `scripts/health/dashboard_v5/lab_review.py:64-92` `scripts/health/dashboard_v5/lab_review.py:166-197` `LAB_CATALOG_SPECS` contains no reviewed thematic group, yet `_group()` infers categories from parameter/metric strings. **Counterexample:** Ferritin is assigned “Vitamine und Mineralstoffe” solely because its name contains `ferritin`; changing an identifier or alias can silently change grouping without a catalog review. ## Verification - Exact base/HEAD: `96df2a255dcfb73ea56257997a15e64d58824d64`. - Reviewed all tracked changes and five nonignored untracked source/test/doc files. - Focused synthetic tests: **11 passed**. - Isolated Sprint 7C-E browser suite: **5 passed**. - Python AST, JavaScript syntax, and `git diff --check`: passed. - Used only isolated synthetic fixtures and source-controlled material; no production records were opened or exposed. - **Files created or modified by review: none.**