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
This commit is contained in:
@@ -0,0 +1,126 @@
|
|||||||
|
#!/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())
|
||||||
Reference in New Issue
Block a user