#!/usr/bin/env bash # plan-refine — Run one full ChatGPT + Claude integration iteration on a plan # 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="" CLAUDE_MODEL="" DRY_RUN=false NO_INTEGRATE=false BROWSER_TIMEOUT="1200s" PLAN_FILE="" INIT_ONLY=false usage() { cat <<'EOF' plan-refine — One-command plan iteration: ChatGPT review + Claude integration Usage: plan-refine [options] Runs both steps automatically: 1. Oracle sends plan to ChatGPT for adversarial review 2. Claude CLI integrates feedback back into the plan file Options: --dry-run Preview what would run without executing --no-integrate Only run ChatGPT step, skip Claude integration --model Force Oracle/ChatGPT model (e.g. gpt-5.2-pro) --model-strategy Browser model strategy: current|select|ignore (default: current) --claude-model Claude model for integration (default: uses your default) --timeout Browser timeout (default: 1200s) --init Add plan frontmatter to file without running anything -h, --help Show this help EOF exit 0 } while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRY_RUN=true; shift ;; --no-integrate) NO_INTEGRATE=true; shift ;; --model) ORACLE_MODEL="$2"; shift 2 ;; --model-strategy) MODEL_STRATEGY="$2"; shift 2 ;; --claude-model) CLAUDE_MODEL="$2"; shift 2 ;; --timeout) BROWSER_TIMEOUT="$2"; shift 2 ;; --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 paths FEEDBACK_FILE="${PLAN_FILE%.md}.feedback-${NEXT_ITERATION}.md" PLAN_DIR=$(dirname "$PLAN_FILE") # Read prompts EVAL_PROMPT=$(cat "$PROMPTS_DIR/chatgpt-eval.md") INTEGRATE_PROMPT=$(cat "$PROMPTS_DIR/claude-integrate.md") # Build Oracle model args ORACLE_MODEL_ARGS=() if [[ -n "$ORACLE_MODEL" ]]; then ORACLE_MODEL_ARGS+=(--model "$ORACLE_MODEL") fi # Build Claude model args CLAUDE_MODEL_ARGS=() if [[ -n "$CLAUDE_MODEL" ]]; then CLAUDE_MODEL_ARGS+=(--model "$CLAUDE_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")" if [[ "$NO_INTEGRATE" == "true" ]]; then echo " Mode: ChatGPT review only (--no-integrate)" else echo " Mode: Full cycle (ChatGPT review + Claude integration)" fi echo "" if [[ "$DRY_RUN" == "true" ]]; then echo "=== DRY RUN ===" echo "" echo "Step 1: Oracle -> ChatGPT" 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 -c 80)...\" \\" echo " --file \"$PLAN_FILE\" \\" echo " --write-output \"$FEEDBACK_FILE\"" echo "" if [[ "$NO_INTEGRATE" != "true" ]]; then echo "Step 2: Claude CLI -> Integration" echo " claude -p \\" echo " --allowedTools \"Read,Edit,Write\" \\" echo " --permission-mode acceptEdits \\" echo " --add-dir \"$PLAN_DIR\"" [[ -n "$CLAUDE_MODEL" ]] && echo " --model $CLAUDE_MODEL" fi echo "" echo "=== ChatGPT PROMPT ===" echo "$EVAL_PROMPT" echo "" echo "=== Claude INTEGRATION PROMPT ===" echo "$INTEGRATE_PROMPT" exit 0 fi # ────────────────────────────────────────────── # Step 1: ChatGPT evaluation via Oracle # ────────────────────────────────────────────── echo "[Step 1/2] Sending to ChatGPT via Oracle..." echo "(Oracle will automate the browser. This may take a few minutes.)" echo "" 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 echo "" echo "ChatGPT feedback saved to: $FEEDBACK_FILE" # ────────────────────────────────────────────── # Step 2: Claude integration # ────────────────────────────────────────────── if [[ "$NO_INTEGRATE" == "true" ]]; then # Clipboard fallback for manual integration if command -v pbcopy &>/dev/null; then 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 "" echo "Integration prompt copied to clipboard. Paste into Claude Code." else echo "" echo "Skipped integration. Run manually:" echo " Plan: $PLAN_FILE" echo " Feedback: $FEEDBACK_FILE" fi else echo "" echo "[Step 2/2] Claude integrating feedback into plan..." CLAUDE_PROMPT="Read the original plan at: ${PLAN_FILE} Read ChatGPT's feedback at: ${FEEDBACK_FILE} ${INTEGRATE_PROMPT} Important instructions: - Write the updated plan back to: ${PLAN_FILE} - Preserve the YAML frontmatter block (between the --- delimiters) at the top unchanged. - Only modify the content below the frontmatter. - Do NOT output the plan to stdout. Write it directly to the file." claude -p "$CLAUDE_PROMPT" \ --allowedTools "Read,Edit,Write" \ --permission-mode acceptEdits \ --add-dir "$PLAN_DIR" \ "${CLAUDE_MODEL_ARGS[@]}" CLAUDE_EXIT=$? if [[ $CLAUDE_EXIT -ne 0 ]]; then echo "Error: Claude CLI exited with code $CLAUDE_EXIT" >&2 echo "Feedback is still available at: $FEEDBACK_FILE" echo "You can integrate manually in Claude Code." exit $CLAUDE_EXIT fi echo "Integration complete. Plan updated." 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 "=== Iteration $NEXT_ITERATION/$TARGET complete ===" if [[ $NEXT_ITERATION -ge $TARGET ]]; then echo "" echo "Target iterations reached. Plan may be ready for bead splitting." echo "To advance status: set 'status: splitting' in the frontmatter." fi