aidp 0.34.1 → 0.39.3

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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -14
  3. data/lib/aidp/agent_harness_adapter.rb +309 -0
  4. data/lib/aidp/cli/issue_importer.rb +20 -6
  5. data/lib/aidp/cli/jobs_command.rb +1 -1
  6. data/lib/aidp/cli/models_command.rb +9 -16
  7. data/lib/aidp/cli/prompts_command.rb +253 -0
  8. data/lib/aidp/cli/security_command.rb +4 -10
  9. data/lib/aidp/cli/storage_command.rb +277 -0
  10. data/lib/aidp/cli/temporal_command.rb +460 -0
  11. data/lib/aidp/cli.rb +24 -2
  12. data/lib/aidp/config.rb +15 -0
  13. data/lib/aidp/config_paths.rb +12 -2
  14. data/lib/aidp/database/migrations.rb +114 -0
  15. data/lib/aidp/database/repositories/checkpoint_repository.rb +174 -0
  16. data/lib/aidp/database/repositories/deprecated_models_repository.rb +206 -0
  17. data/lib/aidp/database/repositories/evaluation_repository.rb +208 -0
  18. data/lib/aidp/database/repositories/harness_state_repository.rb +140 -0
  19. data/lib/aidp/database/repositories/job_repository.rb +278 -0
  20. data/lib/aidp/database/repositories/model_cache_repository.rb +194 -0
  21. data/lib/aidp/database/repositories/progress_repository.rb +210 -0
  22. data/lib/aidp/database/repositories/prompt_archive_repository.rb +195 -0
  23. data/lib/aidp/database/repositories/prompt_feedback_repository.rb +266 -0
  24. data/lib/aidp/database/repositories/provider_info_cache_repository.rb +208 -0
  25. data/lib/aidp/database/repositories/provider_metrics_repository.rb +245 -0
  26. data/lib/aidp/database/repositories/secrets_repository.rb +187 -0
  27. data/lib/aidp/database/repositories/task_repository.rb +231 -0
  28. data/lib/aidp/database/repositories/template_version_repository.rb +383 -0
  29. data/lib/aidp/database/repositories/watch_state_repository.rb +472 -0
  30. data/lib/aidp/database/repositories/workstream_repository.rb +310 -0
  31. data/lib/aidp/database/repositories/worktree_repository.rb +240 -0
  32. data/lib/aidp/database/repository.rb +166 -0
  33. data/lib/aidp/database/schema.rb +347 -0
  34. data/lib/aidp/database/storage_migrator.rb +693 -0
  35. data/lib/aidp/database.rb +139 -0
  36. data/lib/aidp/debug_mixin.rb +2 -2
  37. data/lib/aidp/execute/checkpoint.rb +26 -0
  38. data/lib/aidp/execute/checkpoint_display.rb +16 -0
  39. data/lib/aidp/execute/prompt_evaluator.rb +30 -57
  40. data/lib/aidp/execute/work_loop_runner.rb +294 -46
  41. data/lib/aidp/firewall/provider_requirements_collector.rb +7 -23
  42. data/lib/aidp/harness/agent_harness_provider_manager.rb +275 -0
  43. data/lib/aidp/harness/ai_decision_engine.rb +78 -296
  44. data/lib/aidp/harness/config_schema.rb +59 -0
  45. data/lib/aidp/harness/configuration.rb +229 -10
  46. data/lib/aidp/harness/deprecation_cache.rb +53 -11
  47. data/lib/aidp/harness/enhanced_runner.rb +1 -1
  48. data/lib/aidp/harness/error_handler.rb +11 -5
  49. data/lib/aidp/harness/provider_config.rb +36 -0
  50. data/lib/aidp/harness/provider_factory.rb +26 -24
  51. data/lib/aidp/harness/provider_info.rb +9 -5
  52. data/lib/aidp/harness/provider_manager.rb +2 -2
  53. data/lib/aidp/harness/provider_metrics.rb +103 -1
  54. data/lib/aidp/harness/rspec_command_optimizer.rb +166 -0
  55. data/lib/aidp/harness/ruby_llm_registry.rb +97 -8
  56. data/lib/aidp/harness/runner.rb +7 -2
  57. data/lib/aidp/harness/state_manager.rb +1 -1
  58. data/lib/aidp/harness/test_runner.rb +167 -11
  59. data/lib/aidp/harness/thinking_depth_manager.rb +564 -5
  60. data/lib/aidp/harness/usage_limit.rb +179 -0
  61. data/lib/aidp/harness/usage_limit_enforcer.rb +240 -0
  62. data/lib/aidp/harness/usage_limit_tracker.rb +308 -0
  63. data/lib/aidp/harness/usage_period.rb +234 -0
  64. data/lib/aidp/init/agent_instructions_generator.rb +317 -0
  65. data/lib/aidp/init/runner.rb +25 -4
  66. data/lib/aidp/interfaces/activity_monitor_interface.rb +234 -0
  67. data/lib/aidp/interfaces/binary_checker_interface.rb +232 -0
  68. data/lib/aidp/interfaces/command_executor_interface.rb +216 -0
  69. data/lib/aidp/interfaces/logger_interface.rb +150 -0
  70. data/lib/aidp/interfaces/ui_interface.rb +254 -0
  71. data/lib/aidp/logger.rb +25 -7
  72. data/lib/aidp/orchestration_adapter.rb +279 -0
  73. data/lib/aidp/pr_worktree_manager.rb +4 -15
  74. data/lib/aidp/prompts/feedback_collector.rb +198 -0
  75. data/lib/aidp/prompts/prompt_template_manager.rb +415 -0
  76. data/lib/aidp/prompts/template_evolver.rb +305 -0
  77. data/lib/aidp/prompts/template_version_manager.rb +325 -0
  78. data/lib/aidp/setup/in_memory_config_adapter.rb +257 -0
  79. data/lib/aidp/setup/in_memory_config_manager.rb +262 -0
  80. data/lib/aidp/setup/wizard.rb +616 -176
  81. data/lib/aidp/shell_executor.rb +58 -0
  82. data/lib/aidp/style_guide/selector.rb +56 -1
  83. data/lib/aidp/temporal/activities/analyze_issue_activity.rb +198 -0
  84. data/lib/aidp/temporal/activities/analyze_sub_task_activity.rb +163 -0
  85. data/lib/aidp/temporal/activities/base_activity.rb +78 -0
  86. data/lib/aidp/temporal/activities/create_plan_activity.rb +115 -0
  87. data/lib/aidp/temporal/activities/create_pr_activity.rb +193 -0
  88. data/lib/aidp/temporal/activities/create_prompt_activity.rb +118 -0
  89. data/lib/aidp/temporal/activities/diagnose_failure_activity.rb +228 -0
  90. data/lib/aidp/temporal/activities/prepare_next_iteration_activity.rb +147 -0
  91. data/lib/aidp/temporal/activities/record_checkpoint_activity.rb +81 -0
  92. data/lib/aidp/temporal/activities/run_agent_activity.rb +139 -0
  93. data/lib/aidp/temporal/activities/run_tests_activity.rb +114 -0
  94. data/lib/aidp/temporal/activities/run_work_loop_iteration_activity.rb +249 -0
  95. data/lib/aidp/temporal/configuration.rb +169 -0
  96. data/lib/aidp/temporal/connection.rb +93 -0
  97. data/lib/aidp/temporal/worker.rb +119 -0
  98. data/lib/aidp/temporal/workflow_client.rb +171 -0
  99. data/lib/aidp/temporal/workflows/base_workflow.rb +73 -0
  100. data/lib/aidp/temporal/workflows/issue_to_pr_workflow.rb +278 -0
  101. data/lib/aidp/temporal/workflows/sub_issue_workflow.rb +253 -0
  102. data/lib/aidp/temporal/workflows/work_loop_workflow.rb +321 -0
  103. data/lib/aidp/temporal.rb +120 -0
  104. data/lib/aidp/version.rb +1 -1
  105. data/lib/aidp/watch/base_processor.rb +35 -0
  106. data/lib/aidp/watch/build_processor.rb +132 -0
  107. data/lib/aidp/watch/github_state_extractor.rb +0 -8
  108. data/lib/aidp/watch/rebase_processor.rb +245 -0
  109. data/lib/aidp/watch/round_robin_scheduler.rb +150 -0
  110. data/lib/aidp/watch/runner.rb +366 -285
  111. data/lib/aidp/watch/state_store.rb +80 -0
  112. data/lib/aidp/watch/work_item.rb +96 -0
  113. data/lib/aidp/watch/worktree_cleanup_job.rb +226 -0
  114. data/lib/aidp/watch/worktree_reconciler.rb +643 -0
  115. data/lib/aidp/workflows/guided_agent.rb +1 -1
  116. data/lib/aidp/worktree.rb +62 -0
  117. data/templates/aidp.yml.example +70 -0
  118. metadata +117 -16
  119. data/lib/aidp/analyze/json_file_storage.rb +0 -292
  120. data/lib/aidp/execute/future_work_backlog.rb +0 -411
  121. data/lib/aidp/providers/adapter.rb +0 -239
  122. data/lib/aidp/providers/aider.rb +0 -264
  123. data/lib/aidp/providers/anthropic.rb +0 -614
  124. data/lib/aidp/providers/base.rb +0 -617
  125. data/lib/aidp/providers/capability_registry.rb +0 -204
  126. data/lib/aidp/providers/codex.rb +0 -267
  127. data/lib/aidp/providers/cursor.rb +0 -304
  128. data/lib/aidp/providers/error_taxonomy.rb +0 -195
  129. data/lib/aidp/providers/gemini.rb +0 -110
  130. data/lib/aidp/providers/github_copilot.rb +0 -227
  131. data/lib/aidp/providers/kilocode.rb +0 -157
  132. data/lib/aidp/providers/opencode.rb +0 -139
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e481b19f01c0541ffc177baca0a006daa46e50dc458cfb9d009c4ac306f90fe
4
- data.tar.gz: 8a6d757cdb1821070298dd4e2aa69847f422bb380f662fdc15c7a057ef40c2ef
3
+ metadata.gz: 8cd5163981904da173cfeb433c9d866ac8d138f7020701255d6db3e9b024d9c1
4
+ data.tar.gz: 414b329a3d385dd31a7822af2cb793a974f0ef8e9d231095037c0733fa054c9c
5
5
  SHA512:
6
- metadata.gz: 5579edf4e50738db997d1f77f4b687192cc40df8fd28b8a03d06639191675d48a17437696d2944d0eef5c29bc836931fd9def38688974c70dcb23542b521e04b
7
- data.tar.gz: fc5bf185851a4c1d0a10c0048a48ad86eb82bf5dfdfb232c455116466a50e682055e501f04b1a8abab323061a6ebb52024de69c4cc04a20696d0386917d35f06
6
+ metadata.gz: 2c0c3826a863f357658f9ff9a6aff38404d9939d6ece54c994b0d658bde2b8025e506f4d6964d61fc37f20f97d3bb6c30a3cb58a65ee01e437d23c93d26d53c2
7
+ data.tar.gz: b1fcd507b193d0f7748790f4e22604e6c5fe4d7b29f9df50221eb4850288337600ac607e057f203661b1167c966982ca09a1e97a01a216357c1b0ae46867867b
data/README.md CHANGED
@@ -116,7 +116,7 @@ aidp devcontainer list-backups
116
116
  aidp devcontainer restore 0
117
117
  ```
118
118
 
119
- See [docs/DEVELOPMENT_CONTAINER.md](docs/DEVELOPMENT_CONTAINER.md) for complete devcontainer management documentation.
119
+ See [docs/how-to/DEVELOPMENT_CONTAINER.md](docs/how-to/DEVELOPMENT_CONTAINER.md) for complete devcontainer management documentation.
120
120
 
121
121
  ### Devcontainer Detection
122
122
 
@@ -133,7 +133,7 @@ AIDP implements **work loops** - an iterative execution pattern where AI agents
133
133
  - **Automatic validation**: Tests and linters run after each iteration
134
134
  - **Self-correction**: Only failures are fed back for the next iteration
135
135
 
136
- See [Work Loops Guide](docs/WORK_LOOPS_GUIDE.md) for details.
136
+ See [Work Loops Guide](docs/how-to/WORK_LOOPS_GUIDE.md) for details.
137
137
 
138
138
  ### Waterfall Planning Mode
139
139
 
@@ -167,7 +167,7 @@ aidp execute
167
167
  - **Mermaid Visualizations** - Gantt charts renderable on GitHub/GitLab
168
168
  - **TDD Integration** - Optional test-driven development workflow
169
169
 
170
- See [Waterfall Planning Mode Guide](docs/WATERFALL_PLANNING_MODE.md) for complete documentation.
170
+ See [Waterfall Planning Mode Guide](docs/how-to/WATERFALL_PLANNING_MODE.md) for complete documentation.
171
171
 
172
172
  ### Agile Development Mode
173
173
 
@@ -222,7 +222,7 @@ Analyze existing codebase and create user research plan:
222
222
  - **Marketing Focus** - Translate features into customer value
223
223
  - **Three New Personas** - Product Manager, UX Researcher, Marketing Strategist
224
224
 
225
- See [Agile Development Mode Guide](docs/AGILE_MODE_GUIDE.md) for complete documentation.
225
+ See [Agile Development Mode Guide](docs/how-to/AGILE_MODE_GUIDE.md) for complete documentation.
226
226
 
227
227
  ### GitHub Projects V2 Integration
228
228
 
@@ -257,7 +257,7 @@ main
257
257
  └── aidp/sub-123-126-component-c
258
258
  ```
259
259
 
260
- See [GitHub Projects Guide](docs/GITHUB_PROJECTS.md) for complete documentation.
260
+ See [GitHub Projects Guide](docs/how-to/GITHUB_PROJECTS.md) for complete documentation.
261
261
 
262
262
  ### Job Management
263
263
 
@@ -323,7 +323,7 @@ aidp ws rm issue-123-fix-auth --delete-branch
323
323
  - Independent state and history
324
324
  - Work on multiple features in parallel
325
325
 
326
- See [Workstreams Guide](docs/WORKSTREAMS.md) for detailed usage.
326
+ See [Workstreams Guide](docs/how-to/WORKSTREAMS.md) for detailed usage.
327
327
 
328
328
  ### Watch Mode (Automated GitHub Integration)
329
329
 
@@ -454,10 +454,10 @@ This ensures AIDP never gets stuck - if it needs more information, it will ask f
454
454
 
455
455
  **Additional Documentation:**
456
456
 
457
- - [Watch Mode Guide](docs/FULLY_AUTOMATIC_MODE.md) - Complete guide to watch mode setup and operation
458
- - [Watch Mode Safety](docs/WATCH_MODE_SAFETY.md) - Security features and best practices
459
- - [PR Automation Guide](docs/PR_AUTOMATION.md) - Detailed guide for code review, CI fixes, and PR changes
460
- - [PR Change Requests](docs/PR_CHANGE_REQUESTS.md) - Comprehensive documentation for automated PR modifications
457
+ - [Watch Mode Guide](docs/how-to/FULLY_AUTOMATIC_MODE.md) - Complete guide to watch mode setup and operation
458
+ - [Watch Mode Safety](docs/explanation/WATCH_MODE_SAFETY.md) - Security features and best practices
459
+ - [PR Automation Guide](docs/how-to/PR_AUTOMATION.md) - Detailed guide for code review, CI fixes, and PR changes
460
+ - [PR Change Requests](docs/how-to/PR_CHANGE_REQUESTS.md) - Comprehensive documentation for automated PR modifications
461
461
 
462
462
  ## Command Reference
463
463
 
@@ -844,10 +844,10 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and conventional co
844
844
 
845
845
  For detailed information:
846
846
 
847
- - **[CLI User Guide](docs/CLI_USER_GUIDE.md)** - Complete guide to using AIDP commands
848
- - **[Work Loops Guide](docs/WORK_LOOPS_GUIDE.md)** - Iterative workflows with automatic validation
849
- - **[Configuration Guide](docs/harness-configuration.md)** - Detailed configuration options and examples
850
- - **[Troubleshooting Guide](docs/harness-troubleshooting.md)** - Common issues and solutions
847
+ - **[CLI User Guide](docs/how-to/CLI_USER_GUIDE.md)** - Complete guide to using AIDP commands
848
+ - **[Work Loops Guide](docs/how-to/WORK_LOOPS_GUIDE.md)** - Iterative workflows with automatic validation
849
+ - **[Configuration Guide](docs/reference/CONFIGURATION.md)** - Detailed configuration options and examples
850
+ - **[Debug Guide](docs/how-to/DEBUG_GUIDE.md)** - Debugging and troubleshooting
851
851
 
852
852
  ## Manual Workflow (Alternative)
853
853
 
@@ -0,0 +1,309 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "agent_harness"
4
+
5
+ module Aidp
6
+ # Wraps AIDP's logger to provide standard Ruby Logger interface
7
+ # for AgentHarness compatibility
8
+ class LoggerAdapter
9
+ def initialize(aidp_logger, component: "agent_harness")
10
+ @logger = aidp_logger
11
+ @component = component
12
+ end
13
+
14
+ def debug(message = nil, &block)
15
+ msg = message || (block ? block.call : "")
16
+ @logger&.debug(@component, msg.to_s)
17
+ end
18
+
19
+ def info(message = nil, &block)
20
+ msg = message || (block ? block.call : "")
21
+ @logger&.info(@component, msg.to_s)
22
+ end
23
+
24
+ def warn(message = nil, &block)
25
+ msg = message || (block ? block.call : "")
26
+ @logger&.warn(@component, msg.to_s)
27
+ end
28
+
29
+ def error(message = nil, &block)
30
+ msg = message || (block ? block.call : "")
31
+ @logger&.error(@component, msg.to_s)
32
+ end
33
+
34
+ def fatal(message = nil, &block)
35
+ msg = message || (block ? block.call : "")
36
+ @logger&.error(@component, msg.to_s)
37
+ end
38
+
39
+ def level
40
+ :debug
41
+ end
42
+
43
+ def level=(val)
44
+ # no-op
45
+ end
46
+ end
47
+
48
+ # Adapter for using the AgentHarness gem within AIDP
49
+ #
50
+ # This adapter bridges AIDP's existing provider interface with the
51
+ # new AgentHarness gem, allowing gradual migration.
52
+ #
53
+ # Usage:
54
+ # adapter = Aidp::AgentHarnessAdapter.new(config)
55
+ # response = adapter.send_message(prompt: "Hello", provider: :claude)
56
+ #
57
+ class AgentHarnessAdapter
58
+ attr_reader :conductor
59
+
60
+ # Create a new adapter
61
+ #
62
+ # @param aidp_config [Aidp::Config] AIDP configuration
63
+ # @param logger [Logger] logger instance
64
+ def initialize(aidp_config, logger: nil)
65
+ @aidp_config = aidp_config
66
+ @logger = logger || Aidp.logger
67
+
68
+ configure_agent_harness
69
+ end
70
+
71
+ # Send a message through AgentHarness
72
+ #
73
+ # @param prompt [String] the prompt to send
74
+ # @param provider [Symbol, nil] provider to use
75
+ # @param options [Hash] additional options
76
+ # @return [Hash] AIDP-compatible response
77
+ def send_message(prompt:, provider: nil, **options)
78
+ start_time = Time.now
79
+
80
+ # Map AIDP options to AgentHarness options
81
+ harness_options = map_options(options)
82
+
83
+ # Use the conductor for orchestrated requests
84
+ response = @conductor.send_message(prompt, provider: provider, **harness_options)
85
+
86
+ # Convert Response to AIDP-compatible hash
87
+ convert_response(response, Time.now - start_time)
88
+ rescue AgentHarness::RateLimitError => e
89
+ handle_rate_limit(e, provider)
90
+ rescue AgentHarness::NoProvidersAvailableError => e
91
+ handle_no_providers(e)
92
+ rescue AgentHarness::Error => e
93
+ handle_error(e, provider)
94
+ end
95
+
96
+ # Get a specific provider instance
97
+ #
98
+ # @param name [Symbol] provider name
99
+ # @return [AgentHarness::Providers::Base] provider instance
100
+ def provider(name)
101
+ @conductor.provider_manager.get_provider(name)
102
+ end
103
+
104
+ # Check if a provider is available
105
+ #
106
+ # @param name [Symbol] provider name
107
+ # @return [Boolean] true if available
108
+ def provider_available?(name)
109
+ provider_class = AgentHarness::Providers::Registry.instance.get(name)
110
+ provider_class.available?
111
+ rescue AgentHarness::ConfigurationError
112
+ false
113
+ end
114
+
115
+ # Get orchestration status
116
+ #
117
+ # @return [Hash] status information
118
+ def status
119
+ @conductor.status
120
+ end
121
+
122
+ # Get token usage summary
123
+ #
124
+ # @return [Hash] token usage
125
+ def token_summary
126
+ AgentHarness.token_tracker.summary
127
+ end
128
+
129
+ # Register callback for token events
130
+ #
131
+ # @yield [TokenEvent] token event
132
+ def on_tokens_used(&block)
133
+ AgentHarness.token_tracker.on_tokens_used(&block)
134
+ end
135
+
136
+ # Reset the adapter (useful for testing)
137
+ def reset!
138
+ @conductor.reset!
139
+ AgentHarness.token_tracker.clear!
140
+ end
141
+
142
+ private
143
+
144
+ def configure_agent_harness
145
+ AgentHarness.configure do |config|
146
+ config.logger = LoggerAdapter.new(@logger)
147
+ config.log_level = begin
148
+ @aidp_config.log_level
149
+ rescue
150
+ :info
151
+ end
152
+ config.default_timeout = begin
153
+ @aidp_config.default_timeout
154
+ rescue
155
+ 300
156
+ end
157
+
158
+ # Set default provider from AIDP config
159
+ config.default_provider = map_provider_name(@aidp_config.default_provider)
160
+
161
+ # Configure fallback providers
162
+ config.fallback_providers = (@aidp_config.fallback_providers || []).map { |p| map_provider_name(p) }
163
+
164
+ # Configure orchestration
165
+ config.orchestration do |orch|
166
+ orch.enabled = true
167
+ orch.auto_switch_on_error = true
168
+ orch.auto_switch_on_rate_limit = true
169
+
170
+ orch.circuit_breaker do |cb|
171
+ cb.enabled = true
172
+ cb.failure_threshold = 5
173
+ cb.timeout = 300
174
+ end
175
+
176
+ orch.retry do |r|
177
+ r.enabled = true
178
+ r.max_attempts = 3
179
+ r.base_delay = 1.0
180
+ end
181
+ end
182
+
183
+ # Configure providers from AIDP config
184
+ configure_providers(config)
185
+
186
+ # Register token usage callback
187
+ config.on_tokens_used do |event|
188
+ Aidp.log_debug("agent_harness_adapter", "token_usage",
189
+ provider: event.provider,
190
+ total_tokens: event.total_tokens)
191
+ end
192
+
193
+ # Register provider switch callback
194
+ config.on_provider_switch do |event|
195
+ Aidp.log_info("agent_harness_adapter", "provider_switch",
196
+ from: event[:from],
197
+ to: event[:to],
198
+ reason: event[:reason])
199
+ end
200
+ end
201
+
202
+ @conductor = AgentHarness.conductor
203
+ end
204
+
205
+ def configure_providers(config)
206
+ # Configure enabled providers from AIDP config
207
+ provider_configs = begin
208
+ @aidp_config.providers
209
+ rescue
210
+ {}
211
+ end
212
+
213
+ provider_configs.each do |name, provider_config|
214
+ harness_name = map_provider_name(name)
215
+
216
+ config.provider(harness_name) do |p|
217
+ p.enabled = provider_config[:enabled] != false
218
+ p.type = provider_config[:type]&.to_sym || :usage_based
219
+ p.priority = provider_config[:priority] || 10
220
+ p.timeout = provider_config[:timeout]
221
+ p.model = provider_config[:model]
222
+ p.models = provider_config[:models] || []
223
+ end
224
+ end
225
+
226
+ # Ensure default provider is configured
227
+ unless config.providers.key?(config.default_provider)
228
+ config.provider(config.default_provider) { |p| p.enabled = true }
229
+ end
230
+ end
231
+
232
+ def map_provider_name(name)
233
+ case name.to_s
234
+ when "anthropic", "claude"
235
+ :claude
236
+ when "github_copilot", "copilot"
237
+ :github_copilot
238
+ else
239
+ name.to_sym
240
+ end
241
+ end
242
+
243
+ def map_options(options)
244
+ harness_options = {}
245
+
246
+ harness_options[:model] = options[:model] if options[:model]
247
+ harness_options[:timeout] = options[:timeout] if options[:timeout]
248
+ harness_options[:session] = options[:session] if options[:session]
249
+ harness_options[:dangerous_mode] = options[:dangerous] if options[:dangerous]
250
+ harness_options[:tier] = options[:tier] if options[:tier]
251
+
252
+ harness_options
253
+ end
254
+
255
+ def convert_response(response, duration)
256
+ {
257
+ output: response.output,
258
+ success: response.success?,
259
+ exit_code: response.exit_code,
260
+ provider: response.provider,
261
+ model: response.model,
262
+ duration: duration,
263
+ tokens: response.tokens,
264
+ error: response.error
265
+ }
266
+ end
267
+
268
+ def handle_rate_limit(error, provider)
269
+ Aidp.log_warn("agent_harness_adapter", "rate_limited",
270
+ provider: provider,
271
+ reset_time: error.reset_time)
272
+
273
+ {
274
+ output: nil,
275
+ success: false,
276
+ error: error.message,
277
+ rate_limited: true,
278
+ reset_time: error.reset_time
279
+ }
280
+ end
281
+
282
+ def handle_no_providers(error)
283
+ Aidp.log_error("agent_harness_adapter", "no_providers_available",
284
+ attempted: error.attempted_providers)
285
+
286
+ {
287
+ output: nil,
288
+ success: false,
289
+ error: error.message,
290
+ no_providers: true,
291
+ attempted_providers: error.attempted_providers
292
+ }
293
+ end
294
+
295
+ def handle_error(error, provider)
296
+ Aidp.log_error("agent_harness_adapter", "provider_error",
297
+ provider: provider,
298
+ error: error.class.name,
299
+ message: error.message)
300
+
301
+ {
302
+ output: nil,
303
+ success: false,
304
+ error: error.message,
305
+ provider: provider
306
+ }
307
+ end
308
+ end
309
+ end
@@ -19,7 +19,8 @@ module Aidp
19
19
  # @param gh_available [Boolean, nil] (test-only) forcibly sets whether gh CLI is considered
20
20
  # available. When nil (default) we auto-detect. This enables deterministic specs without
21
21
  # depending on developer environment.
22
- def initialize(gh_available: nil, enable_bootstrap: true)
22
+ # @param project_dir [String] (optional) working directory for the project. Defaults to current directory.
23
+ def initialize(gh_available: nil, enable_bootstrap: true, project_dir: nil)
23
24
  disabled_via_env = ENV["AIDP_DISABLE_GH_CLI"] == "1"
24
25
  @gh_available = if disabled_via_env
25
26
  false
@@ -27,6 +28,7 @@ module Aidp
27
28
  gh_available.nil? ? gh_cli_available? : gh_available
28
29
  end
29
30
  @enable_bootstrap = enable_bootstrap
31
+ @project_dir_override = project_dir
30
32
  Aidp.log_debug(COMPONENT, "Initialized importer", gh_available: @gh_available, enable_bootstrap: @enable_bootstrap, disabled_via_env: disabled_via_env)
31
33
  Aidp.log_debug(COMPONENT, "GitHub CLI disabled via env flag") if disabled_via_env
32
34
  end
@@ -244,7 +246,7 @@ module Aidp
244
246
  prompt_content = generate_prompt_content(issue_data)
245
247
 
246
248
  # Use PromptManager to write to .aidp/PROMPT.md and archive immediately
247
- prompt_manager = Aidp::Execute::PromptManager.new(Dir.pwd)
249
+ prompt_manager = Aidp::Execute::PromptManager.new(project_dir)
248
250
  step_name = "github_issue_#{issue_data[:number]}"
249
251
  prompt_manager.write(prompt_content, step_name: step_name)
250
252
 
@@ -261,9 +263,9 @@ module Aidp
261
263
 
262
264
  ## Instructions
263
265
  You are working on a GitHub issue imported into AIDP. Your responsibilities:
264
- 1. Read this PROMPT.md file to understand what needs to be done
266
+ 1. Read this file (`.aidp/PROMPT.md`) to understand what needs to be done
265
267
  2. Complete the work described in the issue below
266
- 3. **IMPORTANT**: Edit this PROMPT.md file yourself to:
268
+ 3. **IMPORTANT**: Edit this `.aidp/PROMPT.md` file to:
267
269
  - Remove completed items
268
270
  - Update with current status
269
271
  - Keep it concise (remove unnecessary context)
@@ -272,7 +274,7 @@ module Aidp
272
274
  5. If tests/linters fail, you'll see the errors in the next iteration
273
275
 
274
276
  ## Completion Criteria
275
- Mark this issue COMPLETE by adding this line to PROMPT.md:
277
+ Mark this issue COMPLETE by adding this line to `.aidp/PROMPT.md`:
276
278
  ```
277
279
  STATUS: COMPLETE
278
280
  ```
@@ -487,12 +489,24 @@ module Aidp
487
489
  + (result.lint_commands.empty? ? "" : "Lint Commands:\n#{result.lint_commands.map { |c| "- #{c}" }.join("\n")}\n")
488
490
 
489
491
  # Use PromptManager to append to .aidp/PROMPT.md (issue #226)
490
- prompt_manager = Aidp::Execute::PromptManager.new(Dir.pwd)
492
+ prompt_manager = Aidp::Execute::PromptManager.new(project_dir)
491
493
  current_prompt = prompt_manager.read
492
494
  updated_prompt = current_prompt + "\n---\n\n#{tooling_info}"
493
495
  prompt_manager.write(updated_prompt, step_name: "github_issue_tooling")
494
496
 
495
497
  display_message("🧪 Detected tooling and appended to PROMPT.md", type: :info)
496
498
  end
499
+
500
+ def project_dir
501
+ @project_dir_override || safe_pwd
502
+ end
503
+
504
+ def safe_pwd
505
+ Dir.pwd
506
+ rescue Errno::ENOENT
507
+ # If the current directory no longer exists (e.g., in test environment),
508
+ # use ENV["AIDP_PROJECT_DIR"] or fallback to "."
509
+ ENV["AIDP_PROJECT_DIR"] || "."
510
+ end
497
511
  end
498
512
  end
@@ -311,7 +311,7 @@ module Aidp
311
311
 
312
312
  jobs << job_info
313
313
  rescue JSON::ParserError => e
314
- display_message("Warning: Could not parse harness log #{log_file}: #{e.message}", type: :warning) if ENV["AIDP_DEBUG"]
314
+ display_message("Warning: Could not parse harness log #{log_file}: #{e.message}", type: :warning) if Aidp.debug_env_enabled?
315
315
  end
316
316
 
317
317
  # Sort by creation time (newest first)
@@ -3,6 +3,7 @@
3
3
  require "tty-table"
4
4
  require "tty-prompt"
5
5
  require "tty-spinner"
6
+ require "agent_harness"
6
7
  require_relative "../harness/model_registry"
7
8
  require_relative "../harness/ruby_llm_registry"
8
9
 
@@ -208,26 +209,19 @@ module Aidp
208
209
 
209
210
  def find_providers_for_family(family_name)
210
211
  providers = []
212
+ registry = AgentHarness::Providers::Registry.instance
211
213
 
212
- # Check each provider adapter for support
213
- provider_classes = [
214
- Aidp::Providers::Anthropic,
215
- Aidp::Providers::Cursor,
216
- Aidp::Providers::Gemini
217
- ]
218
-
219
- provider_classes.each do |provider_class|
214
+ # Check each registered provider for support
215
+ registry.all.each do |provider_name|
216
+ provider_class = registry.get(provider_name)
220
217
  next unless provider_class.respond_to?(:supports_model_family?)
221
218
 
222
219
  if provider_class.supports_model_family?(family_name)
223
- # Get the provider name from an instance (need to instantiate to call name method)
224
- # Or use a simple name mapping
225
- provider_name = provider_class.name.split("::").last.downcase
226
- providers << provider_name
220
+ providers << provider_name.to_s
227
221
  end
228
222
  rescue => e
229
223
  # Log but don't fail if provider check fails
230
- Aidp.log_debug("models_command", "provider check failed", provider: provider_class.name, error: e.message)
224
+ Aidp.log_debug("models_command", "provider check failed", provider: provider_name, error: e.message)
231
225
  end
232
226
 
233
227
  providers
@@ -455,9 +449,8 @@ module Aidp
455
449
  end
456
450
 
457
451
  def get_provider_class(provider_name)
458
- class_name = "Aidp::Providers::#{provider_name.capitalize}"
459
- Object.const_get(class_name)
460
- rescue NameError
452
+ AgentHarness::Providers::Registry.instance.get(provider_name.to_sym)
453
+ rescue AgentHarness::ConfigurationError
461
454
  nil
462
455
  end
463
456