aidp 0.27.0 โ 0.28.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 +89 -0
- data/lib/aidp/cli/models_command.rb +5 -6
- data/lib/aidp/cli.rb +10 -8
- data/lib/aidp/config.rb +54 -0
- data/lib/aidp/debug_mixin.rb +23 -1
- data/lib/aidp/execute/agent_signal_parser.rb +22 -0
- data/lib/aidp/execute/repl_macros.rb +2 -2
- data/lib/aidp/execute/steps.rb +94 -1
- data/lib/aidp/execute/work_loop_runner.rb +209 -17
- data/lib/aidp/execute/workflow_selector.rb +2 -25
- data/lib/aidp/firewall/provider_requirements_collector.rb +262 -0
- data/lib/aidp/harness/ai_decision_engine.rb +35 -2
- data/lib/aidp/harness/config_manager.rb +0 -5
- data/lib/aidp/harness/config_schema.rb +8 -0
- data/lib/aidp/harness/configuration.rb +27 -19
- data/lib/aidp/harness/enhanced_runner.rb +1 -4
- data/lib/aidp/harness/error_handler.rb +1 -72
- data/lib/aidp/harness/provider_factory.rb +11 -2
- data/lib/aidp/harness/state_manager.rb +0 -7
- data/lib/aidp/harness/thinking_depth_manager.rb +47 -68
- data/lib/aidp/harness/ui/enhanced_tui.rb +8 -18
- data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +0 -18
- data/lib/aidp/harness/ui/progress_display.rb +6 -2
- data/lib/aidp/harness/user_interface.rb +0 -58
- data/lib/aidp/init/runner.rb +7 -2
- data/lib/aidp/planning/analyzers/feedback_analyzer.rb +365 -0
- data/lib/aidp/planning/builders/agile_plan_builder.rb +387 -0
- data/lib/aidp/planning/builders/project_plan_builder.rb +193 -0
- data/lib/aidp/planning/generators/gantt_generator.rb +190 -0
- data/lib/aidp/planning/generators/iteration_plan_generator.rb +392 -0
- data/lib/aidp/planning/generators/legacy_research_planner.rb +473 -0
- data/lib/aidp/planning/generators/marketing_report_generator.rb +348 -0
- data/lib/aidp/planning/generators/mvp_scope_generator.rb +310 -0
- data/lib/aidp/planning/generators/user_test_plan_generator.rb +373 -0
- data/lib/aidp/planning/generators/wbs_generator.rb +259 -0
- data/lib/aidp/planning/mappers/persona_mapper.rb +163 -0
- data/lib/aidp/planning/parsers/document_parser.rb +141 -0
- data/lib/aidp/planning/parsers/feedback_data_parser.rb +252 -0
- data/lib/aidp/provider_manager.rb +8 -32
- data/lib/aidp/providers/aider.rb +264 -0
- data/lib/aidp/providers/anthropic.rb +74 -2
- data/lib/aidp/providers/base.rb +25 -1
- data/lib/aidp/providers/codex.rb +26 -3
- data/lib/aidp/providers/cursor.rb +16 -0
- data/lib/aidp/providers/gemini.rb +13 -0
- data/lib/aidp/providers/github_copilot.rb +17 -0
- data/lib/aidp/providers/kilocode.rb +11 -0
- data/lib/aidp/providers/opencode.rb +11 -0
- data/lib/aidp/setup/wizard.rb +249 -39
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/build_processor.rb +211 -30
- data/lib/aidp/watch/change_request_processor.rb +128 -14
- data/lib/aidp/watch/ci_fix_processor.rb +103 -37
- data/lib/aidp/watch/ci_log_extractor.rb +258 -0
- data/lib/aidp/watch/github_state_extractor.rb +177 -0
- data/lib/aidp/watch/implementation_verifier.rb +284 -0
- data/lib/aidp/watch/plan_generator.rb +7 -43
- data/lib/aidp/watch/plan_processor.rb +7 -6
- data/lib/aidp/watch/repository_client.rb +245 -17
- data/lib/aidp/watch/review_processor.rb +98 -17
- data/lib/aidp/watch/reviewers/base_reviewer.rb +1 -1
- data/lib/aidp/watch/runner.rb +181 -29
- data/lib/aidp/watch/state_store.rb +22 -1
- data/lib/aidp/workflows/definitions.rb +147 -0
- data/lib/aidp/workstream_cleanup.rb +245 -0
- data/lib/aidp/worktree.rb +19 -0
- data/templates/aidp.yml.example +57 -0
- data/templates/implementation/generate_tdd_specs.md +213 -0
- data/templates/implementation/iterative_implementation.md +122 -0
- data/templates/planning/agile/analyze_feedback.md +183 -0
- data/templates/planning/agile/generate_iteration_plan.md +179 -0
- data/templates/planning/agile/generate_legacy_research_plan.md +171 -0
- data/templates/planning/agile/generate_marketing_report.md +162 -0
- data/templates/planning/agile/generate_mvp_scope.md +127 -0
- data/templates/planning/agile/generate_user_test_plan.md +143 -0
- data/templates/planning/agile/ingest_feedback.md +174 -0
- data/templates/planning/assemble_project_plan.md +113 -0
- data/templates/planning/assign_personas.md +108 -0
- data/templates/planning/create_tasks.md +52 -6
- data/templates/planning/generate_gantt.md +86 -0
- data/templates/planning/generate_wbs.md +85 -0
- data/templates/planning/initialize_planning_mode.md +70 -0
- data/templates/skills/README.md +2 -2
- data/templates/skills/marketing_strategist/SKILL.md +279 -0
- data/templates/skills/product_manager/SKILL.md +177 -0
- data/templates/skills/ruby_aidp_planning/SKILL.md +497 -0
- data/templates/skills/ruby_rspec_tdd/SKILL.md +514 -0
- data/templates/skills/ux_researcher/SKILL.md +222 -0
- metadata +39 -1
data/lib/aidp/watch/runner.rb
CHANGED
|
@@ -6,6 +6,7 @@ require_relative "../message_display"
|
|
|
6
6
|
require_relative "repository_client"
|
|
7
7
|
require_relative "repository_safety_checker"
|
|
8
8
|
require_relative "state_store"
|
|
9
|
+
require_relative "github_state_extractor"
|
|
9
10
|
require_relative "plan_generator"
|
|
10
11
|
require_relative "plan_processor"
|
|
11
12
|
require_relative "build_processor"
|
|
@@ -40,10 +41,21 @@ module Aidp
|
|
|
40
41
|
config: safety_config
|
|
41
42
|
)
|
|
42
43
|
@state_store = StateStore.new(project_dir: project_dir, repository: "#{owner}/#{repo}")
|
|
44
|
+
@state_extractor = GitHubStateExtractor.new(repository_client: @repository_client)
|
|
43
45
|
|
|
44
46
|
# Extract label configuration from safety_config (it's actually the full watch config)
|
|
45
47
|
label_config = safety_config[:labels] || safety_config["labels"] || {}
|
|
46
48
|
|
|
49
|
+
# Extract detection comment configuration (issue #280)
|
|
50
|
+
# Enabled by default, can be disabled in config
|
|
51
|
+
@post_detection_comments = if safety_config.key?(:post_detection_comments)
|
|
52
|
+
safety_config[:post_detection_comments]
|
|
53
|
+
elsif safety_config.key?("post_detection_comments")
|
|
54
|
+
safety_config["post_detection_comments"]
|
|
55
|
+
else
|
|
56
|
+
true # Enabled by default
|
|
57
|
+
end
|
|
58
|
+
|
|
47
59
|
@plan_processor = PlanProcessor.new(
|
|
48
60
|
repository_client: @repository_client,
|
|
49
61
|
state_store: @state_store,
|
|
@@ -138,7 +150,12 @@ module Aidp
|
|
|
138
150
|
|
|
139
151
|
def process_plan_triggers
|
|
140
152
|
plan_label = @plan_processor.plan_label
|
|
141
|
-
|
|
153
|
+
begin
|
|
154
|
+
issues = @repository_client.list_issues(labels: [plan_label], state: "open")
|
|
155
|
+
rescue => e
|
|
156
|
+
Aidp.log_error("watch_runner", "plan_poll_failed", label: plan_label, error: e.message)
|
|
157
|
+
return # Skip this cycle, continue watch loop
|
|
158
|
+
end
|
|
142
159
|
Aidp.log_debug("watch_runner", "plan_poll", label: plan_label, total: issues.size)
|
|
143
160
|
issues.each do |issue|
|
|
144
161
|
unless issue_has_label?(issue, plan_label)
|
|
@@ -146,7 +163,18 @@ module Aidp
|
|
|
146
163
|
next
|
|
147
164
|
end
|
|
148
165
|
|
|
149
|
-
|
|
166
|
+
begin
|
|
167
|
+
detailed = @repository_client.fetch_issue(issue[:number])
|
|
168
|
+
rescue => e
|
|
169
|
+
Aidp.log_error("watch_runner", "fetch_issue_failed", issue: issue[:number], error: e.message)
|
|
170
|
+
next # Skip this issue, continue with others
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Check if already in progress by another instance
|
|
174
|
+
if @state_extractor.in_progress?(detailed)
|
|
175
|
+
Aidp.log_debug("watch_runner", "plan_skip_in_progress", issue: detailed[:number])
|
|
176
|
+
next
|
|
177
|
+
end
|
|
150
178
|
|
|
151
179
|
# Check author authorization before processing
|
|
152
180
|
unless @safety_checker.should_process_issue?(detailed, enforce: false)
|
|
@@ -154,6 +182,11 @@ module Aidp
|
|
|
154
182
|
next
|
|
155
183
|
end
|
|
156
184
|
|
|
185
|
+
# Check if detection comment already posted (deduplication)
|
|
186
|
+
unless @state_extractor.detection_comment_posted?(detailed, plan_label)
|
|
187
|
+
post_detection_comment(item_type: :issue, number: detailed[:number], label: plan_label)
|
|
188
|
+
end
|
|
189
|
+
|
|
157
190
|
Aidp.log_debug("watch_runner", "plan_process", issue: detailed[:number])
|
|
158
191
|
@plan_processor.process(detailed)
|
|
159
192
|
rescue RepositorySafetyChecker::UnauthorizedAuthorError => e
|
|
@@ -163,38 +196,82 @@ module Aidp
|
|
|
163
196
|
|
|
164
197
|
def process_build_triggers
|
|
165
198
|
build_label = @build_processor.build_label
|
|
166
|
-
|
|
199
|
+
begin
|
|
200
|
+
issues = @repository_client.list_issues(labels: [build_label], state: "open")
|
|
201
|
+
rescue => e
|
|
202
|
+
Aidp.log_error("watch_runner", "build_poll_failed", label: build_label, error: e.message)
|
|
203
|
+
return # Skip this cycle, continue watch loop
|
|
204
|
+
end
|
|
167
205
|
Aidp.log_debug("watch_runner", "build_poll", label: build_label, total: issues.size)
|
|
168
206
|
issues.each do |issue|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
207
|
+
detailed = nil
|
|
208
|
+
in_progress_added = false
|
|
209
|
+
|
|
210
|
+
begin
|
|
211
|
+
unless issue_has_label?(issue, build_label)
|
|
212
|
+
Aidp.log_debug("watch_runner", "build_skip_label_mismatch", issue: issue[:number], labels: issue[:labels])
|
|
213
|
+
next
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
begin
|
|
217
|
+
detailed = @repository_client.fetch_issue(issue[:number])
|
|
218
|
+
rescue => e
|
|
219
|
+
Aidp.log_error("watch_runner", "fetch_issue_failed", issue: issue[:number], error: e.message)
|
|
220
|
+
next # Skip this issue, continue with others
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Check if already completed (via GitHub comments)
|
|
224
|
+
if @state_extractor.build_completed?(detailed)
|
|
225
|
+
Aidp.log_debug("watch_runner", "build_skip_completed", issue: detailed[:number])
|
|
226
|
+
next
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Check if already in progress by another instance
|
|
230
|
+
if @state_extractor.in_progress?(detailed)
|
|
231
|
+
Aidp.log_debug("watch_runner", "build_skip_in_progress", issue: detailed[:number])
|
|
232
|
+
next
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Check author authorization before processing
|
|
236
|
+
unless @safety_checker.should_process_issue?(detailed, enforce: false)
|
|
237
|
+
Aidp.log_debug("watch_runner", "build_skip_unauthorized_author", issue: detailed[:number], author: detailed[:author])
|
|
238
|
+
next
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Check if detection comment already posted (deduplication)
|
|
242
|
+
unless @state_extractor.detection_comment_posted?(detailed, build_label)
|
|
243
|
+
post_detection_comment(item_type: :issue, number: detailed[:number], label: build_label)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Add in-progress label before processing
|
|
247
|
+
@repository_client.add_labels(detailed[:number], GitHubStateExtractor::IN_PROGRESS_LABEL)
|
|
248
|
+
in_progress_added = true
|
|
249
|
+
|
|
250
|
+
Aidp.log_debug("watch_runner", "build_process", issue: detailed[:number])
|
|
251
|
+
@build_processor.process(detailed)
|
|
252
|
+
rescue RepositorySafetyChecker::UnauthorizedAuthorError => e
|
|
253
|
+
Aidp.log_warn("watch_runner", "unauthorized issue author", issue: issue[:number], error: e.message)
|
|
254
|
+
ensure
|
|
255
|
+
# Remove in-progress label when done (only if we added it)
|
|
256
|
+
if in_progress_added && detailed
|
|
257
|
+
begin
|
|
258
|
+
@repository_client.remove_labels(detailed[:number], GitHubStateExtractor::IN_PROGRESS_LABEL)
|
|
259
|
+
rescue => e
|
|
260
|
+
Aidp.log_warn("watch_runner", "failed_to_remove_in_progress_label", issue: detailed[:number], error: e.message)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
172
263
|
end
|
|
173
|
-
|
|
174
|
-
status = @state_store.build_status(issue[:number])
|
|
175
|
-
if status["status"] == "completed"
|
|
176
|
-
Aidp.log_debug("watch_runner", "build_skip_completed", issue: issue[:number])
|
|
177
|
-
next
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
detailed = @repository_client.fetch_issue(issue[:number])
|
|
181
|
-
|
|
182
|
-
# Check author authorization before processing
|
|
183
|
-
unless @safety_checker.should_process_issue?(detailed, enforce: false)
|
|
184
|
-
Aidp.log_debug("watch_runner", "build_skip_unauthorized_author", issue: detailed[:number], author: detailed[:author])
|
|
185
|
-
next
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
Aidp.log_debug("watch_runner", "build_process", issue: detailed[:number])
|
|
189
|
-
@build_processor.process(detailed)
|
|
190
|
-
rescue RepositorySafetyChecker::UnauthorizedAuthorError => e
|
|
191
|
-
Aidp.log_warn("watch_runner", "unauthorized issue author", issue: issue[:number], error: e.message)
|
|
192
264
|
end
|
|
193
265
|
end
|
|
194
266
|
|
|
195
267
|
def process_review_triggers
|
|
196
268
|
review_label = @review_processor.review_label
|
|
197
|
-
|
|
269
|
+
begin
|
|
270
|
+
prs = @repository_client.list_pull_requests(labels: [review_label], state: "open")
|
|
271
|
+
rescue => e
|
|
272
|
+
Aidp.log_error("watch_runner", "review_poll_failed", label: review_label, error: e.message)
|
|
273
|
+
return # Skip this cycle, continue watch loop
|
|
274
|
+
end
|
|
198
275
|
Aidp.log_debug("watch_runner", "review_poll", label: review_label, total: prs.size)
|
|
199
276
|
prs.each do |pr|
|
|
200
277
|
unless pr_has_label?(pr, review_label)
|
|
@@ -202,7 +279,18 @@ module Aidp
|
|
|
202
279
|
next
|
|
203
280
|
end
|
|
204
281
|
|
|
205
|
-
|
|
282
|
+
begin
|
|
283
|
+
detailed = @repository_client.fetch_pull_request(pr[:number])
|
|
284
|
+
rescue => e
|
|
285
|
+
Aidp.log_error("watch_runner", "fetch_pr_failed", pr: pr[:number], error: e.message)
|
|
286
|
+
next # Skip this PR, continue with others
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Check if already in progress by another instance
|
|
290
|
+
if @state_extractor.in_progress?(detailed)
|
|
291
|
+
Aidp.log_debug("watch_runner", "review_skip_in_progress", pr: detailed[:number])
|
|
292
|
+
next
|
|
293
|
+
end
|
|
206
294
|
|
|
207
295
|
# Check author authorization before processing
|
|
208
296
|
unless @safety_checker.should_process_issue?(detailed, enforce: false)
|
|
@@ -210,6 +298,11 @@ module Aidp
|
|
|
210
298
|
next
|
|
211
299
|
end
|
|
212
300
|
|
|
301
|
+
# Check if detection comment already posted (deduplication)
|
|
302
|
+
unless @state_extractor.detection_comment_posted?(detailed, review_label)
|
|
303
|
+
post_detection_comment(item_type: :pr, number: detailed[:number], label: review_label)
|
|
304
|
+
end
|
|
305
|
+
|
|
213
306
|
Aidp.log_debug("watch_runner", "review_process", pr: detailed[:number])
|
|
214
307
|
@review_processor.process(detailed)
|
|
215
308
|
rescue RepositorySafetyChecker::UnauthorizedAuthorError => e
|
|
@@ -229,12 +322,23 @@ module Aidp
|
|
|
229
322
|
|
|
230
323
|
detailed = @repository_client.fetch_pull_request(pr[:number])
|
|
231
324
|
|
|
325
|
+
# Check if already in progress by another instance
|
|
326
|
+
if @state_extractor.in_progress?(detailed)
|
|
327
|
+
Aidp.log_debug("watch_runner", "ci_fix_skip_in_progress", pr: detailed[:number])
|
|
328
|
+
next
|
|
329
|
+
end
|
|
330
|
+
|
|
232
331
|
# Check author authorization before processing
|
|
233
332
|
unless @safety_checker.should_process_issue?(detailed, enforce: false)
|
|
234
333
|
Aidp.log_debug("watch_runner", "ci_fix_skip_unauthorized_author", pr: detailed[:number], author: detailed[:author])
|
|
235
334
|
next
|
|
236
335
|
end
|
|
237
336
|
|
|
337
|
+
# Check if detection comment already posted (deduplication)
|
|
338
|
+
unless @state_extractor.detection_comment_posted?(detailed, ci_fix_label)
|
|
339
|
+
post_detection_comment(item_type: :pr, number: detailed[:number], label: ci_fix_label)
|
|
340
|
+
end
|
|
341
|
+
|
|
238
342
|
Aidp.log_debug("watch_runner", "ci_fix_process", pr: detailed[:number])
|
|
239
343
|
@ci_fix_processor.process(detailed)
|
|
240
344
|
rescue RepositorySafetyChecker::UnauthorizedAuthorError => e
|
|
@@ -254,12 +358,23 @@ module Aidp
|
|
|
254
358
|
|
|
255
359
|
detailed = @repository_client.fetch_pull_request(pr[:number])
|
|
256
360
|
|
|
361
|
+
# Check if already in progress by another instance
|
|
362
|
+
if @state_extractor.in_progress?(detailed)
|
|
363
|
+
Aidp.log_debug("watch_runner", "change_request_skip_in_progress", pr: detailed[:number])
|
|
364
|
+
next
|
|
365
|
+
end
|
|
366
|
+
|
|
257
367
|
# Check author authorization before processing
|
|
258
368
|
unless @safety_checker.should_process_issue?(detailed, enforce: false)
|
|
259
369
|
Aidp.log_debug("watch_runner", "change_request_skip_unauthorized_author", pr: detailed[:number], author: detailed[:author])
|
|
260
370
|
next
|
|
261
371
|
end
|
|
262
372
|
|
|
373
|
+
# Check if detection comment already posted (deduplication)
|
|
374
|
+
unless @state_extractor.detection_comment_posted?(detailed, change_request_label)
|
|
375
|
+
post_detection_comment(item_type: :pr, number: detailed[:number], label: change_request_label)
|
|
376
|
+
end
|
|
377
|
+
|
|
263
378
|
Aidp.log_debug("watch_runner", "change_request_process", pr: detailed[:number])
|
|
264
379
|
@change_request_processor.process(detailed)
|
|
265
380
|
rescue RepositorySafetyChecker::UnauthorizedAuthorError => e
|
|
@@ -269,7 +384,7 @@ module Aidp
|
|
|
269
384
|
|
|
270
385
|
def issue_has_label?(issue, label)
|
|
271
386
|
Array(issue[:labels]).any? do |issue_label|
|
|
272
|
-
name = issue_label.is_a?(Hash) ? issue_label["name"] : issue_label.to_s
|
|
387
|
+
name = (issue_label.is_a?(Hash) ? issue_label["name"] : issue_label.to_s)
|
|
273
388
|
name.casecmp(label).zero?
|
|
274
389
|
end
|
|
275
390
|
end
|
|
@@ -371,9 +486,46 @@ module Aidp
|
|
|
371
486
|
{}
|
|
372
487
|
end
|
|
373
488
|
|
|
489
|
+
# Post detection comment to GitHub when aidp picks up a labeled item (issue #280)
|
|
490
|
+
# @param item_type [Symbol] Type of item (:issue or :pr)
|
|
491
|
+
# @param number [Integer] Issue or PR number
|
|
492
|
+
# @param label [String] Label that triggered detection
|
|
493
|
+
def post_detection_comment(item_type:, number:, label:)
|
|
494
|
+
return unless @post_detection_comments
|
|
495
|
+
|
|
496
|
+
# Check if we've already posted a detection comment for this item/label combination
|
|
497
|
+
detection_key = "#{item_type}_#{number}_#{label}"
|
|
498
|
+
return if @state_store.detection_comment_posted?(detection_key)
|
|
499
|
+
|
|
500
|
+
timestamp = Time.now.utc.iso8601
|
|
501
|
+
item_name = (item_type == :pr) ? "PR" : "issue"
|
|
502
|
+
|
|
503
|
+
comment_body = "aidp detected `#{label}` at #{timestamp} and is working on it"
|
|
504
|
+
|
|
505
|
+
begin
|
|
506
|
+
@repository_client.post_comment(number, comment_body)
|
|
507
|
+
@state_store.record_detection_comment(detection_key, timestamp: timestamp)
|
|
508
|
+
|
|
509
|
+
Aidp.log_info("watch_runner", "detection_comment_posted",
|
|
510
|
+
item_type: item_type,
|
|
511
|
+
number: number,
|
|
512
|
+
label: label,
|
|
513
|
+
timestamp: timestamp)
|
|
514
|
+
|
|
515
|
+
display_message("๐ฌ Posted detection comment for #{item_name} ##{number}", type: :info) if @verbose
|
|
516
|
+
rescue => e
|
|
517
|
+
# Don't fail processing if comment posting fails - just log it
|
|
518
|
+
Aidp.log_warn("watch_runner", "detection_comment_failed",
|
|
519
|
+
item_type: item_type,
|
|
520
|
+
number: number,
|
|
521
|
+
label: label,
|
|
522
|
+
error: e.message)
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
374
526
|
def pr_has_label?(pr, label)
|
|
375
527
|
Array(pr[:labels]).any? do |pr_label|
|
|
376
|
-
name = pr_label.is_a?(Hash) ? pr_label["name"] : pr_label.to_s
|
|
528
|
+
name = (pr_label.is_a?(Hash) ? pr_label["name"] : pr_label.to_s)
|
|
377
529
|
name.casecmp(label).zero?
|
|
378
530
|
end
|
|
379
531
|
end
|
|
@@ -124,7 +124,10 @@ module Aidp
|
|
|
124
124
|
"changes_applied" => data[:changes_applied],
|
|
125
125
|
"commits" => data[:commits],
|
|
126
126
|
"reason" => data[:reason],
|
|
127
|
-
"clarification_count" => data[:clarification_count]
|
|
127
|
+
"clarification_count" => data[:clarification_count],
|
|
128
|
+
"verification_reasons" => data[:verification_reasons],
|
|
129
|
+
"missing_items" => data[:missing_items],
|
|
130
|
+
"additional_work" => data[:additional_work]
|
|
128
131
|
}.compact
|
|
129
132
|
|
|
130
133
|
change_requests[pr_number.to_s] = payload
|
|
@@ -136,6 +139,19 @@ module Aidp
|
|
|
136
139
|
save!
|
|
137
140
|
end
|
|
138
141
|
|
|
142
|
+
# Detection comment tracking methods (issue #280)
|
|
143
|
+
def detection_comment_posted?(detection_key)
|
|
144
|
+
detection_comments.key?(detection_key.to_s)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def record_detection_comment(detection_key, timestamp:)
|
|
148
|
+
detection_comments[detection_key.to_s] = {
|
|
149
|
+
"timestamp" => timestamp,
|
|
150
|
+
"posted_at" => Time.now.utc.iso8601
|
|
151
|
+
}
|
|
152
|
+
save!
|
|
153
|
+
end
|
|
154
|
+
|
|
139
155
|
private
|
|
140
156
|
|
|
141
157
|
def ensure_directory
|
|
@@ -167,6 +183,7 @@ module Aidp
|
|
|
167
183
|
base["reviews"] ||= {}
|
|
168
184
|
base["ci_fixes"] ||= {}
|
|
169
185
|
base["change_requests"] ||= {}
|
|
186
|
+
base["detection_comments"] ||= {}
|
|
170
187
|
base
|
|
171
188
|
end
|
|
172
189
|
end
|
|
@@ -191,6 +208,10 @@ module Aidp
|
|
|
191
208
|
state["change_requests"]
|
|
192
209
|
end
|
|
193
210
|
|
|
211
|
+
def detection_comments
|
|
212
|
+
state["detection_comments"]
|
|
213
|
+
end
|
|
214
|
+
|
|
194
215
|
def stringify_keys(hash)
|
|
195
216
|
return {} unless hash
|
|
196
217
|
|
|
@@ -165,6 +165,26 @@ module Aidp
|
|
|
165
165
|
]
|
|
166
166
|
},
|
|
167
167
|
|
|
168
|
+
tdd_feature_development: {
|
|
169
|
+
name: "TDD Feature Development",
|
|
170
|
+
description: "Test-driven development with tests written first",
|
|
171
|
+
icon: "๐งช",
|
|
172
|
+
details: [
|
|
173
|
+
"Product requirements",
|
|
174
|
+
"Architecture design",
|
|
175
|
+
"TDD test specifications (write tests FIRST)",
|
|
176
|
+
"RED: Tests fail initially",
|
|
177
|
+
"GREEN: Implement to pass tests",
|
|
178
|
+
"REFACTOR: Improve with confidence"
|
|
179
|
+
],
|
|
180
|
+
steps: [
|
|
181
|
+
"00_PRD",
|
|
182
|
+
"02_ARCHITECTURE",
|
|
183
|
+
"17_TDD_SPECIFICATION",
|
|
184
|
+
"16_IMPLEMENTATION"
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
|
|
168
188
|
production_ready: {
|
|
169
189
|
name: "Production-Ready",
|
|
170
190
|
description: "Enterprise-grade with NFRs and compliance",
|
|
@@ -227,6 +247,133 @@ module Aidp
|
|
|
227
247
|
]
|
|
228
248
|
},
|
|
229
249
|
|
|
250
|
+
waterfall_standard: {
|
|
251
|
+
name: "Waterfall Planning",
|
|
252
|
+
description: "Structured project planning with WBS and Gantt charts",
|
|
253
|
+
icon: "๐",
|
|
254
|
+
details: [
|
|
255
|
+
"Documentation ingestion or generation",
|
|
256
|
+
"Work breakdown structure (WBS)",
|
|
257
|
+
"Gantt chart with critical path",
|
|
258
|
+
"Task dependencies and milestones",
|
|
259
|
+
"Persona/agent assignment",
|
|
260
|
+
"Complete project plan"
|
|
261
|
+
],
|
|
262
|
+
steps: [
|
|
263
|
+
"22_PLANNING_MODE_INIT",
|
|
264
|
+
"00_PRD",
|
|
265
|
+
"02_ARCHITECTURE",
|
|
266
|
+
"18_WBS",
|
|
267
|
+
"19_GANTT_CHART",
|
|
268
|
+
"20_PERSONA_ASSIGNMENT",
|
|
269
|
+
"21_PROJECT_PLAN_ASSEMBLY",
|
|
270
|
+
"16_IMPLEMENTATION"
|
|
271
|
+
]
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
waterfall_minimal: {
|
|
275
|
+
name: "Waterfall Planning (Minimal)",
|
|
276
|
+
description: "Quick waterfall planning without full enterprise features",
|
|
277
|
+
icon: "๐",
|
|
278
|
+
details: [
|
|
279
|
+
"Essential documentation",
|
|
280
|
+
"Basic work breakdown",
|
|
281
|
+
"Simple Gantt chart",
|
|
282
|
+
"Task list with dependencies"
|
|
283
|
+
],
|
|
284
|
+
steps: [
|
|
285
|
+
"22_PLANNING_MODE_INIT",
|
|
286
|
+
"00_PRD",
|
|
287
|
+
"18_WBS",
|
|
288
|
+
"16_IMPLEMENTATION"
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
waterfall_tdd: {
|
|
293
|
+
name: "Waterfall Planning with TDD",
|
|
294
|
+
description: "Waterfall planning with test-driven development",
|
|
295
|
+
icon: "๐๐งช",
|
|
296
|
+
details: [
|
|
297
|
+
"Complete waterfall planning",
|
|
298
|
+
"Work breakdown structure",
|
|
299
|
+
"Gantt chart with critical path",
|
|
300
|
+
"TDD test specifications (write tests first)",
|
|
301
|
+
"Test-driven implementation",
|
|
302
|
+
"Persona assignments"
|
|
303
|
+
],
|
|
304
|
+
steps: [
|
|
305
|
+
"22_PLANNING_MODE_INIT",
|
|
306
|
+
"00_PRD",
|
|
307
|
+
"02_ARCHITECTURE",
|
|
308
|
+
"18_WBS",
|
|
309
|
+
"19_GANTT_CHART",
|
|
310
|
+
"17_TDD_SPECIFICATION",
|
|
311
|
+
"20_PERSONA_ASSIGNMENT",
|
|
312
|
+
"21_PROJECT_PLAN_ASSEMBLY",
|
|
313
|
+
"16_IMPLEMENTATION"
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
agile_mvp: {
|
|
318
|
+
name: "Agile MVP Planning",
|
|
319
|
+
description: "Plan MVP with user testing and marketing",
|
|
320
|
+
icon: "๐",
|
|
321
|
+
details: [
|
|
322
|
+
"MVP scope definition (must-have vs nice-to-have)",
|
|
323
|
+
"User testing plan with surveys and interviews",
|
|
324
|
+
"Marketing materials and messaging",
|
|
325
|
+
"Timeline with Gantt chart",
|
|
326
|
+
"Persona assignments"
|
|
327
|
+
],
|
|
328
|
+
steps: [
|
|
329
|
+
"00_PRD",
|
|
330
|
+
"23_MVP_SCOPE",
|
|
331
|
+
"24_USER_TEST_PLAN",
|
|
332
|
+
"25_MARKETING_REPORT",
|
|
333
|
+
"19_GANTT_CHART",
|
|
334
|
+
"20_PERSONA_ASSIGNMENT",
|
|
335
|
+
"16_IMPLEMENTATION"
|
|
336
|
+
]
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
agile_iteration: {
|
|
340
|
+
name: "Agile Iteration Planning",
|
|
341
|
+
description: "Plan next iteration based on user feedback",
|
|
342
|
+
icon: "๐",
|
|
343
|
+
details: [
|
|
344
|
+
"Ingest user feedback data (CSV/JSON/markdown)",
|
|
345
|
+
"AI-powered feedback analysis",
|
|
346
|
+
"Next iteration plan with tasks",
|
|
347
|
+
"Timeline with Gantt chart",
|
|
348
|
+
"Persona assignments"
|
|
349
|
+
],
|
|
350
|
+
steps: [
|
|
351
|
+
"26_INGEST_FEEDBACK",
|
|
352
|
+
"27_ANALYZE_FEEDBACK",
|
|
353
|
+
"28_ITERATION_PLAN",
|
|
354
|
+
"19_GANTT_CHART",
|
|
355
|
+
"20_PERSONA_ASSIGNMENT",
|
|
356
|
+
"16_IMPLEMENTATION"
|
|
357
|
+
]
|
|
358
|
+
},
|
|
359
|
+
|
|
360
|
+
agile_legacy_research: {
|
|
361
|
+
name: "Legacy Product Research",
|
|
362
|
+
description: "Plan user research for existing codebase",
|
|
363
|
+
icon: "๐",
|
|
364
|
+
details: [
|
|
365
|
+
"Codebase analysis to identify features",
|
|
366
|
+
"User research plan generation",
|
|
367
|
+
"User testing plan with priorities",
|
|
368
|
+
"Improvement recommendations"
|
|
369
|
+
],
|
|
370
|
+
steps: [
|
|
371
|
+
"29_LEGACY_RESEARCH_PLAN",
|
|
372
|
+
"24_USER_TEST_PLAN",
|
|
373
|
+
"16_IMPLEMENTATION"
|
|
374
|
+
]
|
|
375
|
+
},
|
|
376
|
+
|
|
230
377
|
custom: {
|
|
231
378
|
name: "Custom Workflow",
|
|
232
379
|
description: "Choose specific planning and implementation steps",
|