aidp 0.25.0 → 0.26.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 +45 -6
- data/lib/aidp/analyze/error_handler.rb +11 -0
- data/lib/aidp/execute/work_loop_runner.rb +225 -55
- data/lib/aidp/harness/config_loader.rb +20 -11
- data/lib/aidp/harness/config_schema.rb +30 -8
- data/lib/aidp/harness/configuration.rb +73 -2
- data/lib/aidp/harness/filter_strategy.rb +45 -0
- data/lib/aidp/harness/generic_filter_strategy.rb +63 -0
- data/lib/aidp/harness/output_filter.rb +136 -0
- data/lib/aidp/harness/provider_manager.rb +18 -3
- data/lib/aidp/harness/rspec_filter_strategy.rb +82 -0
- data/lib/aidp/harness/test_runner.rb +165 -27
- data/lib/aidp/harness/ui/enhanced_tui.rb +4 -1
- data/lib/aidp/logger.rb +35 -5
- data/lib/aidp/message_display.rb +46 -0
- data/lib/aidp/safe_directory.rb +10 -3
- data/lib/aidp/storage/csv_storage.rb +9 -3
- data/lib/aidp/storage/file_manager.rb +8 -2
- data/lib/aidp/storage/json_storage.rb +9 -3
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/build_processor.rb +40 -1
- data/lib/aidp/watch/change_request_processor.rb +659 -0
- data/lib/aidp/watch/plan_processor.rb +71 -8
- data/lib/aidp/watch/repository_client.rb +85 -20
- data/lib/aidp/watch/runner.rb +37 -0
- data/lib/aidp/watch/state_store.rb +46 -1
- data/lib/aidp/workstream_executor.rb +5 -2
- data/lib/aidp.rb +4 -0
- data/templates/aidp.yml.example +53 -0
- metadata +6 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0b4770edc850e936b3201ec532cdd369f7fd881ff79dd10e24407c6453b8cb22
|
|
4
|
+
data.tar.gz: d7d2640aa63d2c25afbf795bbf77d48741bdd99d6a074765fa5595f3982b96e6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1841e0b35478d65d382d13dd138955c30655002b91c2a83d96ec2c83925eec4f954892aa710ded867b50554dbc9653bddfad5c5aa915890e674bb49afed347bc
|
|
7
|
+
data.tar.gz: 1fc1443566c4e01e0c6ff25f1ae62c890ddcd5373257265ee7119ea8db359c20282cf646d61b955204e4dc538ceb9c6313725cb4fed21cda231b97321cc2c030
|
data/README.md
CHANGED
|
@@ -218,7 +218,9 @@ aidp watch owner/repo --once
|
|
|
218
218
|
|
|
219
219
|
**Label Workflow:**
|
|
220
220
|
|
|
221
|
-
AIDP uses a smart label-based workflow to manage
|
|
221
|
+
AIDP uses a smart label-based workflow to manage both issues and pull requests:
|
|
222
|
+
|
|
223
|
+
#### Issue Workflow (Plan & Build)
|
|
222
224
|
|
|
223
225
|
1. **Planning Phase** (`aidp-plan` label):
|
|
224
226
|
- Add this label to an issue to trigger plan generation
|
|
@@ -247,6 +249,32 @@ AIDP uses a smart label-based workflow to manage the lifecycle of automated issu
|
|
|
247
249
|
- Posts completion comment with summary
|
|
248
250
|
- Automatically removes the `aidp-build` label
|
|
249
251
|
|
|
252
|
+
#### Pull Request Workflow (Review, CI Fix, Change Requests)
|
|
253
|
+
|
|
254
|
+
<!-- markdownlint-disable-next-line MD029 -->
|
|
255
|
+
1. **Code Review** (`aidp-review` label):
|
|
256
|
+
- Add this label to any PR to trigger automated code review
|
|
257
|
+
- AIDP analyzes code from three expert perspectives (Senior Developer, Security Specialist, Performance Analyst)
|
|
258
|
+
- Posts a comprehensive review comment with severity-categorized findings (High Priority, Major, Minor, Nit)
|
|
259
|
+
- Automatically removes the label after posting review
|
|
260
|
+
- No commits are made - review only
|
|
261
|
+
|
|
262
|
+
2. **CI Fix** (`aidp-fix-ci` label):
|
|
263
|
+
- Add this label to a PR with failing CI checks
|
|
264
|
+
- AIDP analyzes CI failure logs and identifies root causes
|
|
265
|
+
- Automatically fixes issues like linting errors, simple test failures, and dependency problems
|
|
266
|
+
- Commits and pushes fixes to the PR branch
|
|
267
|
+
- Posts a summary of what was fixed
|
|
268
|
+
- Automatically removes the label after completion
|
|
269
|
+
|
|
270
|
+
3. **Change Requests** (`aidp-request-changes` label):
|
|
271
|
+
- Comment on your own PR describing desired changes, then add this label
|
|
272
|
+
- AIDP implements the requested changes on the PR branch
|
|
273
|
+
- Runs tests/linters and commits changes
|
|
274
|
+
- **If clarification needed**: Replaces label with `aidp-needs-input` and posts questions
|
|
275
|
+
- User responds to questions and re-applies the label to continue
|
|
276
|
+
- Automatically removes the label after completion
|
|
277
|
+
|
|
250
278
|
**Customizable Labels:**
|
|
251
279
|
|
|
252
280
|
All label names are configurable to match your repository's existing label scheme. Configure via the interactive wizard or manually in `aidp.yml`:
|
|
@@ -255,10 +283,16 @@ All label names are configurable to match your repository's existing label schem
|
|
|
255
283
|
# .aidp/aidp.yml
|
|
256
284
|
watch:
|
|
257
285
|
labels:
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
286
|
+
# Issue-based automation
|
|
287
|
+
plan_trigger: aidp-plan # Trigger plan generation
|
|
288
|
+
needs_input: aidp-needs-input # Needs user input/clarification
|
|
289
|
+
ready_to_build: aidp-ready # Plan ready for implementation
|
|
290
|
+
build_trigger: aidp-build # Trigger implementation
|
|
291
|
+
|
|
292
|
+
# PR-based automation
|
|
293
|
+
review_trigger: aidp-review # Trigger code review
|
|
294
|
+
ci_fix_trigger: aidp-fix-ci # Trigger CI auto-fix
|
|
295
|
+
change_request_trigger: aidp-request-changes # Trigger PR change implementation
|
|
262
296
|
```
|
|
263
297
|
|
|
264
298
|
Run `aidp config --interactive` and enable watch mode to configure labels interactively.
|
|
@@ -294,7 +328,12 @@ AIDP can automatically request clarification when it needs more information duri
|
|
|
294
328
|
|
|
295
329
|
This ensures AIDP never gets stuck - if it needs more information, it will ask for it rather than making incorrect assumptions or failing silently.
|
|
296
330
|
|
|
297
|
-
|
|
331
|
+
**Additional Documentation:**
|
|
332
|
+
|
|
333
|
+
- [Watch Mode Guide](docs/FULLY_AUTOMATIC_MODE.md) - Complete guide to watch mode setup and operation
|
|
334
|
+
- [Watch Mode Safety](docs/WATCH_MODE_SAFETY.md) - Security features and best practices
|
|
335
|
+
- [PR Automation Guide](docs/PR_AUTOMATION.md) - Detailed guide for code review, CI fixes, and PR changes
|
|
336
|
+
- [PR Change Requests](docs/PR_CHANGE_REQUESTS.md) - Comprehensive documentation for automated PR modifications
|
|
298
337
|
|
|
299
338
|
## Command Reference
|
|
300
339
|
|
|
@@ -99,6 +99,13 @@ module Aidp
|
|
|
99
99
|
private
|
|
100
100
|
|
|
101
101
|
def setup_logger(log_file, verbose)
|
|
102
|
+
# Suppress logger output in test/CI environments
|
|
103
|
+
if suppress_error_logs?
|
|
104
|
+
logger = ::Logger.new(IO::NULL)
|
|
105
|
+
logger.level = ::Logger::FATAL
|
|
106
|
+
return logger
|
|
107
|
+
end
|
|
108
|
+
|
|
102
109
|
output_stream = log_file || @output || $stdout
|
|
103
110
|
logger = ::Logger.new(output_stream)
|
|
104
111
|
logger.level = verbose ? ::Logger::DEBUG : ::Logger::INFO
|
|
@@ -108,6 +115,10 @@ module Aidp
|
|
|
108
115
|
logger
|
|
109
116
|
end
|
|
110
117
|
|
|
118
|
+
def suppress_error_logs?
|
|
119
|
+
ENV["RSPEC_RUNNING"] || ENV["CI"] || ENV["RAILS_ENV"] == "test" || ENV["RACK_ENV"] == "test"
|
|
120
|
+
end
|
|
121
|
+
|
|
111
122
|
def setup_recovery_strategies
|
|
112
123
|
strategies = {
|
|
113
124
|
Errno::ENOENT => :skip_step_with_warning,
|
|
@@ -59,6 +59,12 @@ module Aidp
|
|
|
59
59
|
@state_history = []
|
|
60
60
|
@deterministic_runner = DeterministicUnits::Runner.new(project_dir)
|
|
61
61
|
@unit_scheduler = nil
|
|
62
|
+
|
|
63
|
+
# Initialize thinking depth manager for intelligent model selection
|
|
64
|
+
require_relative "../harness/thinking_depth_manager"
|
|
65
|
+
@thinking_depth_manager = Aidp::Harness::ThinkingDepthManager.new(config)
|
|
66
|
+
@consecutive_failures = 0
|
|
67
|
+
@last_tier = nil
|
|
62
68
|
end
|
|
63
69
|
|
|
64
70
|
# Execute a step using fix-forward work loop pattern
|
|
@@ -176,19 +182,45 @@ module Aidp
|
|
|
176
182
|
process_task_filing(agent_result)
|
|
177
183
|
|
|
178
184
|
transition_to(:test)
|
|
185
|
+
# Run all configured checks
|
|
179
186
|
test_results = @test_runner.run_tests
|
|
180
187
|
lint_results = @test_runner.run_linters
|
|
188
|
+
build_results = @test_runner.run_builds
|
|
189
|
+
doc_results = @test_runner.run_documentation
|
|
190
|
+
|
|
191
|
+
# Run formatters only if agent marked work complete (per issue #234)
|
|
192
|
+
formatter_results = if agent_marked_complete?(agent_result)
|
|
193
|
+
@test_runner.run_formatters
|
|
194
|
+
else
|
|
195
|
+
{success: true, output: "Formatters: Skipped (work not complete)", failures: [], required_failures: []}
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
all_results = {
|
|
199
|
+
tests: test_results,
|
|
200
|
+
lints: lint_results,
|
|
201
|
+
formatters: formatter_results,
|
|
202
|
+
builds: build_results,
|
|
203
|
+
docs: doc_results
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
record_periodic_checkpoint(all_results)
|
|
181
207
|
|
|
182
|
-
|
|
208
|
+
# Track failures and escalate thinking tier if needed
|
|
209
|
+
track_failures_and_escalate(all_results)
|
|
183
210
|
|
|
184
|
-
|
|
211
|
+
# All required checks must pass for completion
|
|
212
|
+
all_checks_pass = test_results[:success] &&
|
|
213
|
+
lint_results[:success] &&
|
|
214
|
+
formatter_results[:success] &&
|
|
215
|
+
build_results[:success] &&
|
|
216
|
+
doc_results[:success]
|
|
185
217
|
|
|
186
|
-
if
|
|
218
|
+
if all_checks_pass
|
|
187
219
|
transition_to(:pass)
|
|
188
220
|
|
|
189
221
|
if agent_marked_complete?(agent_result)
|
|
190
222
|
transition_to(:done)
|
|
191
|
-
record_final_checkpoint(
|
|
223
|
+
record_final_checkpoint(all_results)
|
|
192
224
|
display_message("✅ Step #{@step_name} completed after #{@iteration_count} iterations", type: :success)
|
|
193
225
|
display_state_summary
|
|
194
226
|
archive_and_cleanup
|
|
@@ -201,18 +233,18 @@ module Aidp
|
|
|
201
233
|
terminate: true
|
|
202
234
|
)
|
|
203
235
|
else
|
|
204
|
-
display_message("
|
|
236
|
+
display_message(" All checks passed but work not marked complete", type: :info)
|
|
205
237
|
transition_to(:next_patch)
|
|
206
238
|
end
|
|
207
239
|
else
|
|
208
240
|
transition_to(:fail)
|
|
209
|
-
display_message("
|
|
241
|
+
display_message(" Required checks failed", type: :warning)
|
|
210
242
|
|
|
211
243
|
transition_to(:diagnose)
|
|
212
|
-
diagnostic = diagnose_failures(
|
|
244
|
+
diagnostic = diagnose_failures(all_results)
|
|
213
245
|
|
|
214
246
|
transition_to(:next_patch)
|
|
215
|
-
prepare_next_iteration(
|
|
247
|
+
prepare_next_iteration(all_results, diagnostic)
|
|
216
248
|
end
|
|
217
249
|
end
|
|
218
250
|
end
|
|
@@ -222,14 +254,18 @@ module Aidp
|
|
|
222
254
|
|
|
223
255
|
prompt = build_decider_prompt(context)
|
|
224
256
|
|
|
257
|
+
# Select model based on thinking depth tier
|
|
258
|
+
provider_name, model_name, _model_data = select_model_for_current_tier
|
|
259
|
+
|
|
225
260
|
agent_result = @provider_manager.execute_with_provider(
|
|
226
|
-
|
|
261
|
+
provider_name,
|
|
227
262
|
prompt,
|
|
228
263
|
{
|
|
229
264
|
step_name: @step_name,
|
|
230
265
|
iteration: @iteration_count,
|
|
231
266
|
project_dir: @project_dir,
|
|
232
|
-
mode: :decide_whats_next
|
|
267
|
+
mode: :decide_whats_next,
|
|
268
|
+
model: model_name
|
|
233
269
|
}
|
|
234
270
|
)
|
|
235
271
|
|
|
@@ -250,14 +286,18 @@ module Aidp
|
|
|
250
286
|
|
|
251
287
|
prompt = build_diagnose_prompt(context)
|
|
252
288
|
|
|
289
|
+
# Select model based on thinking depth tier
|
|
290
|
+
provider_name, model_name, _model_data = select_model_for_current_tier
|
|
291
|
+
|
|
253
292
|
agent_result = @provider_manager.execute_with_provider(
|
|
254
|
-
|
|
293
|
+
provider_name,
|
|
255
294
|
prompt,
|
|
256
295
|
{
|
|
257
296
|
step_name: @step_name,
|
|
258
297
|
iteration: @iteration_count,
|
|
259
298
|
project_dir: @project_dir,
|
|
260
|
-
mode: :diagnose_failures
|
|
299
|
+
mode: :diagnose_failures,
|
|
300
|
+
model: model_name
|
|
261
301
|
}
|
|
262
302
|
)
|
|
263
303
|
|
|
@@ -421,27 +461,26 @@ module Aidp
|
|
|
421
461
|
result[:status] == "completed" || prompt_marked_complete?
|
|
422
462
|
end
|
|
423
463
|
|
|
424
|
-
# Diagnose
|
|
464
|
+
# Diagnose all failures (tests, lints, formatters, builds, docs)
|
|
425
465
|
# Returns diagnostic information to help agent understand what went wrong
|
|
426
|
-
def diagnose_failures(
|
|
466
|
+
def diagnose_failures(all_results)
|
|
427
467
|
diagnostic = {
|
|
428
468
|
iteration: @iteration_count,
|
|
429
469
|
failures: []
|
|
430
470
|
}
|
|
431
471
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
472
|
+
# Check each result type for failures
|
|
473
|
+
all_results.each do |category, results|
|
|
474
|
+
next if results[:success]
|
|
475
|
+
|
|
476
|
+
# Only include required failures in diagnostic
|
|
477
|
+
required_failures = results[:required_failures] || results[:failures] || []
|
|
478
|
+
next if required_failures.empty?
|
|
439
479
|
|
|
440
|
-
unless lint_results[:success]
|
|
441
480
|
diagnostic[:failures] << {
|
|
442
|
-
type:
|
|
443
|
-
count:
|
|
444
|
-
commands:
|
|
481
|
+
type: category.to_s,
|
|
482
|
+
count: required_failures.size,
|
|
483
|
+
commands: required_failures.map { |f| f[:command] }
|
|
445
484
|
}
|
|
446
485
|
end
|
|
447
486
|
|
|
@@ -650,17 +689,36 @@ module Aidp
|
|
|
650
689
|
# Prepend work loop instructions to every iteration
|
|
651
690
|
full_prompt = build_work_loop_header(@step_name, @iteration_count) + "\n\n" + prompt_content
|
|
652
691
|
|
|
692
|
+
# Select model based on thinking depth tier
|
|
693
|
+
provider_name, model_name, _model_data = select_model_for_current_tier
|
|
694
|
+
|
|
695
|
+
if provider_name.nil? || model_name.nil?
|
|
696
|
+
Aidp.logger.error("work_loop", "Failed to select model for tier",
|
|
697
|
+
tier: @thinking_depth_manager.current_tier,
|
|
698
|
+
step: @step_name,
|
|
699
|
+
iteration: @iteration_count)
|
|
700
|
+
return {status: "error", message: "No model available for tier #{@thinking_depth_manager.current_tier}"}
|
|
701
|
+
end
|
|
702
|
+
|
|
703
|
+
# Log model selection
|
|
704
|
+
tier = @thinking_depth_manager.current_tier
|
|
705
|
+
if @last_tier != tier
|
|
706
|
+
display_message(" 💡 Using tier: #{tier} (#{provider_name}/#{model_name})", type: :info)
|
|
707
|
+
@last_tier = tier
|
|
708
|
+
end
|
|
709
|
+
|
|
653
710
|
# CRITICAL: Change to project directory before calling provider
|
|
654
711
|
# This ensures Claude CLI runs in the correct directory and can create files
|
|
655
712
|
Dir.chdir(@project_dir) do
|
|
656
|
-
# Send to provider via provider_manager
|
|
713
|
+
# Send to provider via provider_manager with selected model
|
|
657
714
|
@provider_manager.execute_with_provider(
|
|
658
|
-
|
|
715
|
+
provider_name,
|
|
659
716
|
full_prompt,
|
|
660
717
|
{
|
|
661
718
|
step_name: @step_name,
|
|
662
719
|
iteration: @iteration_count,
|
|
663
|
-
project_dir: @project_dir
|
|
720
|
+
project_dir: @project_dir,
|
|
721
|
+
model: model_name
|
|
664
722
|
}
|
|
665
723
|
)
|
|
666
724
|
end
|
|
@@ -701,7 +759,7 @@ module Aidp
|
|
|
701
759
|
prompt_content.match?(/^STATUS:\s*COMPLETE/i)
|
|
702
760
|
end
|
|
703
761
|
|
|
704
|
-
def prepare_next_iteration(
|
|
762
|
+
def prepare_next_iteration(all_results, diagnostic = nil)
|
|
705
763
|
# Only append failures to PROMPT.md for agent to see
|
|
706
764
|
# This follows fix-forward: never rollback, only add information for next patch
|
|
707
765
|
failures = []
|
|
@@ -723,25 +781,30 @@ module Aidp
|
|
|
723
781
|
failures << ""
|
|
724
782
|
end
|
|
725
783
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
784
|
+
# Add failure output for each category that has failures
|
|
785
|
+
category_labels = {
|
|
786
|
+
tests: "Test",
|
|
787
|
+
lints: "Linter",
|
|
788
|
+
formatters: "Formatter",
|
|
789
|
+
builds: "Build",
|
|
790
|
+
docs: "Documentation"
|
|
791
|
+
}
|
|
731
792
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
793
|
+
all_results.each do |category, results|
|
|
794
|
+
next if results[:success]
|
|
795
|
+
|
|
796
|
+
failures << "### #{category_labels[category]} Failures"
|
|
797
|
+
failures << results[:output]
|
|
735
798
|
failures << ""
|
|
736
799
|
end
|
|
737
800
|
|
|
738
|
-
strategy = build_failure_strategy(
|
|
801
|
+
strategy = build_failure_strategy(all_results)
|
|
739
802
|
failures.concat(strategy) unless strategy.empty?
|
|
740
803
|
|
|
741
804
|
failures << "**Fix-forward instructions**: Do not rollback changes. Build on what exists and fix the failures above."
|
|
742
805
|
failures << ""
|
|
743
806
|
|
|
744
|
-
return if
|
|
807
|
+
return if all_results.values.all? { |result| result[:success] }
|
|
745
808
|
|
|
746
809
|
# Append failures to PROMPT.md and archive immediately (issue #224)
|
|
747
810
|
current_prompt = @prompt_manager.read
|
|
@@ -832,20 +895,27 @@ module Aidp
|
|
|
832
895
|
reminder.join("\n")
|
|
833
896
|
end
|
|
834
897
|
|
|
835
|
-
def build_failure_strategy(
|
|
836
|
-
return [] if
|
|
898
|
+
def build_failure_strategy(all_results)
|
|
899
|
+
return [] if all_results.values.all? { |result| result[:success] }
|
|
837
900
|
|
|
838
901
|
lines = ["### Recovery Strategy", ""]
|
|
839
902
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
903
|
+
category_strategies = {
|
|
904
|
+
tests: "Re-run %s locally to reproduce the failing specs listed above. Triage the exact failures before moving on to new work.",
|
|
905
|
+
lints: "Execute %s and fix each reported offense.",
|
|
906
|
+
formatters: "Run %s to fix formatting issues.",
|
|
907
|
+
builds: "Run %s to diagnose and fix build errors.",
|
|
908
|
+
docs: "Review and update documentation using %s to meet requirements."
|
|
909
|
+
}
|
|
845
910
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
911
|
+
all_results.each do |category, results|
|
|
912
|
+
next if results[:success]
|
|
913
|
+
|
|
914
|
+
strategy_template = category_strategies[category]
|
|
915
|
+
next unless strategy_template
|
|
916
|
+
|
|
917
|
+
commands = format_command_list(results[:failures])
|
|
918
|
+
lines << "- #{strategy_template % commands}"
|
|
849
919
|
end
|
|
850
920
|
|
|
851
921
|
lines << ""
|
|
@@ -926,13 +996,16 @@ module Aidp
|
|
|
926
996
|
end
|
|
927
997
|
|
|
928
998
|
# Record checkpoint at regular intervals
|
|
929
|
-
def record_periodic_checkpoint(
|
|
999
|
+
def record_periodic_checkpoint(all_results)
|
|
930
1000
|
# Record every CHECKPOINT_INTERVAL iterations or on iteration 1
|
|
931
1001
|
return unless @iteration_count == 1 || (@iteration_count % CHECKPOINT_INTERVAL == 0)
|
|
932
1002
|
|
|
933
1003
|
metrics = {
|
|
934
|
-
tests_passing:
|
|
935
|
-
linters_passing:
|
|
1004
|
+
tests_passing: all_results[:tests][:success],
|
|
1005
|
+
linters_passing: all_results[:lints][:success],
|
|
1006
|
+
formatters_passing: all_results[:formatters][:success],
|
|
1007
|
+
builds_passing: all_results[:builds][:success],
|
|
1008
|
+
docs_passing: all_results[:docs][:success]
|
|
936
1009
|
}
|
|
937
1010
|
|
|
938
1011
|
checkpoint_data = @checkpoint.record_checkpoint(@step_name, @iteration_count, metrics)
|
|
@@ -947,10 +1020,13 @@ module Aidp
|
|
|
947
1020
|
end
|
|
948
1021
|
|
|
949
1022
|
# Record final checkpoint when step completes
|
|
950
|
-
def record_final_checkpoint(
|
|
1023
|
+
def record_final_checkpoint(all_results)
|
|
951
1024
|
metrics = {
|
|
952
|
-
tests_passing:
|
|
953
|
-
linters_passing:
|
|
1025
|
+
tests_passing: all_results[:tests][:success],
|
|
1026
|
+
linters_passing: all_results[:lints][:success],
|
|
1027
|
+
formatters_passing: all_results[:formatters][:success],
|
|
1028
|
+
builds_passing: all_results[:builds][:success],
|
|
1029
|
+
docs_passing: all_results[:docs][:success],
|
|
954
1030
|
completed: true
|
|
955
1031
|
}
|
|
956
1032
|
|
|
@@ -1114,6 +1190,100 @@ module Aidp
|
|
|
1114
1190
|
display_message(" ✓ Confirmed", type: :success)
|
|
1115
1191
|
end
|
|
1116
1192
|
end
|
|
1193
|
+
|
|
1194
|
+
# Select model based on current thinking depth tier
|
|
1195
|
+
# Returns [provider_name, model_name, model_data]
|
|
1196
|
+
def select_model_for_current_tier
|
|
1197
|
+
current_tier = @thinking_depth_manager.current_tier
|
|
1198
|
+
provider_name, model_name, model_data = @thinking_depth_manager.select_model_for_tier(
|
|
1199
|
+
current_tier,
|
|
1200
|
+
provider: @provider_manager.current_provider
|
|
1201
|
+
)
|
|
1202
|
+
|
|
1203
|
+
Aidp.logger.debug("work_loop", "Selected model for tier",
|
|
1204
|
+
tier: current_tier,
|
|
1205
|
+
provider: provider_name,
|
|
1206
|
+
model: model_name,
|
|
1207
|
+
step: @step_name,
|
|
1208
|
+
iteration: @iteration_count)
|
|
1209
|
+
|
|
1210
|
+
[provider_name, model_name, model_data]
|
|
1211
|
+
end
|
|
1212
|
+
|
|
1213
|
+
# Track test/lint/formatter/build/doc failures and escalate tier if needed
|
|
1214
|
+
def track_failures_and_escalate(all_results)
|
|
1215
|
+
all_pass = all_results.values.all? { |result| result[:success] }
|
|
1216
|
+
|
|
1217
|
+
if all_pass
|
|
1218
|
+
# Reset failure count on success
|
|
1219
|
+
@consecutive_failures = 0
|
|
1220
|
+
else
|
|
1221
|
+
# Increment failure count
|
|
1222
|
+
@consecutive_failures += 1
|
|
1223
|
+
|
|
1224
|
+
# Check if we should escalate based on consecutive failures
|
|
1225
|
+
if @thinking_depth_manager.should_escalate_on_failures?(@consecutive_failures)
|
|
1226
|
+
escalate_thinking_tier("consecutive_failures")
|
|
1227
|
+
end
|
|
1228
|
+
end
|
|
1229
|
+
|
|
1230
|
+
# Check complexity-based escalation
|
|
1231
|
+
changed_files = get_changed_files
|
|
1232
|
+
if @thinking_depth_manager.should_escalate_on_complexity?(
|
|
1233
|
+
files_changed: changed_files.size,
|
|
1234
|
+
modules_touched: estimate_modules_touched(changed_files)
|
|
1235
|
+
)
|
|
1236
|
+
escalate_thinking_tier("complexity_threshold")
|
|
1237
|
+
end
|
|
1238
|
+
end
|
|
1239
|
+
|
|
1240
|
+
# Escalate to next thinking tier
|
|
1241
|
+
def escalate_thinking_tier(reason)
|
|
1242
|
+
old_tier = @thinking_depth_manager.current_tier
|
|
1243
|
+
new_tier = @thinking_depth_manager.escalate_tier(reason: reason)
|
|
1244
|
+
|
|
1245
|
+
if new_tier
|
|
1246
|
+
display_message(" ⬆️ Escalated thinking tier: #{old_tier} → #{new_tier} (#{reason})", type: :warning)
|
|
1247
|
+
Aidp.logger.info("work_loop", "Escalated thinking tier",
|
|
1248
|
+
from: old_tier,
|
|
1249
|
+
to: new_tier,
|
|
1250
|
+
reason: reason,
|
|
1251
|
+
step: @step_name,
|
|
1252
|
+
iteration: @iteration_count,
|
|
1253
|
+
consecutive_failures: @consecutive_failures)
|
|
1254
|
+
|
|
1255
|
+
# Reset last tier to trigger display of new tier
|
|
1256
|
+
@last_tier = nil
|
|
1257
|
+
else
|
|
1258
|
+
Aidp.logger.debug("work_loop", "Cannot escalate tier further",
|
|
1259
|
+
current: old_tier,
|
|
1260
|
+
max: @thinking_depth_manager.max_tier,
|
|
1261
|
+
reason: reason)
|
|
1262
|
+
end
|
|
1263
|
+
end
|
|
1264
|
+
|
|
1265
|
+
# Estimate number of modules touched based on file paths
|
|
1266
|
+
def estimate_modules_touched(files)
|
|
1267
|
+
# Group files by their top-level directory or module
|
|
1268
|
+
modules = files.map do |file|
|
|
1269
|
+
parts = file.split("/")
|
|
1270
|
+
# Consider top 2 levels as module identifier
|
|
1271
|
+
parts.take(2).join("/")
|
|
1272
|
+
end.uniq
|
|
1273
|
+
|
|
1274
|
+
modules.size
|
|
1275
|
+
end
|
|
1276
|
+
|
|
1277
|
+
# Get thinking depth status for display
|
|
1278
|
+
def thinking_depth_status
|
|
1279
|
+
{
|
|
1280
|
+
current_tier: @thinking_depth_manager.current_tier,
|
|
1281
|
+
max_tier: @thinking_depth_manager.max_tier,
|
|
1282
|
+
can_escalate: @thinking_depth_manager.can_escalate?,
|
|
1283
|
+
consecutive_failures: @consecutive_failures,
|
|
1284
|
+
escalation_count: @thinking_depth_manager.escalation_count
|
|
1285
|
+
}
|
|
1286
|
+
end
|
|
1117
1287
|
end
|
|
1118
1288
|
end
|
|
1119
1289
|
end
|
|
@@ -316,17 +316,19 @@ module Aidp
|
|
|
316
316
|
def handle_validation_errors(errors)
|
|
317
317
|
error_message = "Configuration validation failed:\n" + errors.join("\n")
|
|
318
318
|
|
|
319
|
-
# Log error
|
|
320
|
-
|
|
321
|
-
Rails.logger
|
|
322
|
-
|
|
323
|
-
|
|
319
|
+
# Log error (suppress in test/CI environments)
|
|
320
|
+
unless suppress_config_warnings?
|
|
321
|
+
if defined?(Rails) && Rails.logger
|
|
322
|
+
Rails.logger.error(error_message)
|
|
323
|
+
else
|
|
324
|
+
warn(error_message)
|
|
325
|
+
end
|
|
324
326
|
end
|
|
325
327
|
|
|
326
328
|
# In development, try to fix common issues
|
|
327
329
|
if ENV["AIDP_ENV"] == "development" || ENV["RACK_ENV"] == "development"
|
|
328
330
|
if @validator.fix_common_issues
|
|
329
|
-
warn("Attempted to fix configuration issues. Please review the updated configuration file.")
|
|
331
|
+
warn("Attempted to fix configuration issues. Please review the updated configuration file.") unless suppress_config_warnings?
|
|
330
332
|
end
|
|
331
333
|
end
|
|
332
334
|
end
|
|
@@ -334,11 +336,13 @@ module Aidp
|
|
|
334
336
|
def log_warnings(warnings)
|
|
335
337
|
warning_message = "Configuration warnings:\n" + warnings.join("\n")
|
|
336
338
|
|
|
337
|
-
# Log warnings
|
|
338
|
-
|
|
339
|
-
Rails.logger
|
|
340
|
-
|
|
341
|
-
|
|
339
|
+
# Log warnings (suppress in test/CI environments)
|
|
340
|
+
unless suppress_config_warnings?
|
|
341
|
+
if defined?(Rails) && Rails.logger
|
|
342
|
+
Rails.logger.warn(warning_message)
|
|
343
|
+
else
|
|
344
|
+
warn(warning_message)
|
|
345
|
+
end
|
|
342
346
|
end
|
|
343
347
|
end
|
|
344
348
|
|
|
@@ -390,6 +394,11 @@ module Aidp
|
|
|
390
394
|
false
|
|
391
395
|
end
|
|
392
396
|
end
|
|
397
|
+
|
|
398
|
+
# Suppress configuration warnings in test/CI environments
|
|
399
|
+
def suppress_config_warnings?
|
|
400
|
+
ENV["RSPEC_RUNNING"] || ENV["CI"] || ENV["RAILS_ENV"] == "test" || ENV["RACK_ENV"] == "test"
|
|
401
|
+
end
|
|
393
402
|
end
|
|
394
403
|
end
|
|
395
404
|
end
|
|
@@ -375,6 +375,9 @@ module Aidp
|
|
|
375
375
|
max_iterations: 50,
|
|
376
376
|
test_commands: [],
|
|
377
377
|
lint_commands: [],
|
|
378
|
+
formatter_commands: [],
|
|
379
|
+
build_commands: [],
|
|
380
|
+
documentation_commands: [],
|
|
378
381
|
units: {},
|
|
379
382
|
guards: {enabled: false},
|
|
380
383
|
version_control: {tool: "git", behavior: "nothing", conventional_commits: false},
|
|
@@ -397,18 +400,37 @@ module Aidp
|
|
|
397
400
|
test_commands: {
|
|
398
401
|
type: :array,
|
|
399
402
|
required: false,
|
|
400
|
-
default: []
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
403
|
+
default: []
|
|
404
|
+
# Items can be strings or {command: string, required: boolean}
|
|
405
|
+
# Validation handled in Configuration class for flexibility
|
|
404
406
|
},
|
|
405
407
|
lint_commands: {
|
|
406
408
|
type: :array,
|
|
407
409
|
required: false,
|
|
408
|
-
default: []
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
default: []
|
|
411
|
+
# Items can be strings or {command: string, required: boolean}
|
|
412
|
+
# Validation handled in Configuration class for flexibility
|
|
413
|
+
},
|
|
414
|
+
formatter_commands: {
|
|
415
|
+
type: :array,
|
|
416
|
+
required: false,
|
|
417
|
+
default: []
|
|
418
|
+
# Items can be strings or {command: string, required: boolean}
|
|
419
|
+
# Validation handled in Configuration class for flexibility
|
|
420
|
+
},
|
|
421
|
+
build_commands: {
|
|
422
|
+
type: :array,
|
|
423
|
+
required: false,
|
|
424
|
+
default: []
|
|
425
|
+
# Items can be strings or {command: string, required: boolean}
|
|
426
|
+
# Validation handled in Configuration class for flexibility
|
|
427
|
+
},
|
|
428
|
+
documentation_commands: {
|
|
429
|
+
type: :array,
|
|
430
|
+
required: false,
|
|
431
|
+
default: []
|
|
432
|
+
# Items can be strings or {command: string, required: boolean}
|
|
433
|
+
# Validation handled in Configuration class for flexibility
|
|
412
434
|
},
|
|
413
435
|
units: {
|
|
414
436
|
type: :hash,
|