diff --git a/codex-rs/review b/codex-rs/review index 9f38dfc915..fb55bd6f1b 100755 --- a/codex-rs/review +++ b/codex-rs/review @@ -61,8 +61,7 @@ def get_diff_text(base_ref: str, head_ref: str) -> str: return out -def study_files_for_reviewer(repo_root: str, reviewer: str) -> List[str]: - base = os.path.join(repo_root, "prs", reviewer, "study") +def study_files_in_dir(base: str) -> List[str]: if not os.path.isdir(base): return [] files = [] @@ -202,9 +201,28 @@ def main(): "Aggregates results, prints a progress bar and a summary of failed points." ), ) - parser.add_argument("reviewer", help="GitHub login whose studyguides to use (prs//study)") + parser.add_argument("reviewer", help="GitHub login whose studyguides to use (ignored if --study-dir is set)") parser.add_argument("--jobs", "-j", type=int, default=10, help="Parallel jobs (default: 10)") parser.add_argument("--base", default=None, help="Base ref to diff against (default: auto: origin/main or main)") + parser.add_argument( + "--study-dir", + "-S", + default=None, + help="Path to a folder containing PR-*-study.md files (overrides default prs//study)", + ) + parser.add_argument( + "--out-dir", + "-o", + default=None, + help="Directory where review JSON files should be written (default: sibling 'review' next to study-dir)", + ) + parser.add_argument( + "--limit", + "-n", + type=int, + default=None, + help="Use only the first N study guides after sorting (like head -n)", + ) parser.add_argument("--show-errors", action="store_true", help="Print per-guide errors encountered") args = parser.parse_args() @@ -213,18 +231,30 @@ def main(): repo_root = detect_repo_root() or os.getcwd() reviewer = args.reviewer - guides = study_files_for_reviewer(repo_root, reviewer) + study_dir = os.path.abspath(args.study_dir) if args.study_dir else os.path.join(repo_root, "prs", reviewer, "study") + guides = study_files_in_dir(study_dir) if not guides: - print(f"No studyguides found in prs/{reviewer}/study.", file=sys.stderr) + print(f"No studyguides found in {study_dir}.", file=sys.stderr) sys.exit(0) + total_available = len(guides) + if args.limit is not None: + if args.limit <= 0: + print("Error: --limit must be a positive integer.", file=sys.stderr) + sys.exit(2) + guides = guides[: args.limit] + branch = get_current_branch() base_ref = args.base or resolve_base_ref() diff_text = get_diff_text(base_ref, "HEAD") if not diff_text.strip(): print("Warning: empty diff vs base; all guides may be irrelevant or pass.", file=sys.stderr) - out_dir = os.path.join(repo_root, "prs", reviewer, "review") + if args.out_dir: + out_dir = os.path.abspath(args.out_dir) + else: + # Default: sibling 'review' next to the study folder + out_dir = os.path.join(os.path.dirname(study_dir), "review") os.makedirs(out_dir, exist_ok=True) total = len(guides) @@ -235,6 +265,10 @@ def main(): errors_all: List[Tuple[str, str]] = [] # (guide, error) print(f"Running {total} review(s) against {branch} vs {base_ref}…") + print(f"Study dir: {study_dir}") + print(f"Output dir: {out_dir}") + if args.limit is not None and args.limit < total_available: + print(f"Limit: using first {total} of {total_available} guides") print_progress(passed, completed, total, lock) def task(p: str):