@startuml patcher-pipeline !theme plain title AI Patch Generation and Application Pipeline start :Receive source file + target file + instruction; :Build prompt with: - Source file diff (staged changes) - Source file full content - Target file current content - Generation instructions from rules - Model hint (fast/quality) if specified; partition "Multi-Provider Fallback" { :Try Provider 1: Claude CLI; if (Claude returned output?) then (yes) if (Output contains\n"API Error: Overloaded"?) then (yes) :Raise PatchGenerationError\n"Claude API is overloaded"; stop endif if (Output contains diff markers?) then (yes) :Success! Continue to extraction; else (no - non-diff response) :Log: "Claude non-diff output"; :Try Provider 2: Codex CLI; if (Codex returned output?) then (yes) :Parse JSON response\nextract agent_message; if (Parsed text contains diff?) then (yes) :Success! Continue to extraction; else (no - exit code 1) :Log: "Codex exited with 1"; :Try Provider 3: Gemini CLI; if (Gemini returned output?) then (yes) if (Gemini returned sentinel?) then (yes) :Log: "No changes needed"; stop else (has diff) :Success! Continue to extraction; endif else (no) :Raise "All providers failed"; stop endif endif else (no) :Raise "All providers failed"; stop endif endif else (no - command failed) :Raise "Provider 1 command failed"; stop endif } :Save raw output to\n.git/ai-rules-debug/*.raw.out; if (Output contains\n<<>>?) then (yes) :Extract content between\nSTART and END markers; else (no) if (Output contains\n"diff --git"?) then (yes) :Extract from\n"diff --git" onward; else (no) :Raise "AI output did not contain a diff"; stop endif endif :Save to *.clean.diff; :Sanitize patch: - Remove "index ..." lines - Remove "similarity index" lines - Keep only diff content; :Save to *.sanitized.diff; if (New file and missing\n"new file mode"?) then (yes) :Add "new file mode 100644" header; endif :Save to *.final.diff; if (Patch is empty?) then (yes) :Raise "AI returned empty patch"; stop endif :Try git apply -p1 --index --check; if (Check succeeded?) then (yes) :git apply -p1 --index; :Success!; stop endif :Try git apply -p1 --index --3way\n--recount --whitespace=nowarn; if (3-way succeeded?) then (yes) :Applied with 3-way merge; :Success!; stop endif if (Is new file?) then (yes) :Try git apply -p1 (without --index); if (Succeeded?) then (yes) :git add target file; :Success!; stop endif endif :Raise "Failed to apply patch\n(strict and 3-way both failed)"; stop note right **AI Provider Configuration:** config/ai.yml defines fallback chains: - command_chain (default) - command_chain_fast (model_hint: fast) - command_chain_quality (model_hint: quality) **Provider Details:** 1. Claude: claude -p (auto-selects subagent) 2. Codex: codex exec --model gpt-5 --json 3. Gemini: gemini --model gemini-2.5-flash **Debug Artifacts Location:** .git/ai-rules-debug/ Files saved: - *.raw.out (full AI response) - *.clean.diff (extracted patch) - *.sanitized.diff (cleaned patch) - *.final.diff (applied patch) Filename format: {output_path_with_underscores}-{pid}.{ext} end note @enduml