Files
QuantEngineByItz/tools/build_document_trust_map_v1.py
T
kjh2064 ba7b10f9a7 feat(wbs-9.6): LLM 레이더 문서 신뢰도 맵 생성 도구 구현
WBS-9.6 Phase 1 — 신뢰도 분류 실행:
- tools/build_document_trust_map_v1.py 신규 작성
  spec/llm_radar_trust_tiers_v1.yaml 기준으로 spec/governance/docs 전체
  216개 문서를 canonical/adapter/reference/deprecated tier로 분류
- 분류 결과: canonical=34(15.7%), adapter=141, reference=41, deprecated=0
- 출력: Temp/document_trust_map_v1.json (gate=PASS)

분류 기준:
- AGENTS.md Critical Authority Files → canonical
- spec/ meta.role=canonical → canonical
- spec/governance/ → adapter
- docs/ → reference
- docs/archive/, suggest/, artifacts/archive/ → deprecated
2026-06-23 10:19:49 +09:00

126 lines
4.2 KiB
Python

#!/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())