diff --git a/bin/plan-refine b/bin/plan-refine index 2aa0997..9912853 100755 --- a/bin/plan-refine +++ b/bin/plan-refine @@ -1,6 +1,10 @@ #!/usr/bin/env bash -# plan-refine — Run one full ChatGPT + Claude integration iteration on a plan +# plan-refine — One-command plan iteration: ChatGPT review + Claude integration # Usage: plan-refine [options] +# +# Step 1: Assembles evaluation prompt + plan content, copies to clipboard. +# User pastes into ChatGPT, copies response, saves to feedback file. +# Step 2: Claude CLI integrates feedback back into the plan file. set -euo pipefail @@ -17,32 +21,29 @@ 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 +STEP="" usage() { cat <<'EOF' -plan-refine — One-command plan iteration: ChatGPT review + Claude integration +plan-refine — Semi-automated 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 +Workflow per iteration: + 1. plan-refine Copies ChatGPT prompt to clipboard + 2. Paste into ChatGPT, copy response, save to .feedback-N.md + 3. plan-refine --integrate Claude integrates feedback into plan 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) + --integrate Run Claude integration (Step 2) + --no-integrate Skip Claude integration, just update frontmatter + --claude-model Claude model for integration (default: your default) + --dry-run Preview what would happen --init Add plan frontmatter to file without running anything -h, --help Show this help EOF @@ -51,12 +52,10 @@ EOF while [[ $# -gt 0 ]]; do case "$1" in - --dry-run) DRY_RUN=true; shift ;; + --integrate) STEP="integrate"; shift ;; --no-integrate) NO_INTEGRATE=true; shift ;; - --model) ORACLE_MODEL="$2"; shift 2 ;; - --model-strategy) MODEL_STRATEGY="$2"; shift 2 ;; + --dry-run) DRY_RUN=true; shift ;; --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 ;; @@ -100,6 +99,14 @@ 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)) +PLAN_DIR=$(dirname "$PLAN_FILE") + +# Build paths +FEEDBACK_FILE="${PLAN_FILE%.md}.feedback-${NEXT_ITERATION}.md" + +# Read prompts +EVAL_PROMPT=$(cat "$PROMPTS_DIR/chatgpt-eval.md") +INTEGRATE_PROMPT=$(cat "$PROMPTS_DIR/claude-integrate.md") # Status check if [[ "$STATUS" == "ready" || "$STATUS" == "implementing" || "$STATUS" == "completed" ]]; then @@ -109,129 +116,56 @@ if [[ "$STATUS" == "ready" || "$STATUS" == "implementing" || "$STATUS" == "compl [[ "$confirm" != "y" && "$confirm" != "Y" ]] && exit 0 fi -# Build paths -FEEDBACK_FILE="${PLAN_FILE%.md}.feedback-${NEXT_ITERATION}.md" -PLAN_DIR=$(dirname "$PLAN_FILE") +# ────────────────────────────────────────────── +# Route to the right step +# ────────────────────────────────────────────── -# Read prompts -EVAL_PROMPT=$(cat "$PROMPTS_DIR/chatgpt-eval.md") -INTEGRATE_PROMPT=$(cat "$PROMPTS_DIR/claude-integrate.md") +if [[ "$STEP" == "integrate" ]]; then + # ────────────────────────────────────────── + # Step 2: Claude integration + # ────────────────────────────────────────── -# Build Oracle model args -ORACLE_MODEL_ARGS=() -if [[ -n "$ORACLE_MODEL" ]]; then - ORACLE_MODEL_ARGS+=(--model "$ORACLE_MODEL") -fi + # Find the latest feedback file + if [[ -f "$FEEDBACK_FILE" ]]; then + FOUND_FEEDBACK="$FEEDBACK_FILE" + else + # Search for any feedback file for the current iteration + FOUND_FEEDBACK=$(ls -t "${PLAN_FILE%.md}".feedback-*.md 2>/dev/null | head -1) + fi -# Build Claude model args -CLAUDE_MODEL_ARGS=() -if [[ -n "$CLAUDE_MODEL" ]]; then - CLAUDE_MODEL_ARGS+=(--model "$CLAUDE_MODEL") -fi + if [[ -z "$FOUND_FEEDBACK" || ! -f "$FOUND_FEEDBACK" ]]; then + echo "Error: No feedback file found." >&2 + echo "Expected: $FEEDBACK_FILE" >&2 + echo "" >&2 + echo "Run step 1 first: plan-refine $PLAN_FILE" >&2 + echo "Then save ChatGPT's response to: $FEEDBACK_FILE" >&2 + exit 1 + 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 "=== plan-refine --integrate ===" + echo " Plan: $(basename "$PLAN_FILE")" + echo " Feedback: $(basename "$FOUND_FEEDBACK")" + echo " Iteration: $ITERATION -> $NEXT_ITERATION (target: $TARGET)" 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" + + if [[ "$DRY_RUN" == "true" ]]; then + echo "=== DRY RUN ===" + echo "Would run:" echo " claude -p \\" echo " --allowedTools \"Read,Edit,Write\" \\" echo " --permission-mode acceptEdits \\" echo " --add-dir \"$PLAN_DIR\"" [[ -n "$CLAUDE_MODEL" ]] && echo " --model $CLAUDE_MODEL" + exit 0 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." + if [[ "$NO_INTEGRATE" == "true" ]]; then + echo "Skipping Claude integration (--no-integrate)." 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..." + echo "Claude integrating feedback into plan..." - CLAUDE_PROMPT="Read the original plan at: ${PLAN_FILE} -Read ChatGPT's feedback at: ${FEEDBACK_FILE} + CLAUDE_PROMPT="Read the original plan at: ${PLAN_FILE} +Read ChatGPT's feedback at: ${FOUND_FEEDBACK} ${INTEGRATE_PROMPT} @@ -241,39 +175,95 @@ Important instructions: - 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_MODEL_ARGS=() + if [[ -n "$CLAUDE_MODEL" ]]; then + CLAUDE_MODEL_ARGS+=(--model "$CLAUDE_MODEL") + fi - CLAUDE_EXIT=$? + claude -p "$CLAUDE_PROMPT" \ + --allowedTools "Read,Edit,Write" \ + --permission-mode acceptEdits \ + --add-dir "$PLAN_DIR" \ + "${CLAUDE_MODEL_ARGS[@]}" - 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 + CLAUDE_EXIT=$? + + if [[ $CLAUDE_EXIT -ne 0 ]]; then + echo "Error: Claude CLI exited with code $CLAUDE_EXIT" >&2 + echo "Feedback is still available at: $FOUND_FEEDBACK" >&2 + echo "You can integrate manually in Claude Code." >&2 + exit $CLAUDE_EXIT + fi + + echo "Integration complete. Plan updated." 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 -# ────────────────────────────────────────────── -# 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." + 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 + +else + # ────────────────────────────────────────── + # Step 1: Prepare ChatGPT prompt + # ────────────────────────────────────────── + + echo "=== plan-refine ===" + echo " Plan: $(basename "$PLAN_FILE")" + echo " Status: $STATUS" + echo " Iteration: $ITERATION -> $NEXT_ITERATION (target: $TARGET)" + echo "" + + # Use Oracle's --render --copy to bundle prompt + file content + if command -v oracle &>/dev/null; then + if [[ "$DRY_RUN" == "true" ]]; then + echo "=== DRY RUN ===" + echo "Would run: oracle --render --copy -p --file $PLAN_FILE" + echo "" + echo "=== PROMPT ===" + echo "$EVAL_PROMPT" + exit 0 + fi + + oracle --render --copy \ + -p "$EVAL_PROMPT" \ + --file "$PLAN_FILE" 2>/dev/null + + echo "ChatGPT prompt copied to clipboard (assembled by Oracle)." + else + # Fallback: manual clipboard assembly + if [[ "$DRY_RUN" == "true" ]]; then + echo "=== DRY RUN ===" + echo "Would copy evaluation prompt + plan content to clipboard." + exit 0 + fi + + PLAN_CONTENT=$(cat "$PLAN_FILE") + CLIPBOARD="${EVAL_PROMPT} + +--- + +${PLAN_CONTENT}" + echo "$CLIPBOARD" | pbcopy + echo "ChatGPT prompt copied to clipboard." + fi + + echo "" + echo "Next steps:" + echo " 1. Paste into ChatGPT (Cmd+V)" + echo " 2. Wait for response" + echo " 3. Copy ChatGPT's full response" + echo " 4. Save it to: $FEEDBACK_FILE" + echo " 5. Run: plan-refine $(basename "$PLAN_FILE") --integrate" fi