Files
whetstone_DSL/tools/mcp/check_semantic_planning_gate.py

69 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Dict, List
def gate(packet: Dict[str, object], min_coverage: float, require_caps_for_complex: bool, min_complexity_score: int) -> Dict[str, object]:
coverage_ratio = float((((packet.get("coverage") or {}).get("coverage_ratio")) or 0.0))
anns = packet.get("annotations") or []
cap_count = 0
complexity_score = 0
for ann in anns:
if not isinstance(ann, dict):
continue
t = ann.get("type")
if t == "capability_requirement":
cap_count += 1
if t == "complexity":
fields = ann.get("fields") or {}
complexity_score = int(fields.get("score") or 0)
reasons: List[str] = []
if coverage_ratio < min_coverage:
reasons.append(f"coverage_below_threshold:{coverage_ratio}<{min_coverage}")
if require_caps_for_complex and complexity_score >= min_complexity_score and cap_count == 0:
reasons.append("complex_spec_missing_capability_requirements")
passed = len(reasons) == 0
return {
"passed": passed,
"reasons": reasons,
"metrics": {
"coverage_ratio": coverage_ratio,
"capability_requirement_count": cap_count,
"complexity_score": complexity_score,
"min_coverage": min_coverage,
"require_caps_for_complex": require_caps_for_complex,
"min_complexity_score": min_complexity_score,
},
}
def main() -> None:
ap = argparse.ArgumentParser(description="Check semantic planning packet quality gate.")
ap.add_argument("--packet", required=True)
ap.add_argument("--out", required=True)
ap.add_argument("--min-coverage", type=float, default=0.9)
ap.add_argument("--require-caps-for-complex", action="store_true")
ap.add_argument("--min-complexity-score", type=int, default=2)
args = ap.parse_args()
packet = json.loads(Path(args.packet).read_text(encoding="utf-8"))
res = gate(packet, args.min_coverage, args.require_caps_for_complex, args.min_complexity_score)
out = Path(args.out)
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text(json.dumps(res, indent=2) + "\n", encoding="utf-8")
print(json.dumps(res, indent=2))
if not res["passed"]:
raise SystemExit(3)
if __name__ == "__main__":
main()