"""Audit: fail if any _send_<vendor> in src/ai_client.py contains an inline
tool-call loop (i.e., a for loop with MAX_TOOL_ROUNDS in it).

The follow-up track's invariant: all tool loops should go through
run_with_tool_loop. Inline loops are forbidden EXCEPT for the 3
vendored-call-path vendors (anthropic, gemini, deepseek) which use
their own SDKs and are tracked as deferred work (Phase 5 t5_6/7/8
in state.toml).

Note: gemini_cli was migrated to run_with_tool_loop via send_func
in commit 4748d134. The previous exclusion list incorrectly
included 'gemini_native' (a non-existent function name); that was
removed on 2026-06-11.

Usage: uv run python scripts/audit_no_inline_tool_loops.py
Exit code: 0 = pass; 1 = violations found.
"""
import re
import sys
from pathlib import Path

TARGET = Path("src/ai_client.py")
DEFERRED_VENDORS = frozenset(["anthropic", "gemini", "deepseek"])

def main() -> int:
 text = TARGET.read_text(encoding="utf-8")
 violations: list[str] = []
 for match in re.finditer(r"^def (_send_\w+)\(", text, re.MULTILINE):
  func_name: str = match.group(1)
  vendor = func_name[len("_send_"):]
  if vendor in DEFERRED_VENDORS:
   continue
  func_start = match.start()
  next_def = re.search(r"\n(?:def|async def) _send_\w+\(", text[func_start + 1:])
  func_end = func_start + 1 + (next_def.start() if next_def else len(text) - func_start - 1)
  func_body = text[func_start:func_end]
  if "for _round_idx in range(MAX_TOOL_ROUNDS" in func_body or "for round_idx in range(MAX_TOOL_ROUNDS" in func_body:
   if "run_with_tool_loop" not in func_body:
    violations.append(vendor)
 if violations:
  print(f"FAIL: {len(violations)} vendor(s) have inline tool loops: {violations}")
  print("Use src.ai_client.run_with_tool_loop instead.")
  return 1
 print("OK: all _send_<vendor> functions use run_with_tool_loop (deferred vendors excluded)")
 return 0

if __name__ == "__main__":
 sys.exit(main())
