← Files Investment BankingARCHIVED FILE

skills/cim-builder/scripts/check_source_log.py

2.58 KB · Oct 2, 2026 · 00:27 UTC

↓ Download file

#!/usr/bin/env python3
"""Validate a CIM source log CSV for required columns and missing evidence fields.

Usage:
  python scripts/check_source_log.py path/to/source_log.csv
  python scripts/check_source_log.py path/to/source_log.csv --fail-on-missing
"""

import argparse
import csv
import sys
from pathlib import Path

REQUIRED_COLUMNS = [
    "claim_or_metric",
    "section_or_page",
    "source_name",
    "source_date",
    "fact_tag",
    "confidence",
    "external_ready",
    "review_status",
]

RECOMMENDED_COLUMNS = [
    "value",
    "period",
    "unit",
    "source_location",
    "notes",
    "owner",
]

CRITICAL_FIELDS = [
    "claim_or_metric",
    "section_or_page",
    "source_name",
    "fact_tag",
    "confidence",
]


def read_rows(path: Path):
    if not path.exists():
        raise FileNotFoundError(f"file not found: {path}")
    with path.open("r", newline="", encoding="utf-8-sig") as handle:
        reader = csv.DictReader(handle)
        fieldnames = reader.fieldnames or []
        rows = list(reader)
    return fieldnames, rows


def main() -> int:
    parser = argparse.ArgumentParser(description="Validate a CIM source log CSV.")
    parser.add_argument("csv_path", help="Path to source_log.csv")
    parser.add_argument(
        "--fail-on-missing",
        action="store_true",
        help="Return non-zero exit code when critical row fields are missing.",
    )
    args = parser.parse_args()

    fieldnames, rows = read_rows(Path(args.csv_path))
    missing_columns = [col for col in REQUIRED_COLUMNS if col not in fieldnames]
    missing_recommended = [col for col in RECOMMENDED_COLUMNS if col not in fieldnames]

    print("CIM source log validation")
    print(f"Rows: {len(rows)}")

    if missing_columns:
        print("Missing required columns:")
        for col in missing_columns:
            print(f"- {col}")
        return 2

    if missing_recommended:
        print("Missing recommended columns:")
        for col in missing_recommended:
            print(f"- {col}")

    problem_rows = []
    for idx, row in enumerate(rows, start=2):
        missing_fields = [field for field in CRITICAL_FIELDS if not (row.get(field) or "").strip()]
        if missing_fields:
            problem_rows.append((idx, missing_fields))

    if problem_rows:
        print("Rows with missing critical fields:")
        for row_num, fields in problem_rows:
            print(f"- row {row_num}: {', '.join(fields)}")
    else:
        print("No missing critical fields found.")

    if args.fail_on_missing and problem_rows:
        return 3
    return 0


if __name__ == "__main__":
    sys.exit(main())

SHA-256: 32f05f0e648c33df60047ea1118da8bca714f4427176414921e53c5e4ef6a3d0