#!/usr/bin/env bash # plan-refine — Run one ChatGPT evaluation iteration on a plan file via Oracle # Usage: plan-refine [options] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" PROMPTS_DIR="$SCRIPT_DIR/prompts" source "$SCRIPT_DIR/lib/frontmatter.sh" # Defaults MODEL_STRATEGY="current" ORACLE_MODEL="" DRY_RUN=false SKIP_CLIPBOARD=false BROWSER_TIMEOUT="1200s" PLAN_FILE="" usage() { cat <<'EOF' plan-refine — Send a plan to ChatGPT for adversarial review via Oracle Usage: plan-refine [options] After Oracle captures ChatGPT's feedback, the Claude integration prompt is copied to your clipboard. Paste it into Claude Code. Options: --dry-run Preview prompt without sending --model Force Oracle model (e.g. gpt-5.2-pro) --model-strategy Browser model strategy: current|select|ignore (default: current) --timeout Browser timeout (default: 1200s) --no-clipboard Skip copying integration prompt to clipboard --init Add plan frontmatter to file without running Oracle -h, --help Show this help EOF exit 0 } INIT_ONLY=false while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRY_RUN=true; shift ;; --model) ORACLE_MODEL="$2"; shift 2 ;; --model-strategy) MODEL_STRATEGY="$2"; shift 2 ;; --timeout) BROWSER_TIMEOUT="$2"; shift 2 ;; --no-clipboard) SKIP_CLIPBOARD=true; shift ;; --init) INIT_ONLY=true; shift ;; -h|--help) usage ;; -*) echo "Unknown option: $1" >&2; exit 2 ;; *) PLAN_FILE="$1"; shift ;; esac done if [[ -z "$PLAN_FILE" ]]; then echo "Error: No plan file specified" >&2 echo "Usage: plan-refine " >&2 exit 2 fi # Resolve to absolute path PLAN_FILE="$(cd "$(dirname "$PLAN_FILE")" && pwd)/$(basename "$PLAN_FILE")" if [[ ! -f "$PLAN_FILE" ]]; then echo "Error: Plan file not found: $PLAN_FILE" >&2 exit 1 fi # Ensure frontmatter exists if ! head -1 "$PLAN_FILE" | grep -q '^---$'; then echo "No frontmatter found. Initializing..." init_frontmatter "$PLAN_FILE" fi if ! is_plan_file "$PLAN_FILE"; then echo "Adding plan: true to frontmatter..." set_frontmatter "$PLAN_FILE" "plan" "true" fi if [[ "$INIT_ONLY" == "true" ]]; then init_frontmatter "$PLAN_FILE" echo "Frontmatter initialized for: $PLAN_FILE" exit 0 fi # Read current state ITERATION=$(get_frontmatter "$PLAN_FILE" "iteration" "0") TARGET=$(get_frontmatter "$PLAN_FILE" "target_iterations" "8") STATUS=$(get_frontmatter "$PLAN_FILE" "status" "drafting") NEXT_ITERATION=$((ITERATION + 1)) # Status check if [[ "$STATUS" == "ready" || "$STATUS" == "implementing" || "$STATUS" == "completed" ]]; then echo "Warning: Plan status is '$STATUS' — already past iteration phase." echo "Continue anyway? (y/N)" read -r confirm [[ "$confirm" != "y" && "$confirm" != "Y" ]] && exit 0 fi # Build feedback output path FEEDBACK_FILE="${PLAN_FILE%.md}.feedback-${NEXT_ITERATION}.md" # Read evaluation prompt EVAL_PROMPT=$(cat "$PROMPTS_DIR/chatgpt-eval.md") # Build Oracle model args ORACLE_MODEL_ARGS=() if [[ -n "$ORACLE_MODEL" ]]; then ORACLE_MODEL_ARGS+=(--model "$ORACLE_MODEL") fi echo "=== plan-refine ===" echo " Plan: $(basename "$PLAN_FILE")" echo " Status: $STATUS" echo " Iteration: $ITERATION -> $NEXT_ITERATION (target: $TARGET)" echo " Feedback: $(basename "$FEEDBACK_FILE")" echo "" if [[ "$DRY_RUN" == "true" ]]; then echo "=== DRY RUN — would send this to Oracle ===" echo "" echo "oracle --engine browser \\" echo " --browser-manual-login \\" echo " --browser-model-strategy $MODEL_STRATEGY \\" echo " --browser-timeout $BROWSER_TIMEOUT \\" [[ -n "$ORACLE_MODEL" ]] && echo " --model $ORACLE_MODEL \\" echo " -p \"$(echo "$EVAL_PROMPT" | head -1)...\" \\" echo " --file \"$PLAN_FILE\" \\" echo " --write-output \"$FEEDBACK_FILE\"" echo "" echo "=== FULL PROMPT ===" echo "$EVAL_PROMPT" exit 0 fi echo "Sending to ChatGPT via Oracle..." echo "(This may take a few minutes. Oracle will automate the browser.)" echo "" # Call Oracle oracle --engine browser \ --browser-manual-login \ --browser-model-strategy "$MODEL_STRATEGY" \ --browser-timeout "$BROWSER_TIMEOUT" \ "${ORACLE_MODEL_ARGS[@]}" \ -p "$EVAL_PROMPT" \ --file "$PLAN_FILE" \ --write-output "$FEEDBACK_FILE" ORACLE_EXIT=$? if [[ $ORACLE_EXIT -ne 0 ]]; then echo "Error: Oracle exited with code $ORACLE_EXIT" >&2 exit $ORACLE_EXIT fi if [[ ! -f "$FEEDBACK_FILE" ]]; then echo "Error: Expected feedback file not found: $FEEDBACK_FILE" >&2 exit 1 fi # Update frontmatter set_frontmatter "$PLAN_FILE" "iteration" "$NEXT_ITERATION" set_frontmatter "$PLAN_FILE" "updated" "$(date +%Y-%m-%d)" if [[ "$STATUS" == "drafting" ]]; then set_frontmatter "$PLAN_FILE" "status" "iterating" fi echo "" echo "Feedback saved to: $FEEDBACK_FILE" echo "" # Build and copy Claude integration prompt if [[ "$SKIP_CLIPBOARD" != "true" ]] && command -v pbcopy &>/dev/null; then INTEGRATE_PROMPT=$(cat "$PROMPTS_DIR/claude-integrate.md") CLIPBOARD_CONTENT="Read the plan at: $PLAN_FILE Read ChatGPT's feedback at: $FEEDBACK_FILE ${INTEGRATE_PROMPT} Write the updated plan back to: $PLAN_FILE" echo "$CLIPBOARD_CONTENT" | pbcopy echo "Claude integration prompt copied to clipboard." echo "Paste it into Claude Code to integrate the feedback." else echo "Next: Tell Claude to integrate the feedback." echo " Plan: $PLAN_FILE" echo " Feedback: $FEEDBACK_FILE" fi # Progress indicator if [[ $NEXT_ITERATION -ge $TARGET ]]; then echo "" echo "Target iterations reached ($NEXT_ITERATION/$TARGET)." echo "Consider: plan-refine $PLAN_FILE --init (to update status to 'splitting')" fi