{
  "run_at": "2026-08-13T11:58:47+00:00",
  "db_path": "/opt/caselaw/repo/output/decisions.db",
  "duration_seconds": 2993.12,
  "summary": {
    "total": 67,
    "passed": 57,
    "critical_failures": 0,
    "quarantine_failures": 0,
    "warning_failures": 10,
    "publish_safe": true
  },
  "results": [
    {
      "name": "urls.no_relative_source_urls",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all source_urls are absolute",
      "sample_rows": [],
      "fix_advice": "scraper must prefix host. See scrapers/entscheidsuche_ingest.py for the GL/BS pattern.",
      "court": null,
      "extra": {}
    },
    {
      "name": "text_integrity.control_chars_sample",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "0 of 1740 sampled rows contain control chars",
      "sample_rows": [],
      "fix_advice": "build_fts5._clean_text (d0072b2) must strip these at insert — a hit means the build-side guarantee regressed (check recent build_fts5/_clean_text changes)",
      "court": null,
      "extra": {}
    },
    {
      "name": "text_integrity.control_chars.ti_gerichte",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "ti_gerichte: clean (200 sampled)",
      "sample_rows": [],
      "fix_advice": "raw portal payload leaked past _clean_text — check the insert path for this court",
      "court": "ti_gerichte",
      "extra": {}
    },
    {
      "name": "text_integrity.control_chars.so_gerichte",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "so_gerichte: clean (200 sampled)",
      "sample_rows": [],
      "fix_advice": "raw portal payload leaked past _clean_text — check the insert path for this court",
      "court": "so_gerichte",
      "extra": {}
    },
    {
      "name": "text_integrity.control_chars.ne_gerichte",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "ne_gerichte: clean (200 sampled)",
      "sample_rows": [],
      "fix_advice": "raw portal payload leaked past _clean_text — check the insert path for this court",
      "court": "ne_gerichte",
      "extra": {}
    },
    {
      "name": "text_integrity.control_chars.ge_gerichte",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "ge_gerichte: clean (200 sampled)",
      "sample_rows": [],
      "fix_advice": "raw portal payload leaked past _clean_text — check the insert path for this court",
      "court": "ge_gerichte",
      "extra": {}
    },
    {
      "name": "structure.sidecar_exists",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "sidecar at output/decision_structure.db (present)",
      "sample_rows": [],
      "fix_advice": "run search_stack/extract_decision_structure.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "schema.required_not_null.decision_id",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all rows have non-null decision_id",
      "sample_rows": [],
      "fix_advice": "investigate ingestion path; required columns must be set by every scraper",
      "court": null,
      "extra": {}
    },
    {
      "name": "schema.required_not_null.court",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all rows have non-null court",
      "sample_rows": [],
      "fix_advice": "investigate ingestion path; required columns must be set by every scraper",
      "court": null,
      "extra": {}
    },
    {
      "name": "schema.decisions_table_exists",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "decisions table present",
      "sample_rows": [],
      "fix_advice": "rebuild output/decisions.db via build_fts5.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "schema.decisions_fts_exists",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "FTS5 virtual table present",
      "sample_rows": [],
      "fix_advice": "rebuild output/decisions.db via build_fts5.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "schema.decision_id_uniqueness",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all decision_ids unique",
      "sample_rows": [],
      "fix_advice": "check INSERT OR IGNORE / INSERT OR REPLACE in scrapers and build_fts5.merge_shards",
      "court": null,
      "extra": {
        "total": 1052991,
        "distinct": 1052991
      }
    },
    {
      "name": "schema.corpus_total_count",
      "severity": "critical",
      "passed": true,
      "metric_value": 1052991,
      "threshold": 950000,
      "message": "corpus total: 1,052,991",
      "sample_rows": [],
      "fix_advice": "check publish.py Step 2 build_fts5 logs; verify .tmp swap completed atomically",
      "court": null,
      "extra": {}
    },
    {
      "name": "mcp_tools.search_fts_returns_hits",
      "severity": "critical",
      "passed": true,
      "metric_value": 404840,
      "threshold": 100,
      "message": "FTS5 'Beschwerde' query: 404,840 hits",
      "sample_rows": [],
      "fix_advice": "if 0, FTS5 build never indexed; rerun build_fts5",
      "court": null,
      "extra": {}
    },
    {
      "name": "mcp_tools.get_decision_by_id",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "get_decision_by_id(bge_BGE_140_III_86): ok",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "mcp_tools.e_number_sort_key_helper",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "e_number_sort: ok (2.10 > 2.2 etc.)",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "mcp_tools.decision_id_variants_helper",
      "severity": "critical",
      "passed": true,
      "metric_value": 2,
      "threshold": 2,
      "message": "_decision_id_variants: 2/2 cases",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "languages.unexpected_values",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all language codes ∈ {de, fr, it, rm}",
      "sample_rows": [],
      "fix_advice": "language must be a 2-letter ISO code. Investigate the scraper that wrote this row's language column.",
      "court": null,
      "extra": {
        "distribution": {
          "de": 501351,
          "fr": 460801,
          "it": 90839
        }
      }
    },
    {
      "name": "languages.distribution_plausible",
      "severity": "critical",
      "passed": true,
      "metric_value": 47.61208785260273,
      "threshold": 30.0,
      "message": "DE 47.6% / FR 43.8% / IT 8.6% / RM 0.00%",
      "sample_rows": [],
      "fix_advice": "DE and FR each need ≥30%, IT ≥3%; under-floor means a language-block of scrapers crashed in publish.py Step 1",
      "court": null,
      "extra": {
        "de": 501351,
        "fr": 460801,
        "it": 90839
      }
    },
    {
      "name": "exports.ris_render",
      "severity": "critical",
      "passed": true,
      "metric_value": 25,
      "threshold": 25,
      "message": "ris: 25/25 sample renders ok",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "exports.bibtex_render",
      "severity": "critical",
      "passed": true,
      "metric_value": 25,
      "threshold": 25,
      "message": "bibtex: 25/25 sample renders ok",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "duplicates.egmr_dual_attribution",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "EGMR attribution clean",
      "sample_rows": [],
      "fix_advice": "codified by build_fts5._dedup_egmr_in_bge() + scrapers/entscheidsuche_ingest.py override",
      "court": null,
      "extra": {}
    },
    {
      "name": "duplicates.decision_id_cross_court",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all decision_ids have a single court attribution",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "dockets.whitespace",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all dockets are trimmed",
      "sample_rows": [],
      "fix_advice": "build_fts5._normalize_dockets() auto-trims; verify it ran",
      "court": null,
      "extra": {}
    },
    {
      "name": "dockets.internal_newlines",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "no embedded newlines",
      "sample_rows": [],
      "fix_advice": "check scraper that wrote these rows; replace newline with space",
      "court": null,
      "extra": {}
    },
    {
      "name": "dates.invalid_format",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all dates are ISO 8601 format",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "cross_db.sidecar_present.statutes",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "statutes at output/statutes.db (present)",
      "sample_rows": [],
      "fix_advice": "rebuild via search_stack/build_statutes_db.py or scripts/extract_*.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "cross_db.sidecar_present.reference_graph",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "reference_graph at output/reference_graph.db (present)",
      "sample_rows": [],
      "fix_advice": "rebuild via search_stack/build_reference_graph_db.py or scripts/extract_*.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "cross_db.sidecar_present.ok_commentaries",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "ok_commentaries at output/ok_commentaries.db (present)",
      "sample_rows": [],
      "fix_advice": "rebuild via search_stack/build_ok_commentaries_db.py or scripts/extract_*.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "cross_db.sidecar_present.decision_structure",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "decision_structure at output/decision_structure.db (present)",
      "sample_rows": [],
      "fix_advice": "rebuild via search_stack/build_decision_structure_db.py or scripts/extract_*.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "cross_db.sidecar_present.cantonal_laws",
      "severity": "critical",
      "passed": true,
      "metric_value": 1,
      "threshold": 1,
      "message": "cantonal_laws at output/cantonal_laws.db (present)",
      "sample_rows": [],
      "fix_advice": "rebuild via search_stack/build_cantonal_laws_db.py or scripts/extract_*.py",
      "court": null,
      "extra": {}
    },
    {
      "name": "courts.null_court",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "every row has a court",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "courts.federal_present.weko",
      "severity": "critical",
      "passed": true,
      "metric_value": 261,
      "threshold": 1,
      "message": "weko: 261 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "weko",
      "extra": {}
    },
    {
      "name": "courts.federal_present.ubi",
      "severity": "critical",
      "passed": true,
      "metric_value": 667,
      "threshold": 1,
      "message": "ubi: 667 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "ubi",
      "extra": {}
    },
    {
      "name": "courts.federal_present.ta_sst",
      "severity": "critical",
      "passed": true,
      "metric_value": 49,
      "threshold": 1,
      "message": "ta_sst: 49 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "ta_sst",
      "extra": {}
    },
    {
      "name": "courts.federal_present.postcom",
      "severity": "critical",
      "passed": true,
      "metric_value": 224,
      "threshold": 1,
      "message": "postcom: 224 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "postcom",
      "extra": {}
    },
    {
      "name": "courts.federal_present.mkg",
      "severity": "critical",
      "passed": true,
      "metric_value": 1244,
      "threshold": 1,
      "message": "mkg: 1,244 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "mkg",
      "extra": {}
    },
    {
      "name": "courts.federal_present.hudoc_ch",
      "severity": "critical",
      "passed": true,
      "metric_value": 847,
      "threshold": 1,
      "message": "hudoc_ch: 847 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "hudoc_ch",
      "extra": {}
    },
    {
      "name": "courts.federal_present.finma_versicherungsrecht",
      "severity": "critical",
      "passed": true,
      "metric_value": 2583,
      "threshold": 1,
      "message": "finma_versicherungsrecht: 2,583 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "finma_versicherungsrecht",
      "extra": {}
    },
    {
      "name": "courts.federal_present.finma",
      "severity": "critical",
      "passed": true,
      "metric_value": 455,
      "threshold": 1,
      "message": "finma: 455 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "finma",
      "extra": {}
    },
    {
      "name": "courts.federal_present.emark",
      "severity": "critical",
      "passed": true,
      "metric_value": 237,
      "threshold": 1,
      "message": "emark: 237 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "emark",
      "extra": {}
    },
    {
      "name": "courts.federal_present.elcom",
      "severity": "critical",
      "passed": true,
      "metric_value": 424,
      "threshold": 1,
      "message": "elcom: 424 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "elcom",
      "extra": {}
    },
    {
      "name": "courts.federal_present.edoeb",
      "severity": "critical",
      "passed": true,
      "metric_value": 1814,
      "threshold": 1,
      "message": "edoeb: 1,814 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "edoeb",
      "extra": {}
    },
    {
      "name": "courts.federal_present.comcom",
      "severity": "critical",
      "passed": true,
      "metric_value": 64,
      "threshold": 1,
      "message": "comcom: 64 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "comcom",
      "extra": {}
    },
    {
      "name": "courts.federal_present.ch_vb",
      "severity": "critical",
      "passed": true,
      "metric_value": 23046,
      "threshold": 1,
      "message": "ch_vb: 23,046 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "ch_vb",
      "extra": {}
    },
    {
      "name": "courts.federal_present.ch_bundesrat",
      "severity": "critical",
      "passed": true,
      "metric_value": 39,
      "threshold": 1,
      "message": "ch_bundesrat: 39 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "ch_bundesrat",
      "extra": {}
    },
    {
      "name": "courts.federal_present.bvger",
      "severity": "critical",
      "passed": true,
      "metric_value": 108421,
      "threshold": 1,
      "message": "bvger: 108,421 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bvger",
      "extra": {}
    },
    {
      "name": "courts.federal_present.bstger",
      "severity": "critical",
      "passed": true,
      "metric_value": 11624,
      "threshold": 1,
      "message": "bstger: 11,624 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bstger",
      "extra": {}
    },
    {
      "name": "courts.federal_present.bpatger",
      "severity": "critical",
      "passed": true,
      "metric_value": 196,
      "threshold": 1,
      "message": "bpatger: 196 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bpatger",
      "extra": {}
    },
    {
      "name": "courts.federal_present.bger",
      "severity": "critical",
      "passed": true,
      "metric_value": 192499,
      "threshold": 1,
      "message": "bger: 192,499 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bger",
      "extra": {}
    },
    {
      "name": "courts.federal_present.bge_egmr",
      "severity": "critical",
      "passed": true,
      "metric_value": 487,
      "threshold": 1,
      "message": "bge_egmr: 487 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bge_egmr",
      "extra": {}
    },
    {
      "name": "courts.federal_present.bge",
      "severity": "critical",
      "passed": true,
      "metric_value": 50467,
      "threshold": 1,
      "message": "bge: 50,467 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bge",
      "extra": {}
    },
    {
      "name": "courts.canonical_format",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all 118 court codes look canonical",
      "sample_rows": [],
      "fix_advice": "court ids must match `[a-z][a-z0-9_]*`. Investigate the scraper writing this row's court value.",
      "court": null,
      "extra": {
        "distinct_courts": 118
      }
    },
    {
      "name": "dates.year_0000",
      "severity": "quarantine",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "no year-0000 placeholder dates",
      "sample_rows": [],
      "fix_advice": "build_fts5._normalize_dates() auto-converts to NULL; verify it ran on this build",
      "court": null,
      "extra": {}
    },
    {
      "name": "dates.pre_1700",
      "severity": "quarantine",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "no pre-1700 dates",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "dates.future_window",
      "severity": "quarantine",
      "passed": true,
      "metric_value": 4,
      "threshold": 50,
      "message": "4 future-dated rows (within tolerance)",
      "sample_rows": [
        {
          "decision_id": "fr_gerichte_608 2025 164",
          "court": "fr_gerichte",
          "decision_date": "2026-09-15"
        },
        {
          "decision_id": "fr_gerichte_502 2026 135",
          "court": "fr_gerichte",
          "decision_date": "2026-09-15"
        },
        {
          "decision_id": "fr_gerichte_604 2025 137",
          "court": "fr_gerichte",
          "decision_date": "2026-09-15"
        },
        {
          "decision_id": "fr_gerichte_602 2025 169",
          "court": "fr_gerichte",
          "decision_date": "2026-09-14"
        }
      ],
      "fix_advice": "if >50, expect a scraper date-parsing regression",
      "court": null,
      "extra": {}
    },
    {
      "name": "dates.far_future",
      "severity": "quarantine",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "no far-future dates",
      "sample_rows": [],
      "fix_advice": "build_fts5._normalize_dates() auto-NULLs these; check scraper date-parsing for German/French month confusion",
      "court": null,
      "extra": {}
    },
    {
      "name": "urls.http_count",
      "severity": "warning",
      "passed": false,
      "metric_value": 220550,
      "threshold": 50,
      "message": "220,550 rows still use http:// (http 220,550 / https 832,441)",
      "sample_rows": [],
      "fix_advice": "upgrade scraper to write https://, then run a REPLACE(source_url, 'http://', 'https://') backfill",
      "court": null,
      "extra": {
        "http": 220550,
        "https": 832441
      }
    },
    {
      "name": "urls.decision_id_whitespace",
      "severity": "warning",
      "passed": false,
      "metric_value": 58825,
      "threshold": 50000,
      "message": "58,825 decision_ids contain whitespace (percent-encoded in URLs; ugly but functional)",
      "sample_rows": [],
      "fix_advice": "if growing >50k, a new scraper started concatenating dockets with spaces; consider underscore separator at scraper time for cleaner URLs",
      "court": null,
      "extra": {}
    },
    {
      "name": "structure.federal_have_erwaegungen",
      "severity": "warning",
      "passed": false,
      "metric_value": 85.5,
      "threshold": 95.0,
      "message": "BGer (>5y old): 855/1000 sample have sidecar paragraphs (85.5%)",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "scholarship.statute_citations_floor",
      "severity": "warning",
      "passed": false,
      "metric_value": 47968,
      "threshold": 65000,
      "message": "47,968 pub→statute citations (expect ~90k)",
      "sample_rows": [],
      "fix_advice": "check statute regex + law-abbreviation map. statutes.db schema may have changed.",
      "court": null,
      "extra": {}
    },
    {
      "name": "dockets.excessively_long",
      "severity": "warning",
      "passed": false,
      "metric_value": 15,
      "threshold": 0,
      "message": "15 rows with docket_number > 150 chars",
      "sample_rows": [
        {
          "decision_id": "ecthr_chamber_20416_92_20417_92_20418_92_20419_92_20420_92_20421_92_20422_92_20423_92_20424_92_20425_92_20426_92_20427_92_20428_92_20429_92_20430_92_20431_92_20432_92_20665_92_20666_92_20667_92_20668_92_20669_92_20670_92_20671_92_20672_92_20673_92_20674_92_20675_92_20718_92_20719_92_20720_92_20721_92_20722_92_20723_92_20724_92_20725_92_20726_92_20727_92_20738_92_21270_93_21716_93_21718_93_21719_93_21721_93_21722_93_21723_93_21724_93_21725_93_21726_93_21727_93_21728_93_21729_93_21730_93_21731_93_21732_93_21734_93_21735_93_21736_93_21737_93_21738_93_21740_93_21742_93_21744_93_21745_93_21746_93_21747_93_21748_93_21749_93_21750_93_21991_93_21992_93_21998_93_21999_93_22000_93_22213_93_22214_93_22215_93_22216_93_22217_93_22218_93_22219_93_22220_93_22221_93_22222_93_22223_93_22224_93_22225_93_22226_93_22227_93_22854_93_22855_93_22856_93_22857_93",
          "court": "ecthr_chamber",
          "docket_preview": "20416/92_20417/92_20418/92_20419/92_20420/92_20421/92_20422/92_20423/92_20424/92...",
          "len": 836
        },
        {
          "decision_id": "ecthr_chamber_9988_13_14338_14_45973_14_48431_14_59787_14_4798_15_7098_15_13474_15_14070_15_24773_15_25934_15_27654_15_32412_15_32423_15_37043_15_42351_15_44403_15_47695_15_49258_15_52257_15_55272_15_55280_15_57310_15_57931_15_60098_15_60400_15_1786_16_3085_16_5941_16_10028_16_14980_16_15098_16_19719_16_26169_16_26303_16_33734_16_35816_16_37256_16_48049_16_53429_16_59985_16_61699_16_61732_16_61989_16_69826_16_76854_16_9076_17_14823_17_16094_17_29482_17_34499_17_53490_17_60569_17_61111_17_62848_17_64181_17_69157_17_81560_17_81751_17_130_18_15813_18",
          "court": "ecthr_chamber",
          "docket_preview": "9988/13_14338/14_45973/14_48431/14_59787/14_4798/15_7098/15_13474/15_14070/15_24...",
          "len": 539
        },
        {
          "decision_id": "ecthr_committee_4180_08_4219_08_8725_09_8727_09_8728_09_8733_09_8735_09_8737_09_8738_09_8739_09_8743_09_8746_09_8747_09_8750_09_8751_09_8756_09_8758_09_8759_09_8760_09_8764_09_8771_09_8773_09_8775_09_8776_09_8777_09_8778_09_8779_09_8780_09_8781_09_8783_09_8784_09_8787_09_28922_09_38777_09_38786_09_38792_09_38814_09_38816_09_38825_09_38829_09_38841_09_38844_09_45047_09_45057_09_62387_09_62409_09_62874_09_2248_10_2257_10_49829_10",
          "court": "ecthr_committee",
          "docket_preview": "4180/08_4219/08_8725/09_8727/09_8728/09_8733/09_8735/09_8737/09_8738/09_8739/09_...",
          "len": 415
        },
        {
          "decision_id": "ecthr_committee_8726_09_8731_09_8732_09_8734_09_8736_09_8741_09_8742_09_8745_09_8749_09_8752_09_8754_09_8755_09_8762_09_8765_09_8767_09_8768_09_8769_09_8770_09_8774_09_8782_09_11254_09_11271_09_38800_09_45049_09_45053_09_45054_09_45064_09_45083_09_45089_09_45095_09_45099_09_45102_09_45105_09_45106_09_45107_09_45108_09_45109_09_45111_09_2252_10",
          "court": "ecthr_committee",
          "docket_preview": "8726/09_8731/09_8732/09_8734/09_8736/09_8741/09_8742/09_8745/09_8749/09_8752/09_...",
          "len": 329
        },
        {
          "decision_id": "ecthr_committee_37105_21_52836_21_22785_22_22788_22_22790_22_22793_22_22796_22_22803_22_22805_22_22807_22_22811_22_22818_22_22822_22_22975_22_22977_22_22978_22_22979_22_22981_22_22982_22_22983_22_22986_22_22988_22_22989_22_22990_22_22991_22_22992_22_22993_22_22997_22_22998_22_22999_22_23001_22_23003_22",
          "court": "ecthr_committee",
          "docket_preview": "37105/21_52836/21_22785/22_22788/22_22790/22_22793/22_22796/22_22803/22_22805/22...",
          "len": 287
        }
      ],
      "fix_advice": null,
      "court": null,
      "extra": {}
    },
    {
      "name": "dates.total_null",
      "severity": "warning",
      "passed": false,
      "metric_value": 2567,
      "threshold": 1923,
      "message": "2567 total NULL decision_dates (expected ≤ 1923)",
      "sample_rows": [],
      "fix_advice": "if growing, identify the new court contributing NULL dates via per-court breakdown",
      "court": null,
      "extra": {}
    },
    {
      "name": "dates.publication_before_decision",
      "severity": "warning",
      "passed": false,
      "metric_value": 40064,
      "threshold": 28000,
      "message": "40064 rows with publication_date < decision_date (13414 gross >1mo) — baseline 28000",
      "sample_rows": [
        {
          "decision_id": "bge_150 II 417",
          "court": "bge",
          "decision_date": "2024-03-12",
          "publication_date": "2024-01-01"
        },
        {
          "decision_id": "bge_150 II 537",
          "court": "bge",
          "decision_date": "2024-06-04",
          "publication_date": "2024-01-01"
        },
        {
          "decision_id": "bge_150 III 160",
          "court": "bge",
          "decision_date": "2024-03-18",
          "publication_date": "2024-01-01"
        },
        {
          "decision_id": "bge_150 IV 196",
          "court": "bge",
          "decision_date": "2024-04-29",
          "publication_date": "2024-01-01"
        },
        {
          "decision_id": "bge_150 IV 292",
          "court": "bge",
          "decision_date": "2024-03-11",
          "publication_date": "2024-01-01"
        }
      ],
      "fix_advice": "decision_date (header ruling date) is trusted; run scripts/fix_date_inversions.py to swap-or-NULL the suspect publication_date + add a build_fts5 forward guard. Growth here = a scraper labeling the dates backwards.",
      "court": null,
      "extra": {
        "gross_over_1mo": 13414,
        "by_court": {
          "bge": 15833,
          "zh_sozialversicherungsgericht": 13308,
          "ge_gerichte": 7872,
          "gr_gerichte": 984,
          "vd_findinfo": 263,
          "bs_appellationsgericht": 250,
          "bvger": 209,
          "elcom": 162,
          "ch_vb": 158,
          "fr_gerichte": 156
        }
      }
    },
    {
      "name": "dates.null_date_floor.ti_gerichte",
      "severity": "warning",
      "passed": false,
      "metric_value": 753,
      "threshold": 603,
      "message": "ti_gerichte: 753 NULL decision_dates (floor 549)",
      "sample_rows": [],
      "fix_advice": "if growing, check the court-specific recovery script in build_fts5._recover_decision_dates / scripts/",
      "court": "ti_gerichte",
      "extra": {}
    },
    {
      "name": "dates.null_date_floor.gr_gerichte",
      "severity": "warning",
      "passed": false,
      "metric_value": 811,
      "threshold": 297,
      "message": "gr_gerichte: 811 NULL decision_dates (floor 270)",
      "sample_rows": [],
      "fix_advice": "if growing, check the court-specific recovery script in build_fts5._recover_decision_dates / scripts/",
      "court": "gr_gerichte",
      "extra": {}
    },
    {
      "name": "cross_db.no_orphan_structure_rows",
      "severity": "warning",
      "passed": false,
      "metric_value": 10.18,
      "threshold": 1.0,
      "message": "509/5000 (10.18%) sidecar rows orphan",
      "sample_rows": [],
      "fix_advice": "rerun extract_decision_structure.py against current decisions.db so IDs realign",
      "court": null,
      "extra": {}
    }
  ]
}