File size: 5,805 Bytes
2e1a095
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from __future__ import annotations

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


ROOT_DIR = Path(__file__).resolve().parent.parent
if str(ROOT_DIR) not in sys.path:
    sys.path.insert(0, str(ROOT_DIR))

from scripts import check_research_sources, research_watchlist


DEFAULT_REPORT = ROOT_DIR / "outputs" / "research-refresh.json"


def refresh_research_evidence(
    *,
    watchlist_report: Path = ROOT_DIR / "docs" / "research-watchlist.md",
    recommendation_report: Path = ROOT_DIR / "docs" / "recommended-free-stack.md",
    decision_card_json: Path = ROOT_DIR / "docs" / "recommended-decision-card.json",
    decision_card_report: Path = ROOT_DIR / "docs" / "recommended-decision-card.md",
    metadata_report: Path = ROOT_DIR / "docs" / "huggingface-model-metadata.md",
    report_out: Path = DEFAULT_REPORT,
    require_live_hf_metadata: bool = False,
    timeout: float = 12.0,
) -> dict[str, Any]:
    research_watchlist.write_report(watchlist_report, research_watchlist.CANDIDATES)
    research_watchlist.write_recommendation_report(recommendation_report, research_watchlist.CANDIDATES)
    research_watchlist.write_decision_card_json(decision_card_json, research_watchlist.CANDIDATES)
    research_watchlist.write_decision_card_report(decision_card_report, research_watchlist.CANDIDATES)

    hf_checks = check_research_sources.collect_huggingface_metadata_checks(timeout=timeout)
    check_research_sources.write_huggingface_metadata_report(metadata_report, hf_checks)

    source_checks = check_research_sources.collect_checks(metadata_path=metadata_report)
    source_checks.extend(check_research_sources.collect_key_source_checks())
    source_summary = check_research_sources.summarize(source_checks)

    license_violations = research_watchlist.license_policy_violations(research_watchlist.CANDIDATES)
    live_hf_failures = [check for check in hf_checks if not check.ok]
    ready = bool(
        source_summary["ready"]
        and not license_violations
        and (not require_live_hf_metadata or not live_hf_failures)
    )
    result: dict[str, Any] = {
        "ready": ready,
        "watchlistReport": str(watchlist_report),
        "recommendationReport": str(recommendation_report),
        "decisionCardJson": str(decision_card_json),
        "decisionCardReport": str(decision_card_report),
        "metadataReport": str(metadata_report),
        "sourceSummary": source_summary,
        "licensePolicy": {
            "ready": not license_violations,
            "violations": license_violations,
        },
        "liveHfMetadata": {
            "required": require_live_hf_metadata,
            "counts": {
                "PASS": sum(1 for check in hf_checks if check.ok),
                "FAIL": len(live_hf_failures),
            },
            "failures": [check.__dict__ for check in live_hf_failures],
        },
    }
    report_out.parent.mkdir(parents=True, exist_ok=True)
    report_out.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
    result["report"] = str(report_out)
    return result


def print_summary(result: dict[str, Any]) -> None:
    source_counts = result["sourceSummary"].get("counts", {})
    live_counts = result["liveHfMetadata"].get("counts", {})
    print(f"Research refresh: {'ready' if result['ready'] else 'not ready'}")
    print(f"Watchlist: {result['watchlistReport']}")
    print(f"Recommendation: {result['recommendationReport']}")
    print(f"Decision card JSON: {result['decisionCardJson']}")
    print(f"Decision card report: {result['decisionCardReport']}")
    print(f"Metadata: {result['metadataReport']}")
    print(f"Source checks: {source_counts}")
    print(f"License violations: {len(result['licensePolicy']['violations'])}")
    print(
        "Live HF metadata: "
        f"required={result['liveHfMetadata']['required']} "
        f"pass={live_counts.get('PASS', 0)} fail={live_counts.get('FAIL', 0)}"
    )
    print(f"Report: {result['report']}")


def main() -> None:
    parser = argparse.ArgumentParser(description="Refresh Arabic OCR/TTS research evidence and decision reports.")
    parser.add_argument("--watchlist-report", type=Path, default=ROOT_DIR / "docs" / "research-watchlist.md")
    parser.add_argument("--recommendation-report", type=Path, default=ROOT_DIR / "docs" / "recommended-free-stack.md")
    parser.add_argument("--decision-card-json", type=Path, default=ROOT_DIR / "docs" / "recommended-decision-card.json")
    parser.add_argument("--decision-card-report", type=Path, default=ROOT_DIR / "docs" / "recommended-decision-card.md")
    parser.add_argument("--metadata-report", type=Path, default=ROOT_DIR / "docs" / "huggingface-model-metadata.md")
    parser.add_argument("--report-out", type=Path, default=DEFAULT_REPORT)
    parser.add_argument(
        "--require-live-hf-metadata",
        action="store_true",
        help="Treat failed live Hugging Face metadata fetches as refresh failures.",
    )
    parser.add_argument("--timeout", type=float, default=12.0)
    parser.add_argument("--json", action="store_true")
    args = parser.parse_args()

    result = refresh_research_evidence(
        watchlist_report=args.watchlist_report,
        recommendation_report=args.recommendation_report,
        decision_card_json=args.decision_card_json,
        decision_card_report=args.decision_card_report,
        metadata_report=args.metadata_report,
        report_out=args.report_out,
        require_live_hf_metadata=args.require_live_hf_metadata,
        timeout=args.timeout,
    )
    if args.json:
        print(json.dumps(result, ensure_ascii=False, indent=2))
    else:
        print_summary(result)
    if not result["ready"]:
        raise SystemExit(1)


if __name__ == "__main__":
    main()