← Files Investment BankingARCHIVED FILE

scripts/validate_banker_runtime_readiness.py

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

↓ Download file

#!/usr/bin/env python3
"""Validate the Investment Banking banker runtime readiness inventory."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path
from typing import Any, Mapping

ROOT = Path(__file__).resolve().parents[1]
VALID_GAP_TYPES = {
    "runtime_missing",
    "model_citation_missing",
    "native_office_missing",
    "stdout_machine_readable",
    "pdf_ocr_missing",
    "visual_review_missing",
    "domain_depth_partial",
    "manifest_nonstandard",
    "source_gate_partial",
}
VALID_MATURITY = {
    "instruction_only",
    "support_script",
    "deterministic_human_artifact",
    "banker_operational",
    "senior_ready",
    "external_ready",
}
VALID_STATUS = {"planned", "in_progress", "fixed", "accepted_gap"}
VALID_PRIORITY = {"P0", "P1", "P2"}
REQUIRED = {
    "skill",
    "gap_type",
    "current_runtime",
    "target_runtime",
    "hero_artifact",
    "companion_artifact",
    "support_artifacts",
    "validator_needed",
    "eval_needed",
    "priority",
    "runtime_maturity",
    "status",
}


def _as_list(value: Any) -> list[Any]:
    return value if isinstance(value, list) else []


def validate_inventory(payload: Mapping[str, Any], root: Path = ROOT) -> list[str]:
    errors: list[str] = []
    if payload.get("plugin") != "investment-banking":
        errors.append("plugin must be investment-banking")
    rows = payload.get("rows")
    if not isinstance(rows, list) or not rows:
        errors.append("rows must be a non-empty array")
        return errors
    seen: set[tuple[str, str]] = set()
    for idx, row in enumerate(rows):
        prefix = f"rows[{idx}]"
        if not isinstance(row, dict):
            errors.append(f"{prefix} must be an object")
            continue
        missing = sorted(REQUIRED - set(row))
        if missing:
            errors.append(f"{prefix} missing required fields: {', '.join(missing)}")
        key = (str(row.get("skill", "")), str(row.get("gap_type", "")))
        if key in seen:
            errors.append(f"{prefix} duplicate skill/gap_type pair: {key}")
        seen.add(key)
        if row.get("gap_type") not in VALID_GAP_TYPES:
            errors.append(f"{prefix}.gap_type invalid: {row.get('gap_type')}")
        if row.get("runtime_maturity") not in VALID_MATURITY:
            errors.append(f"{prefix}.runtime_maturity invalid: {row.get('runtime_maturity')}")
        if row.get("status") not in VALID_STATUS:
            errors.append(f"{prefix}.status invalid: {row.get('status')}")
        if row.get("priority") not in VALID_PRIORITY:
            errors.append(f"{prefix}.priority invalid: {row.get('priority')}")
        for field in ("support_artifacts", "validator_needed", "eval_needed", "eval_prompt_ids"):
            if field in row and not isinstance(row[field], list):
                errors.append(f"{prefix}.{field} must be an array")
        skill = row.get("skill")
        if (
            skill
            and not (root / "skills" / str(skill)).exists()
            and str(skill) != "dashboard-builder"
        ):
            errors.append(f"{prefix}.skill directory not found: {skill}")
        if row.get("status") == "fixed":
            script = str(row.get("runtime_script", ""))
            test = str(row.get("primary_test", ""))
            if not script or not (root / script).exists():
                errors.append(f"{prefix} fixed gap must name an existing runtime_script")
            if not test or not (root / test).exists():
                errors.append(f"{prefix} fixed gap must name an existing primary_test")
            if not _as_list(row.get("eval_prompt_ids")):
                errors.append(f"{prefix} fixed gap must include eval_prompt_ids")
    return errors


def main(argv: list[str] | None = None) -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("inventory", type=Path)
    args = parser.parse_args(argv)
    payload = json.loads(args.inventory.read_text(encoding="utf-8"))
    errors = validate_inventory(payload)
    if errors:
        for error in errors:
            print(f"ERROR: {error}", file=sys.stderr)
        return 1
    print(f"OK: {len(payload.get('rows', []))} banker runtime readiness rows validated")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

SHA-256: a29890a8de9821f70e62811d4040294c90b023719fcbfcafcd89854e753637f4