import os import re import json import argparse from pathlib import Path ROOT = Path(__file__).resolve().parents[1] def main(): parser = argparse.ArgumentParser() parser.add_argument("--strict", action="store_true") args = parser.parse_args() forbidden_keywords = [ r"decision", r"score", r"risk", r"stop", r"takeProfit", r"size", r"gate", r"verdict", r"stopLoss", r"take_profit" ] forbidden_pattern = re.compile("|".join(forbidden_keywords), re.I) # Allowed exceptions (e.g. log messages or display labels) allowed_pattern = re.compile(r"Logger\.log|console\.log|ui\.alert|'Score'|'Risk'", re.I) files = list(Path(ROOT).glob("gas_*.gs")) total_functions = 0 forbidden_functions = 0 report = { "formula_id": "GAS_FORBIDDEN_LOGIC_RATIO_V2", "files": [] } for f_path in files: content = f_path.read_text(encoding="utf-8") # Extract functions func_pattern = re.compile(r"function\s+(\w+)\s*\(.*?\)\s*\{", re.DOTALL) file_forbidden_count = 0 file_functions = 0 # Simple line-by-line check for keywords within function bodies lines = content.splitlines() for line in lines: if "function " in line: file_functions += 1 total_functions += 1 if forbidden_pattern.search(line) and not allowed_pattern.search(line): file_forbidden_count += 1 ratio = file_forbidden_count / file_functions if file_functions > 0 else 0 report["files"].append({ "file": f_path.name, "forbidden_count": file_forbidden_count, "function_count": file_functions, "ratio": round(ratio, 3) }) total_forbidden = sum(f["forbidden_count"] for f in report["files"]) total_ratio = total_forbidden / total_functions if total_functions > 0 else 0 report["total_forbidden_logic_ratio"] = round(total_ratio, 3) # Threshold 0.05 from TODO report["gate"] = "PASS" if total_ratio <= 0.05 else "FAIL" print(json.dumps(report, indent=2)) if args.strict and report["gate"] == "FAIL": return 1 return 0 if __name__ == "__main__": import sys sys.exit(main())