143215a7a2ed0bf37f565d6463ca11964b69dc80 jnavarr5 Wed Jul 29 11:02:35 2026 -0700 Floor the scaled daily code review timeout at the previous flat 600s so 1-2 commit authors keep the same runway, No RM. diff --git src/utils/codeReviewAi.py src/utils/codeReviewAi.py index 81f8a4fdbc4..a1fe83010aa 100755 --- src/utils/codeReviewAi.py +++ src/utils/codeReviewAi.py @@ -34,32 +34,34 @@ GIT_REPORTS_PATH = "/hive/groups/qa/git-reports-history" GIT_REPO_PATH = "/data/git/kent.git" OUTPUT_DIR = f"/hive/users/{getpass.getuser()}/codeReview" MLQ_CONF_PATH = os.path.expanduser("~/.hg.conf") DEFAULT_CC = "browser-code-reviews-group@ucsc.edu" DEFAULT_ALERT_EMAIL = "browserqa-group@ucsc.edu" GMAIL_TOKEN_PATH = os.path.expanduser("~/.gmail_token.json") GMAIL_CREDS_PATH = os.path.expanduser("~/.gmail_credentials.json") GMAIL_SCOPES = [ 'https://www.googleapis.com/auth/gmail.send', ] CLAUDE_CLI = os.path.expanduser('~/.local/bin/claude') # Daily reviews get a timeout scaled to the batch size. A flat 600s limit timed # out repeatedly on 8-11 commit days, and since the retry reused the same limit # those authors' commits went unreviewed with no later window to catch them. +# The floor keeps small batches at the old flat 600s rather than shrinking them. DAILY_TIMEOUT_BASE = 300 DAILY_TIMEOUT_PER_COMMIT = 120 +DAILY_TIMEOUT_MIN = 600 DAILY_TIMEOUT_MAX = 2400 def load_config(): """Load API keys from ~/.hg.conf""" config = {} if not os.path.exists(MLQ_CONF_PATH): print(f"ERROR: Config file not found: {MLQ_CONF_PATH}") sys.exit(1) with open(MLQ_CONF_PATH, 'r') as f: for line in f: line = line.strip() if '=' in line and not line.startswith('#'): key, value = line.split('=', 1) config[key.strip()] = value.strip() @@ -1370,31 +1372,32 @@ prompt = build_daily_review_prompt(author_name, commits, window_label) # Save prompt to log_dir for debugging (cleaned up on success) safe_name = re.sub(r'[^a-zA-Z0-9]', '_', author_name) suffix = file_suffix or datetime.now().strftime('%Y%m%d') temp_files = [] prompt_file = os.path.join(log_dir, f".tmp_daily_prompt_{safe_name}_{suffix}.txt") with open(prompt_file, 'w') as f: f.write(prompt) temp_files.append(prompt_file) print(f" Prompt saved to: {prompt_file}") timeout = min(DAILY_TIMEOUT_MAX, - DAILY_TIMEOUT_BASE + DAILY_TIMEOUT_PER_COMMIT * len(commits)) + max(DAILY_TIMEOUT_MIN, + DAILY_TIMEOUT_BASE + DAILY_TIMEOUT_PER_COMMIT * len(commits))) print(f" Calling Claude CLI (timeout {timeout}s for {len(commits)} commit(s))...") raw_response = call_claude_cli(prompt, timeout=timeout, validator=validate_daily_review_output) error = detect_cli_failure(raw_response, validate_daily_review_output) # Save whatever we got back for debugging, even on failure. if raw_response: response_file = os.path.join(log_dir, f".tmp_daily_response_{safe_name}_{suffix}.txt") with open(response_file, 'w') as f: f.write(raw_response) temp_files.append(response_file) if error: print(f" WARNING: review failed - {error}") response = f"DAILY CODE REVIEW - {author_name}\n\nError: {error}\n"