{
  "run_at": "2026-10-13T13:39:25+00:00",
  "scope": "critical_only",
  "db_path": "/opt/caselaw/repo/output/decisions.db",
  "duration_seconds": 2374.11,
  "summary": {
    "total": 65,
    "passed": 57,
    "critical_failures": 0,
    "quarantine_failures": 0,
    "warning_failures": 8,
    "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": {},
      "elapsed_s": 2304.168
    },
    {
      "name": "text_integrity.control_chars_sample",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "0 of 1748 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": {},
      "elapsed_s": 3.91
    },
    {
      "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": {},
      "elapsed_s": 2.621
    },
    {
      "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": {},
      "elapsed_s": 2.621
    },
    {
      "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": {},
      "elapsed_s": 2.621
    },
    {
      "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": {},
      "elapsed_s": 2.621
    },
    {
      "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": {},
      "elapsed_s": 0.001
    },
    {
      "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": {},
      "elapsed_s": 0.069
    },
    {
      "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": {},
      "elapsed_s": 0.069
    },
    {
      "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": {},
      "elapsed_s": 0.001
    },
    {
      "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": {},
      "elapsed_s": 0.001
    },
    {
      "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": 1078022,
        "distinct": 1078022
      },
      "elapsed_s": 0.208
    },
    {
      "name": "schema.corpus_total_count",
      "severity": "critical",
      "passed": true,
      "metric_value": 1078022,
      "threshold": 950000,
      "message": "corpus total: 1,078,022",
      "sample_rows": [],
      "fix_advice": "check publish.py Step 2 build_fts5 logs; verify .tmp swap completed atomically",
      "court": null,
      "extra": {},
      "elapsed_s": 0.027
    },
    {
      "name": "mcp_tools.search_fts_returns_hits",
      "severity": "critical",
      "passed": true,
      "metric_value": 409599,
      "threshold": 100,
      "message": "FTS5 'Beschwerde' query: 409,599 hits",
      "sample_rows": [],
      "fix_advice": "if 0, FTS5 build never indexed; rerun build_fts5",
      "court": null,
      "extra": {},
      "elapsed_s": 0.024
    },
    {
      "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": {},
      "elapsed_s": 0.004
    },
    {
      "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": {},
      "elapsed_s": 0.48
    },
    {
      "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": {},
      "elapsed_s": 1.75
    },
    {
      "name": "languages.unexpected_values",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all language codes ∈ {de, fr, it, rm} (+ en on ECtHR courts)",
      "sample_rows": [],
      "fix_advice": "language must be a 2-letter ISO code, and `en` is reserved for English-authoritative ECtHR judgments. Investigate the scraper that wrote this row's language column.",
      "court": null,
      "extra": {
        "distribution": {
          "de": 504611,
          "en": 3972,
          "fr": 478230,
          "it": 91209
        }
      },
      "elapsed_s": 0.155
    },
    {
      "name": "languages.distribution_plausible",
      "severity": "critical",
      "passed": true,
      "metric_value": 46.98207718448862,
      "threshold": 30.0,
      "message": "DE 47.0% / FR 44.5% / IT 8.5% / 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": 504611,
        "fr": 478230,
        "it": 91209
      },
      "elapsed_s": 0.177
    },
    {
      "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": {},
      "elapsed_s": 0.027
    },
    {
      "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": {},
      "elapsed_s": 0.33
    },
    {
      "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": {},
      "elapsed_s": 1.18
    },
    {
      "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": {},
      "elapsed_s": 8.223
    },
    {
      "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": {},
      "elapsed_s": 0.104
    },
    {
      "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": {},
      "elapsed_s": 0.125
    },
    {
      "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": {},
      "elapsed_s": 0.083
    },
    {
      "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": {},
      "elapsed_s": 0.0
    },
    {
      "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": {},
      "elapsed_s": 0.0
    },
    {
      "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": {},
      "elapsed_s": 0.0
    },
    {
      "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": {},
      "elapsed_s": 0.0
    },
    {
      "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": {},
      "elapsed_s": 0.0
    },
    {
      "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": {},
      "elapsed_s": 0.091
    },
    {
      "name": "courts.federal_present.weko",
      "severity": "critical",
      "passed": true,
      "metric_value": 299,
      "threshold": 1,
      "message": "weko: 299 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "weko",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.ubi",
      "severity": "critical",
      "passed": true,
      "metric_value": 679,
      "threshold": 1,
      "message": "ubi: 679 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "ubi",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.ta_sst",
      "severity": "critical",
      "passed": true,
      "metric_value": 90,
      "threshold": 1,
      "message": "ta_sst: 90 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "ta_sst",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.postcom",
      "severity": "critical",
      "passed": true,
      "metric_value": 336,
      "threshold": 1,
      "message": "postcom: 336 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "postcom",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "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": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.hudoc_ch",
      "severity": "critical",
      "passed": true,
      "metric_value": 857,
      "threshold": 1,
      "message": "hudoc_ch: 857 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "hudoc_ch",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.finma_versicherungsrecht",
      "severity": "critical",
      "passed": true,
      "metric_value": 2585,
      "threshold": 1,
      "message": "finma_versicherungsrecht: 2,585 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "finma_versicherungsrecht",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "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": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.emark",
      "severity": "critical",
      "passed": true,
      "metric_value": 433,
      "threshold": 1,
      "message": "emark: 433 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "emark",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.elcom",
      "severity": "critical",
      "passed": true,
      "metric_value": 435,
      "threshold": 1,
      "message": "elcom: 435 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "elcom",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.edoeb",
      "severity": "critical",
      "passed": true,
      "metric_value": 1818,
      "threshold": 1,
      "message": "edoeb: 1,818 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "edoeb",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "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": {},
      "elapsed_s": 0.101
    },
    {
      "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": {},
      "elapsed_s": 0.101
    },
    {
      "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": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.bvger",
      "severity": "critical",
      "passed": true,
      "metric_value": 109323,
      "threshold": 1,
      "message": "bvger: 109,323 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bvger",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.bstger",
      "severity": "critical",
      "passed": true,
      "metric_value": 11718,
      "threshold": 1,
      "message": "bstger: 11,718 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bstger",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.bpatger",
      "severity": "critical",
      "passed": true,
      "metric_value": 197,
      "threshold": 1,
      "message": "bpatger: 197 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bpatger",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.bger",
      "severity": "critical",
      "passed": true,
      "metric_value": 193740,
      "threshold": 1,
      "message": "bger: 193,740 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bger",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.bge_egmr",
      "severity": "critical",
      "passed": true,
      "metric_value": 491,
      "threshold": 1,
      "message": "bge_egmr: 491 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bge_egmr",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.federal_present.bge",
      "severity": "critical",
      "passed": true,
      "metric_value": 49486,
      "threshold": 1,
      "message": "bge: 49,486 decisions",
      "sample_rows": [],
      "fix_advice": null,
      "court": "bge",
      "extra": {},
      "elapsed_s": 0.101
    },
    {
      "name": "courts.canonical_format",
      "severity": "critical",
      "passed": true,
      "metric_value": 0,
      "threshold": 0,
      "message": "all 124 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": 124
      },
      "elapsed_s": 0.106
    },
    {
      "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": {},
      "elapsed_s": 0.055
    },
    {
      "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": {},
      "elapsed_s": 0.001
    },
    {
      "name": "dates.future_window",
      "severity": "quarantine",
      "passed": true,
      "metric_value": 1,
      "threshold": 50,
      "message": "1 future-dated rows (within tolerance)",
      "sample_rows": [
        {
          "decision_id": "fr_gerichte_605 2025 140",
          "court": "fr_gerichte",
          "decision_date": "2027-07-27"
        }
      ],
      "fix_advice": "if >50, expect a scraper date-parsing regression",
      "court": null,
      "extra": {},
      "elapsed_s": 0.0
    },
    {
      "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": {},
      "elapsed_s": 0.001
    },
    {
      "name": "urls.http_count",
      "severity": "warning",
      "passed": false,
      "metric_value": 221230,
      "threshold": 50,
      "message": "221,230 rows still use http:// (http 221,230 / https 856,792)",
      "sample_rows": [],
      "fix_advice": "upgrade scraper to write https://, then run a REPLACE(source_url, 'http://', 'https://') backfill",
      "court": null,
      "extra": {
        "http": 221230,
        "https": 856792
      },
      "elapsed_s": 2347.965
    },
    {
      "name": "urls.decision_id_whitespace",
      "severity": "warning",
      "passed": false,
      "metric_value": 60663,
      "threshold": 50000,
      "message": "60,663 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": {},
      "elapsed_s": 0.152
    },
    {
      "name": "structure.federal_have_erwaegungen",
      "severity": "warning",
      "passed": false,
      "metric_value": 87.4,
      "threshold": 95.0,
      "message": "BGer (>5y old): 874/1000 sample have sidecar paragraphs (87.4%)",
      "sample_rows": [],
      "fix_advice": null,
      "court": null,
      "extra": {},
      "elapsed_s": 1.741
    },
    {
      "name": "dockets.excessively_long",
      "severity": "warning",
      "passed": false,
      "metric_value": 7,
      "threshold": 0,
      "message": "7 rows with docket_number > 150 chars",
      "sample_rows": [
        {
          "decision_id": "sg_publikationen_Art. 28 IVG. Rentenanspruch. Beweiswürdigung Gutachten. Kein rentenbegründender Invaliditätsgrad (Entscheid des Versicherungsgerichts des Kantons St. Gallen vom  15. Dezember 2015, IV 2012_450).  Bestätigt durch Urteil des Bundesgerichts 8C_92_2015.",
          "court": "sg_versicherungsgericht",
          "docket_preview": "Art. 28 IVG. Rentenanspruch. Beweiswürdigung Gutachten. Kein rentenbegründender ...",
          "len": 247
        },
        {
          "decision_id": "sg_gerichte_Art._28_IVG._Rentenanspruch._Beweisw_rdigung_Gutachten._Kein_rentenbegr_ndender_Invalidit_tsgrad__Entscheid_des_Versicherungsgerichts_des_Kantons_St._Gallen_vom__15._Dezember_2015__IV_2012_450_.__Best_tigt_durch_Urteil_des_Bundesgerichts_8C_92_2015.",
          "court": "sg_gerichte",
          "docket_preview": "Art. 28 IVG. Rentenanspruch. Beweiswürdigung Gutachten. Kein rentenbegründender ...",
          "len": 247
        },
        {
          "decision_id": "sh_obergericht__div__span_style__color__rgb_70__70__70___font-family__Helvetica_Neue_Web_Light______SimSun________STXihei__sans-serif__font-size__1.34116em__font-weight__500__background-color__rgb_235__235__235____Nr._63_2020_6__span__br___div_",
          "court": "sh_obergericht",
          "docket_preview": "<div><span style='color: rgb(70, 70, 70); font-family: Helvetica_Neue_Web_Light,...",
          "len": 229
        },
        {
          "decision_id": "sh_gerichte_Nr. 60_2023_3<span style=\"color: rgb(70, 70, 70); font-family: Helvetica_Neue_Web_Light, 宋体, SimSun, 华文细黑, STXihei, sans-serif; font-size: 1.33882em; font-weight: 500; background-color: rgb(235, 235, 235);\">&nbsp;&nbsp;<_span>",
          "court": "sh_gerichte",
          "docket_preview": "Nr. 60/2023/3<span style=\"color: rgb(70, 70, 70); font-family: Helvetica_Neue_We...",
          "len": 226
        },
        {
          "decision_id": "sh_obergericht_60_2023_3_span_style__color__rgb_70__70__70___font-family__Helvetica_Neue_Web_Light______SimSun________STXihei__sans-serif__font-size__1.33882em__font-weight__500__background-color__rgb_235__235__235________span_",
          "court": "sh_obergericht",
          "docket_preview": "60/2023/3<span style='color: rgb(70, 70, 70); font-family: Helvetica_Neue_Web_Li...",
          "len": 211
        }
      ],
      "fix_advice": null,
      "court": null,
      "extra": {},
      "elapsed_s": 3.722
    },
    {
      "name": "dates.total_null",
      "severity": "warning",
      "passed": false,
      "metric_value": 2713,
      "threshold": 1927,
      "message": "2713 total NULL decision_dates (expected ≤ 1927)",
      "sample_rows": [],
      "fix_advice": "if growing, identify the new court contributing NULL dates via per-court breakdown",
      "court": null,
      "extra": {},
      "elapsed_s": 0.001
    },
    {
      "name": "dates.publication_before_decision",
      "severity": "warning",
      "passed": false,
      "metric_value": 34702,
      "threshold": 28000,
      "message": "34702 rows with publication_date < decision_date (8616 gross >1mo) — baseline 28000",
      "sample_rows": [
        {
          "decision_id": "gr_gerichte_ERZ 2009 81",
          "court": "gr_gerichte",
          "decision_date": "2009-03-17",
          "publication_date": "2009-02-10"
        },
        {
          "decision_id": "bge_BGE_121_I_102",
          "court": "bge",
          "decision_date": "1995-05-10",
          "publication_date": "1995-01-01"
        },
        {
          "decision_id": "bge_BGE_121_I_108",
          "court": "bge",
          "decision_date": "1995-06-09",
          "publication_date": "1995-01-01"
        },
        {
          "decision_id": "bge_BGE_121_I_113",
          "court": "bge",
          "decision_date": "1995-07-17",
          "publication_date": "1995-01-01"
        },
        {
          "decision_id": "bge_BGE_121_I_138",
          "court": "bge",
          "decision_date": "1995-04-19",
          "publication_date": "1995-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": 8616,
        "by_court": {
          "zh_sozialversicherungsgericht": 13308,
          "bge": 10498,
          "ge_gerichte": 7872,
          "gr_gerichte": 984,
          "vd_findinfo": 263,
          "bs_appellationsgericht": 250,
          "bvger": 209,
          "elcom": 162,
          "ch_vb": 158,
          "fr_gerichte": 156
        }
      },
      "elapsed_s": 4.382
    },
    {
      "name": "dates.null_date_floor.ti_gerichte",
      "severity": "warning",
      "passed": false,
      "metric_value": 831,
      "threshold": 603,
      "message": "ti_gerichte: 831 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": {},
      "elapsed_s": 0.124
    },
    {
      "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": {},
      "elapsed_s": 0.124
    }
  ]
}