mirror of
https://github.com/Sea-Haven-Industries/security-review.git
synced 2026-09-30 10:23:14 +00:00
feat: add router-less cross-family reviewer CLI (cross_review.py)
Re-homes the archived orchestrator repo's GPT-4.1 cross_reviewer as a direct OpenAI SDK CLI: verbatim system prompt, same model id, ported 3-attempt exponential-backoff retry. Reads OPENAI_API_KEY from the environment or the gitignored repo-root .env. Lazy openai import so --help works without the package.
This commit is contained in:
parent
5408649943
commit
e061ef8f80
2 changed files with 143 additions and 3 deletions
139
cross_review.py
Executable file
139
cross_review.py
Executable file
|
|
@ -0,0 +1,139 @@
|
|||
#!/usr/bin/env python3
|
||||
"""cross_review.py — Sea Haven cross-family (GPT-4.1) review CLI.
|
||||
|
||||
Re-homed from the archived Sea-Haven-Industries/orchestrator repo's
|
||||
`cross_reviewer` agent. Router-less: one direct OpenAI SDK call, no langchain,
|
||||
no routing logic. This is the mandatory cross-family reviewer for IAM/policy
|
||||
and Lambda-handler-signature changes, and the reasoning backend for the
|
||||
sh-plan-review / sh-security-audit / sh-build-review gates.
|
||||
|
||||
Usage:
|
||||
python3 cross_review.py "Review this diff for breaking changes: <diff>"
|
||||
|
||||
Auth: reads OPENAI_API_KEY from the environment, falling back to the
|
||||
gitignored .env at the repo root. Never prints the key.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import time
|
||||
|
||||
# Model ID — single source of truth (ported from orchestrator/models.py).
|
||||
DEFAULT_MODEL = "gpt-4.1"
|
||||
TEMPERATURE = 0.2
|
||||
MAX_ATTEMPTS = 3
|
||||
|
||||
# System prompt ported verbatim from the orchestrator's cross_reviewer agent
|
||||
# (orchestrator/agents.py, CROSS_REVIEWER_PROMPT).
|
||||
CROSS_REVIEWER_PROMPT = """You are a cross-family code review agent. You provide an independent review perspective.
|
||||
Review the provided code for bugs, security issues, and improvements.
|
||||
Categorize findings as BLOCK, FIX, or NIT. Be concise.
|
||||
Focus on issues that might be missed by the primary development team."""
|
||||
|
||||
|
||||
def load_api_key() -> str:
|
||||
"""OPENAI_API_KEY from the environment, else hand-parsed from repo-root .env."""
|
||||
key = os.environ.get("OPENAI_API_KEY")
|
||||
if key:
|
||||
return key
|
||||
env_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")
|
||||
try:
|
||||
with open(env_path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
name, _, value = line.partition("=")
|
||||
if name.strip() == "OPENAI_API_KEY":
|
||||
return value.strip().strip("'\"")
|
||||
except OSError:
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
def run_review(task: str, model: str, api_key: str) -> str:
|
||||
"""One review call with retries on transient API errors (3 attempts,
|
||||
exponential backoff with jitter — ported from orchestrator/models.py
|
||||
with_retries)."""
|
||||
# Lazy import so --help works without the openai package installed.
|
||||
import openai
|
||||
|
||||
retriable = (
|
||||
openai.APIConnectionError,
|
||||
openai.RateLimitError,
|
||||
openai.InternalServerError,
|
||||
)
|
||||
client = openai.OpenAI(api_key=api_key)
|
||||
for attempt in range(1, MAX_ATTEMPTS + 1):
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model=model,
|
||||
temperature=TEMPERATURE,
|
||||
messages=[
|
||||
{"role": "system", "content": CROSS_REVIEWER_PROMPT},
|
||||
{"role": "user", "content": task},
|
||||
],
|
||||
)
|
||||
content = response.choices[0].message.content
|
||||
if not content:
|
||||
raise RuntimeError("model returned an empty review")
|
||||
return content
|
||||
except retriable as exc:
|
||||
if attempt == MAX_ATTEMPTS:
|
||||
raise
|
||||
delay = (2 ** (attempt - 1)) + random.uniform(0, 1)
|
||||
print(
|
||||
f"cross_review: transient API error ({type(exc).__name__}), "
|
||||
f"retrying in {delay:.1f}s (attempt {attempt}/{MAX_ATTEMPTS})",
|
||||
file=sys.stderr,
|
||||
)
|
||||
time.sleep(delay)
|
||||
raise RuntimeError("unreachable")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Cross-family GPT-4.1 review (direct OpenAI SDK, no router). "
|
||||
"Mandatory for IAM/policy and Lambda-handler-signature changes."
|
||||
)
|
||||
)
|
||||
parser.add_argument("task", help="review task: a diff, change description, or plan")
|
||||
parser.add_argument(
|
||||
"--model",
|
||||
default=DEFAULT_MODEL,
|
||||
help=f"OpenAI model id (default: {DEFAULT_MODEL})",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
api_key = load_api_key()
|
||||
if not api_key:
|
||||
print(
|
||||
"cross_review: OPENAI_API_KEY not set and not found in repo-root .env",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
|
||||
try:
|
||||
review = run_review(args.task, args.model, api_key)
|
||||
except ImportError:
|
||||
print(
|
||||
"cross_review: the 'openai' package is not installed "
|
||||
"(pip install -r requirements.txt)",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
except Exception as exc: # noqa: BLE001 — CLI boundary: report and exit nonzero
|
||||
print(
|
||||
f"cross_review: review failed: {type(exc).__name__}: {exc}", file=sys.stderr
|
||||
)
|
||||
return 1
|
||||
|
||||
print(review)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
# Path B headless agentic runner (run_headless.py). Scanners (semgrep, gitleaks,
|
||||
# Headless agentic runner (run_headless.py). Scanners (semgrep, gitleaks,
|
||||
# checkov, cfn-lint, pip-audit) and npm are external binaries, installed separately
|
||||
# (see README). The optional cross-model hook (ENABLE_XMODEL_HOOK=1) additionally
|
||||
# needs langchain-openai, intentionally not pinned here since it is off by default.
|
||||
# (see README).
|
||||
claude-agent-sdk
|
||||
# Cross-family reviewer CLI (cross_review.py) — direct OpenAI SDK, no langchain.
|
||||
openai
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue