#!/usr/bin/env python3 """WBS-9.6: LLM 레이더 문서 신뢰도 맵 생성 도구.""" from __future__ import annotations import json import sys from pathlib import Path import yaml ROOT = Path(__file__).resolve().parents[1] TRUST_TIERS_SPEC = ROOT / "spec" / "llm_radar_trust_tiers_v1.yaml" OUT = ROOT / "Temp" / "document_trust_map_v1.json" CANONICAL_SPEC_NAMES = { "spec/00_execution_contract.yaml", "spec/12_field_dictionary.yaml", "spec/13_formula_registry.yaml", "spec/14_raw_workbook_mapping.yaml", "spec/15_account_snapshot_contract.yaml", "spec/02_data_contract.yaml", "spec/09_decision_flow.yaml", "spec/11_market_regime.yaml", "spec/risk/aggregate_risk.yaml", "spec/risk/portfolio_exposure.yaml", "spec/calibration_registry.yaml", "spec/19_harness_contract.yaml", "spec/41_release_dag.yaml", } DEPRECATED_PREFIXES = ("docs/archive/", "suggest/", "artifacts/archive/") def _get_meta_role(path): try: data = yaml.safe_load(path.read_text(encoding="utf-8", errors="replace")) if not isinstance(data, dict): return None meta = data.get("meta") if isinstance(meta, dict): return meta.get("role") except Exception: pass return None def _classify(rel, path): if rel.startswith(DEPRECATED_PREFIXES): return "deprecated" if rel.startswith("docs/"): return "reference" if rel.startswith("governance/rules/"): return "adapter" if rel.startswith("spec/") and path.suffix == ".yaml": if rel in CANONICAL_SPEC_NAMES: return "canonical" role = _get_meta_role(path) if role == "canonical": return "canonical" if role in ("derived_adapter", "compatibility_index", "adapter"): return "adapter" if role == "deprecated": return "deprecated" if role == "reference": return "reference" return "adapter" if rel.startswith("governance/"): return "adapter" return "reference" def main(): if not TRUST_TIERS_SPEC.exists(): print(f"ERROR: trust tiers spec not found: {TRUST_TIERS_SPEC}", file=sys.stderr) return 1 spec_tier = yaml.safe_load(TRUST_TIERS_SPEC.read_text(encoding="utf-8")) scan_roots = [ROOT / "spec", ROOT / "governance", ROOT / "docs"] docs = [] tier_counts = {"canonical": 0, "adapter": 0, "reference": 0, "deprecated": 0} trust_level_map = {"canonical": 100, "adapter": 80, "reference": 60, "deprecated": 0} priority_map = {"canonical": 1, "adapter": 2, "reference": 3, "deprecated": 0} for root in scan_roots: if not root.exists(): continue for path in sorted(root.rglob("*")): if not path.is_file(): continue if path.suffix not in (".yaml", ".yml", ".md", ".json", ".py"): continue rel = path.relative_to(ROOT).as_posix() tier = _classify(rel, path) tier_counts[tier] = tier_counts.get(tier, 0) + 1 docs.append({ "path": rel, "tier": tier, "trust_level": trust_level_map.get(tier, 60), "loading_priority": priority_map.get(tier, 3), "size_bytes": path.stat().st_size, }) total = len(docs) canonical_pct = round(100.0 * tier_counts.get("canonical", 0) / total, 1) if total else 0.0 result = { "formula_id": "DOCUMENT_TRUST_MAP_V1", "gate": "PASS", "as_of": "2026-06-23", "spec_path": TRUST_TIERS_SPEC.relative_to(ROOT).as_posix(), "total_documents": total, "tier_counts": tier_counts, "canonical_coverage_pct": canonical_pct, "trust_tier_system": spec_tier.get("trust_tier_system", {}), "documents": docs, } OUT.parent.mkdir(parents=True, exist_ok=True) OUT.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") summary = {k: v for k, v in result.items() if k != "documents"} print(json.dumps(summary, ensure_ascii=False, indent=2)) print(f"\n-> 출력: {OUT}") return 0 if __name__ == "__main__": raise SystemExit(main())