55 lines
1.8 KiB
Python
Executable File
55 lines
1.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Dict
|
|
|
|
|
|
def load_json(path: Path) -> Dict:
|
|
with path.open("r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
|
|
|
|
def write_json(path: Path, obj: Dict) -> None:
|
|
with path.open("w", encoding="utf-8") as f:
|
|
json.dump(obj, f, indent=2, sort_keys=True)
|
|
f.write("\n")
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description="Check semantic fallback usage against a configured budget.")
|
|
parser.add_argument("--summary", required=True, help="Path to semantic_fallback_summary.json")
|
|
parser.add_argument("--out", required=True, help="Output gate evaluation JSON")
|
|
parser.add_argument("--max-fallback-rate", type=float, default=0.35, help="Max allowed fallback rate in [0,1]")
|
|
parser.add_argument("--min-record-count", type=int, default=5, help="Minimum records required before strict gating")
|
|
args = parser.parse_args()
|
|
|
|
summary = load_json(Path(args.summary))
|
|
fallback_rate = float(summary.get("fallback_rate", 0.0) or 0.0)
|
|
record_count = int(summary.get("record_count", 0) or 0)
|
|
|
|
enforceable = record_count >= args.min_record_count
|
|
passed = True
|
|
reason = "insufficient_data"
|
|
if enforceable:
|
|
passed = fallback_rate <= args.max_fallback_rate
|
|
reason = "within_budget" if passed else "fallback_rate_exceeds_budget"
|
|
|
|
result = {
|
|
"passed": bool(passed),
|
|
"reason": reason,
|
|
"enforceable": bool(enforceable),
|
|
"record_count": record_count,
|
|
"min_record_count": int(args.min_record_count),
|
|
"fallback_rate": fallback_rate,
|
|
"max_fallback_rate": float(args.max_fallback_rate),
|
|
}
|
|
write_json(Path(args.out), result)
|
|
|
|
print(json.dumps(result, sort_keys=True))
|
|
return 0 if passed else 9
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|