Class: Aidp::Watch::PlanGenerator

Inherits:
Object
  • Object
show all
Includes:
MessageDisplay
Defined in:
lib/aidp/watch/plan_generator.rb

Overview

Generates implementation plans for issues during watch mode. Attempts to use a configured provider for high quality output and falls back to a deterministic heuristic plan when no provider can be invoked.

Constant Summary collapse

PROVIDER_PROMPT =
"You are AIDP's planning specialist. Read the GitHub issue and existing comments.\nProduce a concise implementation contract describing the plan for the aidp agent.\nRespond in JSON with the following shape (no extra text, no code fences):\n{\n  \"plan_summary\": \"one paragraph summary of what will be implemented\",\n  \"plan_tasks\": [\"task 1\", \"task 2\", \"...\"],\n  \"clarifying_questions\": [\"question 1\", \"question 2\"]\n}\nFocus on concrete engineering tasks. Ensure questions are actionable.\n"

Constants included from MessageDisplay

MessageDisplay::COLOR_MAP

Instance Method Summary collapse

Methods included from MessageDisplay

#display_message, included, #message_display_prompt

Constructor Details

#initialize(provider_name: nil, verbose: false) ⇒ PlanGenerator

Returns a new instance of PlanGenerator.



29
30
31
32
33
# File 'lib/aidp/watch/plan_generator.rb', line 29

def initialize(provider_name: nil, verbose: false)
  @provider_name = provider_name
  @verbose = verbose
  @providers_attempted = []
end

Instance Method Details

#generate(issue) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/aidp/watch/plan_generator.rb', line 35

def generate(issue)
  Aidp.log_debug("plan_generator", "generate.start", provider: @provider_name, issue: issue[:number])

  # Try providers in fallback chain order
  providers_to_try = build_provider_fallback_chain
  Aidp.log_debug("plan_generator", "fallback_chain", providers: providers_to_try, count: providers_to_try.size)

  providers_to_try.each do |provider_name|
    next if @providers_attempted.include?(provider_name)

    Aidp.log_debug("plan_generator", "trying_provider", provider: provider_name, attempted: @providers_attempted)

    provider = resolve_provider(provider_name)
    unless provider
      Aidp.log_debug("plan_generator", "provider_unavailable", provider: provider_name, reason: "not resolved")
      @providers_attempted << provider_name
      next
    end

    begin
      Aidp.log_info("plan_generator", "generate_with_provider", provider: provider_name, issue: issue[:number])
      result = generate_with_provider(provider, issue, provider_name)
      if result
        Aidp.log_info("plan_generator", "generation_success", provider: provider_name, issue: issue[:number])
        return result
      end

      # Provider returned nil - try next provider
      Aidp.log_warn("plan_generator", "provider_returned_nil", provider: provider_name)
      @providers_attempted << provider_name
    rescue => e
      # Log error and try next provider in chain
      Aidp.log_warn("plan_generator", "provider_failed", provider: provider_name, error: e.message, error_class: e.class.name)
      @providers_attempted << provider_name
    end
  end

  # All providers exhausted - silently fail without heuristic fallback
  Aidp.log_warn("plan_generator", "all_providers_exhausted", attempted: @providers_attempted, result: "failed")
  display_message("⚠️  All providers unavailable or failed. Unable to generate plan.", type: :warn)
  nil
rescue => e
  Aidp.log_error("plan_generator", "generation_failed_unexpectedly", error: e.message, backtrace: e.backtrace&.first(3))
  display_message("⚠️  Plan generation failed unexpectedly (#{e.message}).", type: :warn)
  nil
end