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.
- checksums.yaml +4 -4
- data/README.md +69 -0
- data/lib/aidp/analyze/kb_inspector.rb +2 -3
- data/lib/aidp/analyze/progress.rb +5 -10
- data/lib/aidp/cli/mcp_dashboard.rb +1 -1
- data/lib/aidp/cli.rb +64 -29
- data/lib/aidp/config.rb +9 -14
- data/lib/aidp/execute/progress.rb +5 -8
- data/lib/aidp/execute/prompt_manager.rb +128 -1
- data/lib/aidp/execute/repl_macros.rb +555 -0
- data/lib/aidp/execute/work_loop_runner.rb +108 -1
- data/lib/aidp/harness/ai_decision_engine.rb +376 -0
- data/lib/aidp/harness/capability_registry.rb +273 -0
- data/lib/aidp/harness/config_loader.rb +2 -2
- data/lib/aidp/harness/config_schema.rb +305 -1
- data/lib/aidp/harness/configuration.rb +452 -0
- data/lib/aidp/harness/enhanced_runner.rb +23 -8
- data/lib/aidp/harness/error_handler.rb +12 -5
- data/lib/aidp/harness/provider_factory.rb +0 -2
- data/lib/aidp/harness/provider_manager.rb +4 -19
- data/lib/aidp/harness/runner.rb +9 -3
- data/lib/aidp/harness/state/persistence.rb +9 -10
- data/lib/aidp/harness/state/workflow_state.rb +3 -2
- data/lib/aidp/harness/state_manager.rb +33 -97
- data/lib/aidp/harness/status_display.rb +22 -12
- data/lib/aidp/harness/thinking_depth_manager.rb +335 -0
- data/lib/aidp/harness/ui/enhanced_tui.rb +3 -4
- data/lib/aidp/harness/user_interface.rb +11 -6
- data/lib/aidp/harness/zfc_condition_detector.rb +395 -0
- data/lib/aidp/init/devcontainer_generator.rb +274 -0
- data/lib/aidp/init/runner.rb +37 -10
- data/lib/aidp/init.rb +1 -0
- data/lib/aidp/jobs/background_runner.rb +7 -1
- data/lib/aidp/logger.rb +1 -1
- data/lib/aidp/message_display.rb +9 -2
- data/lib/aidp/prompt_optimization/context_composer.rb +286 -0
- data/lib/aidp/prompt_optimization/optimizer.rb +335 -0
- data/lib/aidp/prompt_optimization/prompt_builder.rb +309 -0
- data/lib/aidp/prompt_optimization/relevance_scorer.rb +256 -0
- data/lib/aidp/prompt_optimization/source_code_fragmenter.rb +308 -0
- data/lib/aidp/prompt_optimization/style_guide_indexer.rb +240 -0
- data/lib/aidp/prompt_optimization/template_indexer.rb +250 -0
- data/lib/aidp/provider_manager.rb +0 -2
- data/lib/aidp/providers/anthropic.rb +20 -1
- data/lib/aidp/providers/base.rb +4 -4
- data/lib/aidp/providers/codex.rb +1 -1
- data/lib/aidp/providers/cursor.rb +1 -1
- data/lib/aidp/providers/gemini.rb +1 -1
- data/lib/aidp/providers/github_copilot.rb +1 -1
- data/lib/aidp/providers/opencode.rb +1 -1
- data/lib/aidp/setup/wizard.rb +299 -4
- data/lib/aidp/skills/wizard/prompter.rb +2 -2
- data/lib/aidp/utils/devcontainer_detector.rb +166 -0
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/build_processor.rb +72 -6
- data/lib/aidp/watch/plan_generator.rb +1 -1
- data/lib/aidp/watch/repository_client.rb +15 -10
- data/lib/aidp/workflows/guided_agent.rb +2 -312
- data/lib/aidp/workstream_executor.rb +8 -2
- data/lib/aidp.rb +0 -1
- data/templates/aidp.yml.example +128 -0
- metadata +14 -2
- 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
|
-
@
|
|
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
|
|
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.
|
|
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
|
-
|
|
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 =
|
|
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
|
|
data/templates/aidp.yml.example
CHANGED
|
@@ -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.
|
|
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
|