aidp 0.17.0 → 0.18.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +69 -0
  3. data/lib/aidp/analyze/kb_inspector.rb +2 -3
  4. data/lib/aidp/analyze/progress.rb +5 -10
  5. data/lib/aidp/cli/mcp_dashboard.rb +1 -1
  6. data/lib/aidp/cli.rb +64 -29
  7. data/lib/aidp/config.rb +9 -14
  8. data/lib/aidp/execute/progress.rb +5 -8
  9. data/lib/aidp/execute/prompt_manager.rb +128 -1
  10. data/lib/aidp/execute/repl_macros.rb +555 -0
  11. data/lib/aidp/execute/work_loop_runner.rb +108 -1
  12. data/lib/aidp/harness/ai_decision_engine.rb +376 -0
  13. data/lib/aidp/harness/capability_registry.rb +273 -0
  14. data/lib/aidp/harness/config_loader.rb +2 -2
  15. data/lib/aidp/harness/config_schema.rb +305 -1
  16. data/lib/aidp/harness/configuration.rb +452 -0
  17. data/lib/aidp/harness/enhanced_runner.rb +23 -8
  18. data/lib/aidp/harness/error_handler.rb +12 -5
  19. data/lib/aidp/harness/provider_factory.rb +0 -2
  20. data/lib/aidp/harness/provider_manager.rb +4 -19
  21. data/lib/aidp/harness/runner.rb +9 -3
  22. data/lib/aidp/harness/state/persistence.rb +9 -10
  23. data/lib/aidp/harness/state/workflow_state.rb +3 -2
  24. data/lib/aidp/harness/state_manager.rb +33 -97
  25. data/lib/aidp/harness/status_display.rb +22 -12
  26. data/lib/aidp/harness/thinking_depth_manager.rb +335 -0
  27. data/lib/aidp/harness/ui/enhanced_tui.rb +3 -4
  28. data/lib/aidp/harness/user_interface.rb +11 -6
  29. data/lib/aidp/harness/zfc_condition_detector.rb +395 -0
  30. data/lib/aidp/init/devcontainer_generator.rb +274 -0
  31. data/lib/aidp/init/runner.rb +37 -10
  32. data/lib/aidp/init.rb +1 -0
  33. data/lib/aidp/jobs/background_runner.rb +7 -1
  34. data/lib/aidp/logger.rb +1 -1
  35. data/lib/aidp/message_display.rb +9 -2
  36. data/lib/aidp/prompt_optimization/context_composer.rb +286 -0
  37. data/lib/aidp/prompt_optimization/optimizer.rb +335 -0
  38. data/lib/aidp/prompt_optimization/prompt_builder.rb +309 -0
  39. data/lib/aidp/prompt_optimization/relevance_scorer.rb +256 -0
  40. data/lib/aidp/prompt_optimization/source_code_fragmenter.rb +308 -0
  41. data/lib/aidp/prompt_optimization/style_guide_indexer.rb +240 -0
  42. data/lib/aidp/prompt_optimization/template_indexer.rb +250 -0
  43. data/lib/aidp/provider_manager.rb +0 -2
  44. data/lib/aidp/providers/anthropic.rb +20 -1
  45. data/lib/aidp/providers/base.rb +4 -4
  46. data/lib/aidp/providers/codex.rb +1 -1
  47. data/lib/aidp/providers/cursor.rb +1 -1
  48. data/lib/aidp/providers/gemini.rb +1 -1
  49. data/lib/aidp/providers/github_copilot.rb +1 -1
  50. data/lib/aidp/providers/opencode.rb +1 -1
  51. data/lib/aidp/setup/wizard.rb +299 -4
  52. data/lib/aidp/skills/wizard/prompter.rb +2 -2
  53. data/lib/aidp/utils/devcontainer_detector.rb +166 -0
  54. data/lib/aidp/version.rb +1 -1
  55. data/lib/aidp/watch/build_processor.rb +72 -6
  56. data/lib/aidp/watch/plan_generator.rb +1 -1
  57. data/lib/aidp/watch/repository_client.rb +15 -10
  58. data/lib/aidp/workflows/guided_agent.rb +2 -312
  59. data/lib/aidp/workstream_executor.rb +8 -2
  60. data/lib/aidp.rb +0 -1
  61. data/templates/aidp.yml.example +128 -0
  62. metadata +14 -2
  63. data/lib/aidp/providers/macos_ui.rb +0 -102
@@ -11,6 +11,16 @@ module Aidp
11
11
  # (works for private repositories) and falls back to public REST endpoints
12
12
  # when the CLI is unavailable.
13
13
  class RepositoryClient
14
+ # Binary availability checker for testing
15
+ class BinaryChecker
16
+ def gh_cli_available?
17
+ _stdout, _stderr, status = Open3.capture3("gh", "--version")
18
+ status.success?
19
+ rescue Errno::ENOENT
20
+ false
21
+ end
22
+ end
23
+
14
24
  attr_reader :owner, :repo
15
25
 
16
26
  def self.parse_issues_url(issues_url)
@@ -24,10 +34,11 @@ module Aidp
24
34
  end
25
35
  end
26
36
 
27
- def initialize(owner:, repo:, gh_available: nil)
37
+ def initialize(owner:, repo:, gh_available: nil, binary_checker: BinaryChecker.new)
28
38
  @owner = owner
29
39
  @repo = repo
30
- @gh_available = gh_available.nil? ? gh_cli_available? : gh_available
40
+ @binary_checker = binary_checker
41
+ @gh_available = gh_available.nil? ? @binary_checker.gh_cli_available? : gh_available
31
42
  end
32
43
 
33
44
  def gh_available?
@@ -56,13 +67,6 @@ module Aidp
56
67
 
57
68
  private
58
69
 
59
- def gh_cli_available?
60
- _stdout, _stderr, status = Open3.capture3("gh", "--version")
61
- status.success?
62
- rescue Errno::ENOENT
63
- false
64
- end
65
-
66
70
  def list_issues_via_gh(labels:, state:)
67
71
  json_fields = %w[number title labels updatedAt state url assignees]
68
72
  cmd = ["gh", "issue", "list", "--repo", full_repo, "--state", state, "--json", json_fields.join(",")]
@@ -158,7 +162,7 @@ module Aidp
158
162
  response.body
159
163
  end
160
164
 
161
- def create_pull_request_via_gh(title:, body:, head:, base:, issue_number:)
165
+ def create_pull_request_via_gh(title:, body:, head:, base:, issue_number:, draft: false)
162
166
  cmd = [
163
167
  "gh", "pr", "create",
164
168
  "--repo", full_repo,
@@ -168,6 +172,7 @@ module Aidp
168
172
  "--base", base
169
173
  ]
170
174
  cmd += ["--issue", issue_number.to_s] if issue_number
175
+ cmd += ["--draft"] if draft
171
176
 
172
177
  stdout, stderr, status = Open3.capture3(*cmd)
173
178
  raise "Failed to create PR via gh: #{stderr.strip}" unless status.success?
@@ -201,79 +201,10 @@ module Aidp
201
201
  goal
202
202
  end
203
203
 
204
- def analyze_user_intent(user_goal)
205
- display_message("\n🔍 Analyzing your request...", type: :info)
206
-
207
- # Build the system prompt with AIDP capabilities
208
- system_prompt = build_system_prompt
209
-
210
- # Build the user prompt
211
- user_prompt = build_analysis_prompt(user_goal)
212
-
213
- # Call provider to analyze intent
214
- response = call_provider_for_analysis(system_prompt, user_prompt)
215
-
216
- # Parse the response
217
- parse_recommendation(response)
218
- end
219
-
220
- def build_system_prompt
221
- # Try to load from project dir first, fall back to gem's docs
222
- capabilities_path = File.join(@project_dir, "docs", "AIDP_CAPABILITIES.md")
223
- unless File.exist?(capabilities_path)
224
- # Use the gem's copy
225
- gem_root = File.expand_path("../../..", __dir__)
226
- capabilities_path = File.join(gem_root, "docs", "AIDP_CAPABILITIES.md")
227
- end
228
-
229
- capabilities_doc = File.read(capabilities_path)
230
-
231
- <<~PROMPT
232
- You are an expert AI assistant helping users select the right AIDP workflow for their needs.
233
-
234
- Your role:
235
- 1. Understand what the user wants to accomplish
236
- 2. Match their intent to AIDP's capabilities
237
- 3. Recommend the most appropriate workflow
238
- 4. Explain why this workflow fits their needs
239
- 5. Identify if custom steps or templates are needed
240
-
241
- AIDP Capabilities Reference:
242
- #{capabilities_doc}
243
-
244
- Response Format:
245
- Provide a JSON response with:
246
- {
247
- "mode": "analyze|execute|hybrid",
248
- "workflow_key": "specific_workflow_key",
249
- "reasoning": "brief explanation of why this fits",
250
- "additional_steps": ["any", "custom", "steps", "if", "needed"],
251
- "questions": ["any", "clarifying", "questions"],
252
- "confidence": "high|medium|low"
253
- }
254
-
255
- Be concise to preserve the user's context window.
256
- PROMPT
257
- end
258
-
259
- def build_analysis_prompt(user_goal)
260
- <<~PROMPT
261
- User Goal: #{user_goal}
262
-
263
- Analyze this goal and recommend the most appropriate AIDP workflow.
264
- Consider:
265
- - Is this analysis or development?
266
- - What level of rigor is needed?
267
- - Are there any gaps in existing workflows?
268
-
269
- Provide your recommendation in JSON format.
270
- PROMPT
271
- end
272
-
273
204
  def call_provider_for_analysis(system_prompt, user_prompt)
274
205
  attempts = 0
275
206
  max_attempts = (@provider_manager.respond_to?(:configured_providers) ? @provider_manager.configured_providers.size : 2)
276
- max_attempts = 2 if max_attempts < 2 # at least one retry if a fallback exists
207
+ max_attempts = 2 if max_attempts < 2
277
208
 
278
209
  begin
279
210
  attempts += 1
@@ -283,7 +214,6 @@ module Aidp
283
214
  raise ConversationError, "No provider configured for guided workflow"
284
215
  end
285
216
 
286
- # Create provider instance using ProviderFactory
287
217
  provider_factory = Aidp::Harness::ProviderFactory.new(@config_manager)
288
218
  provider = provider_factory.create_provider(provider_name, prompt: @prompt)
289
219
 
@@ -292,7 +222,7 @@ module Aidp
292
222
  end
293
223
 
294
224
  combined_prompt = "#{system_prompt}\n\n#{user_prompt}"
295
- result = provider.send(prompt: combined_prompt)
225
+ result = provider.send_message(prompt: combined_prompt)
296
226
 
297
227
  if result.nil? || result.empty?
298
228
  raise ConversationError, "Provider request failed: empty response"
@@ -319,20 +249,6 @@ module Aidp
319
249
  end
320
250
  end
321
251
 
322
- def parse_recommendation(response_text)
323
- # Extract JSON from response (might be wrapped in markdown code blocks)
324
- json_match = response_text.match(/```json\s*(\{.*?\})\s*```/m) ||
325
- response_text.match(/(\{.*\})/m)
326
-
327
- unless json_match
328
- raise ConversationError, "Could not parse recommendation from response"
329
- end
330
-
331
- JSON.parse(json_match[1], symbolize_names: true)
332
- rescue JSON::ParserError => e
333
- raise ConversationError, "Invalid JSON in recommendation: #{e.message}"
334
- end
335
-
336
252
  def validate_provider_configuration!
337
253
  configured = @provider_manager.configured_providers
338
254
  if configured.nil? || configured.empty?
@@ -349,232 +265,6 @@ module Aidp
349
265
  end
350
266
  end
351
267
 
352
- def present_recommendation(recommendation)
353
- display_message("\n✨ Recommendation", type: :highlight)
354
- display_message("─" * 60, type: :muted)
355
-
356
- mode = recommendation[:mode].to_sym
357
- workflow_key = recommendation[:workflow_key].to_sym
358
-
359
- # Get workflow details
360
- workflow = Definitions.get_workflow(mode, workflow_key)
361
-
362
- unless workflow
363
- # Handle custom workflow or error
364
- return handle_custom_workflow(recommendation)
365
- end
366
-
367
- # Display the recommendation
368
- display_message("Mode: #{mode.to_s.capitalize}", type: :info)
369
- display_message("Workflow: #{workflow[:name]}", type: :info)
370
- display_message("\n#{workflow[:description]}", type: :muted)
371
- display_message("\nReasoning: #{recommendation[:reasoning]}\n", type: :info)
372
-
373
- # Show what's included
374
- display_message("This workflow includes:", type: :highlight)
375
- workflow[:details].each do |detail|
376
- display_message(" • #{detail}", type: :info)
377
- end
378
-
379
- # Handle additional steps if needed
380
- steps = workflow[:steps]
381
- if recommendation[:additional_steps]&.any?
382
- display_message("\nAdditional custom steps recommended:", type: :highlight)
383
- recommendation[:additional_steps].each do |step|
384
- display_message(" • #{step}", type: :info)
385
- end
386
- steps = workflow[:steps] + recommendation[:additional_steps]
387
- end
388
-
389
- # Ask for confirmation
390
- display_message("")
391
- confirmed = @prompt.yes?("Does this workflow fit your needs?")
392
-
393
- if confirmed
394
- {
395
- mode: mode,
396
- workflow_key: workflow_key,
397
- workflow_type: workflow_key,
398
- steps: steps,
399
- user_input: @user_input,
400
- workflow: workflow
401
- }
402
- else
403
- # Offer alternatives
404
- offer_alternatives(mode)
405
- end
406
- end
407
-
408
- def handle_custom_workflow(recommendation)
409
- display_message("\n💡 Custom Workflow Needed", type: :highlight)
410
- display_message("The AI recommends creating a custom workflow:\n", type: :info)
411
- display_message(recommendation[:reasoning], type: :muted)
412
-
413
- if recommendation[:questions]&.any?
414
- display_message("\nLet me gather some more information:\n", type: :highlight)
415
- recommendation[:questions].each do |question|
416
- answer = @prompt.ask(question)
417
- @user_input[question.downcase.gsub(/\s+/, "_").to_sym] = answer
418
- end
419
- end
420
-
421
- # Let user select from available steps
422
- mode = recommendation[:mode].to_sym
423
- display_message("\nLet's build a custom workflow by selecting specific steps:", type: :info)
424
-
425
- steps = select_custom_steps(mode, recommendation[:additional_steps])
426
-
427
- {
428
- mode: mode,
429
- workflow_key: :custom,
430
- workflow_type: :custom,
431
- steps: steps,
432
- user_input: @user_input,
433
- workflow: {
434
- name: "Custom Workflow",
435
- description: recommendation[:reasoning],
436
- details: steps
437
- }
438
- }
439
- end
440
-
441
- def select_custom_steps(mode, suggested_steps = [])
442
- # Get available steps for the mode
443
- spec = case mode
444
- when :analyze
445
- Aidp::Analyze::Steps::SPEC
446
- when :execute
447
- Aidp::Execute::Steps::SPEC
448
- when :hybrid
449
- # Combine both
450
- Aidp::Analyze::Steps::SPEC.merge(Aidp::Execute::Steps::SPEC)
451
- else
452
- {}
453
- end
454
-
455
- step_choices = spec.map do |step_key, step_spec|
456
- {
457
- name: "#{step_key} - #{step_spec["description"]}",
458
- value: step_key
459
- }
460
- end
461
-
462
- # Pre-select suggested steps
463
- default_indices = suggested_steps.map do |step|
464
- step_choices.index { |choice| choice[:value].to_s == step.to_s }
465
- end.compact
466
-
467
- selected_steps = @prompt.multi_select(
468
- "Select steps for your custom workflow:",
469
- step_choices,
470
- default: default_indices,
471
- per_page: 20
472
- )
473
-
474
- selected_steps.empty? ? suggested_steps : selected_steps
475
- end
476
-
477
- def offer_alternatives(current_mode)
478
- display_message("\n🔄 Let's find a better fit", type: :highlight)
479
-
480
- choices = [
481
- {name: "Try a different #{current_mode} workflow", value: :different_workflow},
482
- {name: "Switch to a different mode", value: :different_mode},
483
- {name: "Build a custom workflow", value: :custom},
484
- {name: "Start over", value: :restart}
485
- ]
486
-
487
- choice = @prompt.select("What would you like to do?", choices)
488
-
489
- case choice
490
- when :different_workflow
491
- select_manual_workflow(current_mode)
492
- when :different_mode
493
- # Let user pick mode manually then workflow
494
- new_mode = @prompt.select(
495
- "Select mode:",
496
- {
497
- "🔬 Analyze Mode" => :analyze,
498
- "🏗️ Execute Mode" => :execute,
499
- "🔀 Hybrid Mode" => :hybrid
500
- }
501
- )
502
- select_manual_workflow(new_mode)
503
- when :custom
504
- select_custom_steps(current_mode)
505
- when :restart
506
- select_workflow # Recursive call to start over
507
- end
508
- end
509
-
510
- def select_manual_workflow(mode)
511
- workflows = Definitions.workflows_for_mode(mode)
512
-
513
- choices = workflows.map do |key, workflow|
514
- {
515
- name: "#{workflow[:icon]} #{workflow[:name]} - #{workflow[:description]}",
516
- value: key
517
- }
518
- end
519
-
520
- selected_key = @prompt.select("Choose a workflow:", choices, per_page: 15)
521
- workflow = workflows[selected_key]
522
-
523
- {
524
- mode: mode,
525
- workflow_key: selected_key,
526
- workflow_type: selected_key,
527
- steps: workflow[:steps],
528
- user_input: @user_input,
529
- workflow: workflow
530
- }
531
- end
532
-
533
- def collect_workflow_details(workflow_selection)
534
- # Collect additional information based on mode
535
- case workflow_selection[:mode]
536
- when :execute
537
- collect_execute_details
538
- when :analyze
539
- # Analyze mode typically doesn't need much user input
540
- @user_input[:analysis_goal] = @user_input[:original_goal]
541
- when :hybrid
542
- collect_execute_details # Hybrid often needs project details
543
- end
544
-
545
- # Update the workflow selection with collected input
546
- workflow_selection[:user_input] = @user_input
547
- end
548
-
549
- def collect_execute_details
550
- return if @user_input[:project_description] # Already collected
551
-
552
- display_message("\n📝 Project Information", type: :highlight)
553
- display_message("Let me gather some details for the PRD:\n", type: :info)
554
-
555
- @user_input[:project_description] = @prompt.ask(
556
- "Describe what you're building (can reference your original goal):",
557
- default: @user_input[:original_goal]
558
- )
559
-
560
- @user_input[:tech_stack] = @prompt.ask(
561
- "Tech stack (e.g., Ruby/Rails, Node.js, Python)? [optional]",
562
- required: false
563
- )
564
-
565
- @user_input[:target_users] = @prompt.ask(
566
- "Who will use this? [optional]",
567
- required: false
568
- )
569
-
570
- @user_input[:success_criteria] = @prompt.ask(
571
- "How will you measure success? [optional]",
572
- required: false
573
- )
574
- end
575
-
576
- # Plan-then-execute helper methods
577
-
578
268
  def build_planning_system_prompt
579
269
  <<~PROMPT
580
270
  You are a planning assistant helping gather requirements through clarifying questions.
@@ -25,11 +25,17 @@ module Aidp
25
25
  keyword_init: true
26
26
  )
27
27
 
28
- def initialize(project_dir: Dir.pwd, max_concurrent: 3)
28
+ # @param project_dir [String] root directory of the project
29
+ # @param max_concurrent [Integer] maximum number of concurrent workstreams (thread pool size)
30
+ # @param runner_factory [Proc] factory that builds a harness runner. Signature: (path, mode, options) => object responding to #run
31
+ def initialize(project_dir: Dir.pwd, max_concurrent: 3, runner_factory: nil)
29
32
  @project_dir = project_dir
30
33
  @max_concurrent = max_concurrent
31
34
  @results = Concurrent::Hash.new
32
35
  @start_times = Concurrent::Hash.new
36
+ @runner_factory = runner_factory || lambda do |path, mode, options|
37
+ Aidp::Harness::Runner.new(path, mode, options)
38
+ end
33
39
  end
34
40
 
35
41
  # Execute multiple workstreams in parallel
@@ -120,7 +126,7 @@ module Aidp
120
126
  Dir.chdir(workstream[:path])
121
127
 
122
128
  # Execute harness
123
- runner = Aidp::Harness::Runner.new(
129
+ runner = @runner_factory.call(
124
130
  workstream[:path],
125
131
  options[:mode] || :execute,
126
132
  options
data/lib/aidp.rb CHANGED
@@ -25,7 +25,6 @@ require_relative "aidp/providers/base"
25
25
  require_relative "aidp/providers/cursor"
26
26
  require_relative "aidp/providers/anthropic"
27
27
  require_relative "aidp/providers/gemini"
28
- require_relative "aidp/providers/macos_ui"
29
28
  # Supervised providers removed - using direct execution model
30
29
  require_relative "aidp/provider_manager"
31
30
 
@@ -123,6 +123,93 @@ harness:
123
123
  api_key_rotation: false # Enable API key rotation
124
124
  audit_logging: true # Enable audit logging
125
125
 
126
+ # Thinking Depth Configuration
127
+ # Controls model selection based on task complexity
128
+ thinking:
129
+ # Default tier for new requests (mini, standard, thinking, pro, max)
130
+ default_tier: "mini"
131
+
132
+ # Maximum tier allowed (prevents excessive costs)
133
+ max_tier: "max"
134
+
135
+ # Enable automatic tier escalation on failures
136
+ auto_escalate: true
137
+
138
+ # Number of failures before escalating to next tier
139
+ escalation_threshold: 2
140
+
141
+ # Per-operation tier overrides (optional)
142
+ overrides:
143
+ # Example: Use mini tier for simple decisions
144
+ # decision.condition_detection: mini
145
+ # decision.error_classification: mini
146
+ # decision.completion_detection: mini
147
+
148
+ # Zero Framework Cognition (ZFC) Configuration
149
+ # Delegates semantic analysis to AI instead of pattern matching
150
+ zfc:
151
+ # Master toggle for ZFC features
152
+ enabled: false # Set to true to enable (experimental)
153
+
154
+ # Fallback to legacy pattern matching if AI fails
155
+ fallback_to_legacy: true
156
+
157
+ # Individual decision types (can be toggled separately)
158
+ decisions:
159
+ # Condition detection (replaces regex patterns)
160
+ condition_detection:
161
+ enabled: false
162
+ tier: "mini" # AI tier to use
163
+ cache_ttl: null # Cache duration in seconds (null = no cache)
164
+ confidence_threshold: 0.7 # Minimum confidence to accept result
165
+
166
+ # Error classification (determines if retryable)
167
+ error_classification:
168
+ enabled: false
169
+ tier: "mini"
170
+ cache_ttl: null
171
+ confidence_threshold: 0.7
172
+
173
+ # Completion detection (replaces keyword matching)
174
+ completion_detection:
175
+ enabled: false
176
+ tier: "mini"
177
+ cache_ttl: null
178
+ confidence_threshold: 0.8
179
+
180
+ # Provider selection (replaces load calculation formula)
181
+ provider_selection:
182
+ enabled: false
183
+ tier: "mini"
184
+ cache_ttl: 300 # Cache for 5 minutes
185
+ confidence_threshold: 0.7
186
+
187
+ # Tier escalation decision (replaces heuristic thresholds)
188
+ tier_escalation:
189
+ enabled: false
190
+ tier: "mini"
191
+ cache_ttl: null
192
+ confidence_threshold: 0.7
193
+
194
+ # Workflow routing (replaces pattern matching)
195
+ workflow_routing:
196
+ enabled: false
197
+ tier: "mini"
198
+ cache_ttl: 60 # Cache for 1 minute
199
+ confidence_threshold: 0.7
200
+
201
+ # Cost controls for ZFC
202
+ cost_limits:
203
+ max_daily_cost: 5.00 # Maximum daily ZFC cost in USD
204
+ max_cost_per_decision: 0.01 # Maximum cost per decision
205
+ alert_threshold: 0.8 # Alert at 80% of budget
206
+
207
+ # A/B testing configuration
208
+ ab_testing:
209
+ enabled: false # Enable A/B testing
210
+ sample_rate: 0.1 # Test 10% of decisions
211
+ log_comparisons: true # Log ZFC vs legacy comparisons
212
+
126
213
  # Provider configurations
127
214
  providers:
128
215
  # Cursor provider (subscription-based)
@@ -580,6 +667,47 @@ users:
580
667
  cursor:
581
668
  priority: 2
582
669
 
670
+ # Devcontainer configuration (experimental)
671
+ # Controls behavior when running inside a development container
672
+ devcontainer:
673
+ # Enable automatic detection of devcontainer environment
674
+ enabled: true
675
+
676
+ # Run agents with full permissions when in devcontainer
677
+ # This allows more dangerous filesystem operations in the sandboxed environment
678
+ # Only applies when AIDP detects it's running in a container
679
+ full_permissions_when_in_devcontainer: false
680
+
681
+ # Override detection (useful for testing or forcing behavior)
682
+ # Set to true/false to force detection result, or null for auto-detection
683
+ force_detection: null
684
+
685
+ # Permissions to grant when in devcontainer
686
+ permissions:
687
+ # Allow dangerous filesystem operations
688
+ dangerous_filesystem_ops: false
689
+
690
+ # Skip permission checks for specific providers
691
+ # Provider-specific flags will be added automatically
692
+ skip_permission_checks:
693
+ - "claude" # Adds --dangerously-skip-permissions for Claude Code
694
+ # - "cursor"
695
+ # - "gemini"
696
+
697
+ # Container-specific settings
698
+ settings:
699
+ # Increase timeouts in container (may be slower)
700
+ timeout_multiplier: 1.5
701
+
702
+ # Enable more verbose logging in devcontainer
703
+ verbose_logging: true
704
+
705
+ # Network allowlist (for firewall configuration)
706
+ # These will be added to init-firewall.sh if using AIDP's devcontainer
707
+ allowed_domains: []
708
+ # - "api.example.com"
709
+ # - "registry.example.com"
710
+
583
711
  # Configuration tips:
584
712
  # - Set max_tokens based on your API plan limits
585
713
  # - Use default_flags to customize provider behavior
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.17.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bart Agapinan
@@ -280,6 +280,8 @@ files:
280
280
  - lib/aidp/execute/work_loop_state.rb
281
281
  - lib/aidp/execute/work_loop_unit_scheduler.rb
282
282
  - lib/aidp/execute/workflow_selector.rb
283
+ - lib/aidp/harness/ai_decision_engine.rb
284
+ - lib/aidp/harness/capability_registry.rb
283
285
  - lib/aidp/harness/completion_checker.rb
284
286
  - lib/aidp/harness/condition_detector.rb
285
287
  - lib/aidp/harness/config_loader.rb
@@ -305,6 +307,7 @@ files:
305
307
  - lib/aidp/harness/state_manager.rb
306
308
  - lib/aidp/harness/status_display.rb
307
309
  - lib/aidp/harness/test_runner.rb
310
+ - lib/aidp/harness/thinking_depth_manager.rb
308
311
  - lib/aidp/harness/ui/base.rb
309
312
  - lib/aidp/harness/ui/enhanced_tui.rb
310
313
  - lib/aidp/harness/ui/enhanced_workflow_selector.rb
@@ -325,13 +328,22 @@ files:
325
328
  - lib/aidp/harness/ui/status_widget.rb
326
329
  - lib/aidp/harness/ui/workflow_controller.rb
327
330
  - lib/aidp/harness/user_interface.rb
331
+ - lib/aidp/harness/zfc_condition_detector.rb
328
332
  - lib/aidp/init.rb
333
+ - lib/aidp/init/devcontainer_generator.rb
329
334
  - lib/aidp/init/doc_generator.rb
330
335
  - lib/aidp/init/project_analyzer.rb
331
336
  - lib/aidp/init/runner.rb
332
337
  - lib/aidp/jobs/background_runner.rb
333
338
  - lib/aidp/logger.rb
334
339
  - lib/aidp/message_display.rb
340
+ - lib/aidp/prompt_optimization/context_composer.rb
341
+ - lib/aidp/prompt_optimization/optimizer.rb
342
+ - lib/aidp/prompt_optimization/prompt_builder.rb
343
+ - lib/aidp/prompt_optimization/relevance_scorer.rb
344
+ - lib/aidp/prompt_optimization/source_code_fragmenter.rb
345
+ - lib/aidp/prompt_optimization/style_guide_indexer.rb
346
+ - lib/aidp/prompt_optimization/template_indexer.rb
335
347
  - lib/aidp/provider_manager.rb
336
348
  - lib/aidp/providers/anthropic.rb
337
349
  - lib/aidp/providers/base.rb
@@ -339,7 +351,6 @@ files:
339
351
  - lib/aidp/providers/cursor.rb
340
352
  - lib/aidp/providers/gemini.rb
341
353
  - lib/aidp/providers/github_copilot.rb
342
- - lib/aidp/providers/macos_ui.rb
343
354
  - lib/aidp/providers/opencode.rb
344
355
  - lib/aidp/rescue_logging.rb
345
356
  - lib/aidp/setup/wizard.rb
@@ -360,6 +371,7 @@ files:
360
371
  - lib/aidp/storage/json_storage.rb
361
372
  - lib/aidp/tooling_detector.rb
362
373
  - lib/aidp/util.rb
374
+ - lib/aidp/utils/devcontainer_detector.rb
363
375
  - lib/aidp/version.rb
364
376
  - lib/aidp/watch.rb
365
377
  - lib/aidp/watch/build_processor.rb