import json import sys from pathlib import Path KEY_CONTRACT_TERMS = { "qpi": [ "problem_owner", "time_scale", "dominant_scarcity", "evidence_gap", "classification", "no_call" ], "intellectual_archaeology": [ "should_call", "recommended_max_depth", "stop_reason", "no_deeper_reason", "validation_needed", "action_implication" ] } def read_json(path): return json.loads(path.read_text(encoding="utf-8")) def card_path_for_model(root, model_id): return root / "cards" / f"{model_id}.md" def check_model_card(root, model_path): model = read_json(model_path) model_id = model["model_id"] card_path = card_path_for_model(root, model_id) errors = [] manual_review = [] if not card_path.exists(): return [f"missing card {card_path.relative_to(root).as_posix()}"], [] text = card_path.read_text(encoding="utf-8") hard_values = [ model_id, model["model_name"], model["model_type"], model["pipeline_position"], model["regression_status"], model["version"], model["last_updated"], model.get("status", "") ] stability_level = model.get("stability_profile", {}).get("stability_level") if stability_level: hard_values.append(stability_level) for value in hard_values: if value and value not in text: errors.append(f"{model_id} card missing hard value {value}") for source_id in model.get("source_articles", []): if source_id not in text: errors.append(f"{model_id} card missing source article {source_id}") for excerpt_id in model.get("source_evidence", []): if excerpt_id not in text: errors.append(f"{model_id} card missing source evidence {excerpt_id}") for term in KEY_CONTRACT_TERMS.get(model_id, []): if term not in text: errors.append(f"{model_id} card missing key contract term {term}") manual_review.append(f"{model_id}: long Chinese definitions, examples, and risk notes require human semantic review.") return errors, manual_review def write_report(root, errors, manual_review): report_path = root / "reports" / "model_card_sync_report_v0.2.md" lines = [ "# Model Card Sync Report v0.2", "", f"Status: `{'PASS' if not errors else 'FAIL'}`", "", ] if errors: lines.append("## Errors") lines.append("") lines.extend(f"- {error}" for error in errors) lines.append("") else: lines.append("## Hard-Field Result") lines.append("") lines.append("- Model IDs, names, types, pipeline positions, source IDs, evidence IDs, stability fields, regression status, version, and last_updated are present in Markdown cards.") lines.append("- Key output contract and depth-control terms are present.") lines.append("") lines.append("## Manual Review Items") lines.append("") lines.extend(f"- {item}" for item in manual_review) report_path.write_text("\n".join(lines) + "\n", encoding="utf-8") return report_path def check_sync(root): root = Path(root) errors = [] manual_review = [] for model_path in sorted((root / "models").glob("*.model.json")): model_errors, model_manual_review = check_model_card(root, model_path) errors.extend(model_errors) manual_review.extend(model_manual_review) report_path = write_report(root, errors, manual_review) return errors, report_path def main(): root = Path(__file__).resolve().parents[1] errors, report_path = check_sync(root) print(f"model/card sync report written to {report_path}") if errors: for error in errors: print(f"ERROR: {error}") return 1 print("model/card sync passed") return 0 if __name__ == "__main__": sys.exit(main())