aidp 0.21.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,7 +33,6 @@ module Aidp
33
33
  @provider_manager = Aidp::Harness::ProviderManager.new(@config_manager, prompt: @prompt)
34
34
  @conversation_history = []
35
35
  @user_input = {}
36
- @invalid_planning_responses = 0
37
36
  @verbose = verbose
38
37
  @debug_env = ENV["DEBUG"] == "1" || ENV["DEBUG"] == "2"
39
38
  end
@@ -138,7 +137,7 @@ module Aidp
138
137
  end
139
138
 
140
139
  response = call_provider_for_analysis(system_prompt, user_prompt)
141
- parsed = safe_parse_planning_response(response)
140
+ parsed = parse_planning_response(response)
142
141
  # Attach raw response for debug
143
142
  parsed[:raw_response] = response
144
143
  emit_verbose_raw_prompt(system_prompt, user_prompt, response)
@@ -378,53 +377,20 @@ module Aidp
378
377
  json_match = response_text.match(/```json\s*(\{.*?\})\s*```/m) ||
379
378
  response_text.match(/(\{.*\})/m)
380
379
 
381
- return {error: :invalid_format} unless json_match
382
- JSON.parse(json_match[1], symbolize_names: true)
383
- rescue JSON::ParserError
384
- {error: :invalid_format}
385
- end
386
-
387
- # Provides structured fallback sequence when provider keeps returning invalid planning JSON.
388
- # After exceeding sequence length, switches to manual entry question.
389
- def safe_parse_planning_response(response_text)
390
- parsed = parse_planning_response(response_text)
391
- return parsed unless parsed.is_a?(Hash) && parsed[:error] == :invalid_format
392
-
393
- @invalid_planning_responses += 1
394
- fallback_sequence = [
395
- "Provide scope (key features) and primary users.",
396
- "List 3-5 key functional requirements and any technical constraints.",
397
- "Supply any non-functional requirements (performance/security) or type 'skip'."
398
- ]
399
-
400
- if @invalid_planning_responses <= fallback_sequence.size
401
- {complete: false, questions: [fallback_sequence[@invalid_planning_responses - 1]], reasoning: "Fallback due to invalid provider response (format)", error: :fallback}
402
- else
403
- display_message("[ERROR] Provider returned invalid planning JSON #{@invalid_planning_responses} times. Enter combined plan details manually.", type: :error)
404
- {complete: false, questions: ["Enter plan details manually (features; users; requirements; constraints) or type 'skip'"], reasoning: "Manual recovery mode", error: :manual_recovery}
380
+ unless json_match
381
+ raise ConversationError, "Provider returned invalid format: no JSON found in response"
405
382
  end
383
+
384
+ JSON.parse(json_match[1], symbolize_names: true)
385
+ rescue JSON::ParserError => e
386
+ raise ConversationError, "Provider returned invalid JSON: #{e.message}"
406
387
  end
407
388
 
408
389
  def update_plan_from_answer(plan, question, answer)
409
390
  # Simple heuristic-based plan updates
410
391
  # In a more sophisticated implementation, use AI to categorize answers
411
392
 
412
- # IMPORTANT: Check manual recovery sentinel prompt first so it isn't misclassified
413
- # by broader keyword heuristics (e.g., it contains the word 'users').
414
- if question.start_with?("Enter plan details manually")
415
- unless answer.strip.downcase == "skip"
416
- parts = answer.split(/;|\|/).map(&:strip).reject(&:empty?)
417
- features, users, requirements, constraints = parts
418
- plan[:scope][:included] ||= []
419
- plan[:scope][:included] << features if features
420
- plan[:users][:personas] ||= []
421
- plan[:users][:personas] << users if users
422
- plan[:requirements][:functional] ||= []
423
- plan[:requirements][:functional] << requirements if requirements
424
- plan[:constraints][:technical] ||= []
425
- plan[:constraints][:technical] << constraints if constraints
426
- end
427
- elsif question.downcase.include?("scope") || question.downcase.include?("include")
393
+ if question.downcase.include?("scope") || question.downcase.include?("include")
428
394
  plan[:scope][:included] ||= []
429
395
  plan[:scope][:included] << answer
430
396
  elsif question.downcase.include?("user") || question.downcase.include?("who")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aidp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.1
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bart Agapinan
@@ -245,6 +245,7 @@ files:
245
245
  - lib/aidp/analyze/tree_sitter_grammar_loader.rb
246
246
  - lib/aidp/analyze/tree_sitter_scan.rb
247
247
  - lib/aidp/cli.rb
248
+ - lib/aidp/cli/devcontainer_commands.rb
248
249
  - lib/aidp/cli/enhanced_input.rb
249
250
  - lib/aidp/cli/first_run_wizard.rb
250
251
  - lib/aidp/cli/issue_importer.rb
@@ -354,6 +355,11 @@ files:
354
355
  - lib/aidp/providers/github_copilot.rb
355
356
  - lib/aidp/providers/opencode.rb
356
357
  - lib/aidp/rescue_logging.rb
358
+ - lib/aidp/safe_directory.rb
359
+ - lib/aidp/setup/devcontainer/backup_manager.rb
360
+ - lib/aidp/setup/devcontainer/generator.rb
361
+ - lib/aidp/setup/devcontainer/parser.rb
362
+ - lib/aidp/setup/devcontainer/port_manager.rb
357
363
  - lib/aidp/setup/wizard.rb
358
364
  - lib/aidp/skills.rb
359
365
  - lib/aidp/skills/composer.rb