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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +89 -0
  3. data/lib/aidp/cli/models_command.rb +5 -6
  4. data/lib/aidp/cli.rb +10 -8
  5. data/lib/aidp/config.rb +54 -0
  6. data/lib/aidp/debug_mixin.rb +23 -1
  7. data/lib/aidp/execute/agent_signal_parser.rb +22 -0
  8. data/lib/aidp/execute/repl_macros.rb +2 -2
  9. data/lib/aidp/execute/steps.rb +94 -1
  10. data/lib/aidp/execute/work_loop_runner.rb +209 -17
  11. data/lib/aidp/execute/workflow_selector.rb +2 -25
  12. data/lib/aidp/firewall/provider_requirements_collector.rb +262 -0
  13. data/lib/aidp/harness/ai_decision_engine.rb +35 -2
  14. data/lib/aidp/harness/config_manager.rb +0 -5
  15. data/lib/aidp/harness/config_schema.rb +8 -0
  16. data/lib/aidp/harness/configuration.rb +27 -19
  17. data/lib/aidp/harness/enhanced_runner.rb +1 -4
  18. data/lib/aidp/harness/error_handler.rb +1 -72
  19. data/lib/aidp/harness/provider_factory.rb +11 -2
  20. data/lib/aidp/harness/state_manager.rb +0 -7
  21. data/lib/aidp/harness/thinking_depth_manager.rb +47 -68
  22. data/lib/aidp/harness/ui/enhanced_tui.rb +8 -18
  23. data/lib/aidp/harness/ui/enhanced_workflow_selector.rb +0 -18
  24. data/lib/aidp/harness/ui/progress_display.rb +6 -2
  25. data/lib/aidp/harness/user_interface.rb +0 -58
  26. data/lib/aidp/init/runner.rb +7 -2
  27. data/lib/aidp/planning/analyzers/feedback_analyzer.rb +365 -0
  28. data/lib/aidp/planning/builders/agile_plan_builder.rb +387 -0
  29. data/lib/aidp/planning/builders/project_plan_builder.rb +193 -0
  30. data/lib/aidp/planning/generators/gantt_generator.rb +190 -0
  31. data/lib/aidp/planning/generators/iteration_plan_generator.rb +392 -0
  32. data/lib/aidp/planning/generators/legacy_research_planner.rb +473 -0
  33. data/lib/aidp/planning/generators/marketing_report_generator.rb +348 -0
  34. data/lib/aidp/planning/generators/mvp_scope_generator.rb +310 -0
  35. data/lib/aidp/planning/generators/user_test_plan_generator.rb +373 -0
  36. data/lib/aidp/planning/generators/wbs_generator.rb +259 -0
  37. data/lib/aidp/planning/mappers/persona_mapper.rb +163 -0
  38. data/lib/aidp/planning/parsers/document_parser.rb +141 -0
  39. data/lib/aidp/planning/parsers/feedback_data_parser.rb +252 -0
  40. data/lib/aidp/provider_manager.rb +8 -32
  41. data/lib/aidp/providers/aider.rb +264 -0
  42. data/lib/aidp/providers/anthropic.rb +74 -2
  43. data/lib/aidp/providers/base.rb +25 -1
  44. data/lib/aidp/providers/codex.rb +26 -3
  45. data/lib/aidp/providers/cursor.rb +16 -0
  46. data/lib/aidp/providers/gemini.rb +13 -0
  47. data/lib/aidp/providers/github_copilot.rb +17 -0
  48. data/lib/aidp/providers/kilocode.rb +11 -0
  49. data/lib/aidp/providers/opencode.rb +11 -0
  50. data/lib/aidp/setup/wizard.rb +249 -39
  51. data/lib/aidp/version.rb +1 -1
  52. data/lib/aidp/watch/build_processor.rb +211 -30
  53. data/lib/aidp/watch/change_request_processor.rb +128 -14
  54. data/lib/aidp/watch/ci_fix_processor.rb +103 -37
  55. data/lib/aidp/watch/ci_log_extractor.rb +258 -0
  56. data/lib/aidp/watch/github_state_extractor.rb +177 -0
  57. data/lib/aidp/watch/implementation_verifier.rb +284 -0
  58. data/lib/aidp/watch/plan_generator.rb +7 -43
  59. data/lib/aidp/watch/plan_processor.rb +7 -6
  60. data/lib/aidp/watch/repository_client.rb +245 -17
  61. data/lib/aidp/watch/review_processor.rb +98 -17
  62. data/lib/aidp/watch/reviewers/base_reviewer.rb +1 -1
  63. data/lib/aidp/watch/runner.rb +181 -29
  64. data/lib/aidp/watch/state_store.rb +22 -1
  65. data/lib/aidp/workflows/definitions.rb +147 -0
  66. data/lib/aidp/workstream_cleanup.rb +245 -0
  67. data/lib/aidp/worktree.rb +19 -0
  68. data/templates/aidp.yml.example +57 -0
  69. data/templates/implementation/generate_tdd_specs.md +213 -0
  70. data/templates/implementation/iterative_implementation.md +122 -0
  71. data/templates/planning/agile/analyze_feedback.md +183 -0
  72. data/templates/planning/agile/generate_iteration_plan.md +179 -0
  73. data/templates/planning/agile/generate_legacy_research_plan.md +171 -0
  74. data/templates/planning/agile/generate_marketing_report.md +162 -0
  75. data/templates/planning/agile/generate_mvp_scope.md +127 -0
  76. data/templates/planning/agile/generate_user_test_plan.md +143 -0
  77. data/templates/planning/agile/ingest_feedback.md +174 -0
  78. data/templates/planning/assemble_project_plan.md +113 -0
  79. data/templates/planning/assign_personas.md +108 -0
  80. data/templates/planning/create_tasks.md +52 -6
  81. data/templates/planning/generate_gantt.md +86 -0
  82. data/templates/planning/generate_wbs.md +85 -0
  83. data/templates/planning/initialize_planning_mode.md +70 -0
  84. data/templates/skills/README.md +2 -2
  85. data/templates/skills/marketing_strategist/SKILL.md +279 -0
  86. data/templates/skills/product_manager/SKILL.md +177 -0
  87. data/templates/skills/ruby_aidp_planning/SKILL.md +497 -0
  88. data/templates/skills/ruby_rspec_tdd/SKILL.md +514 -0
  89. data/templates/skills/ux_researcher/SKILL.md +222 -0
  90. metadata +39 -1
@@ -0,0 +1,245 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "worktree"
4
+ require_relative "workstream_state"
5
+ require "open3"
6
+ require "tty-prompt"
7
+
8
+ module Aidp
9
+ # Service for interactively cleaning up inactive workstreams
10
+ # Displays comprehensive status and prompts user for deletion decisions
11
+ class WorkstreamCleanup
12
+ class Error < StandardError; end
13
+
14
+ def initialize(project_dir: Dir.pwd, prompt: TTY::Prompt.new)
15
+ @project_dir = project_dir
16
+ @prompt = prompt
17
+ end
18
+
19
+ # Run interactive cleanup workflow
20
+ def run
21
+ Aidp.log_debug("workstream_cleanup", "start", project_dir: @project_dir)
22
+
23
+ workstreams = Aidp::Worktree.list(project_dir: @project_dir)
24
+
25
+ if workstreams.empty?
26
+ @prompt.say("No workstreams found.")
27
+ Aidp.log_debug("workstream_cleanup", "no_workstreams")
28
+ return
29
+ end
30
+
31
+ @prompt.say("Found #{workstreams.size} workstream(s)\n")
32
+
33
+ workstreams.each do |ws|
34
+ process_workstream(ws)
35
+ end
36
+
37
+ @prompt.say("\nโœ“ Cleanup complete")
38
+ Aidp.log_debug("workstream_cleanup", "complete")
39
+ end
40
+
41
+ private
42
+
43
+ def process_workstream(ws)
44
+ Aidp.log_debug("workstream_cleanup", "process", slug: ws[:slug])
45
+
46
+ status = gather_status(ws)
47
+ display_status(ws, status)
48
+
49
+ choice = prompt_action(ws, status)
50
+ execute_action(ws, choice, status)
51
+ end
52
+
53
+ def gather_status(ws)
54
+ Aidp.log_debug("workstream_cleanup", "gather_status", slug: ws[:slug])
55
+
56
+ status = {
57
+ exists: ws[:active],
58
+ state: Aidp::WorkstreamState.read(slug: ws[:slug], project_dir: @project_dir) || {}
59
+ }
60
+
61
+ return status unless status[:exists]
62
+
63
+ # Gather git status information
64
+ Dir.chdir(ws[:path]) do
65
+ status[:uncommitted_changes] = uncommitted_changes?
66
+ status[:unpushed_commits] = unpushed_commits?
67
+ status[:upstream_exists] = upstream_exists?
68
+ status[:last_commit_date] = last_commit_date
69
+ status[:behind_upstream] = behind_upstream? if status[:upstream_exists]
70
+ end
71
+
72
+ status
73
+ end
74
+
75
+ def uncommitted_changes?
76
+ stdout, _stderr, status = Open3.capture3("git", "status", "--porcelain")
77
+ status.success? && !stdout.strip.empty?
78
+ end
79
+
80
+ def unpushed_commits?
81
+ # Check if there are commits not in the upstream branch
82
+ stdout, _stderr, status = Open3.capture3("git", "log", "@{upstream}..", "--oneline")
83
+ status.success? && !stdout.strip.empty?
84
+ rescue
85
+ # If @{upstream} doesn't exist, check for any commits
86
+ false
87
+ end
88
+
89
+ def upstream_exists?
90
+ _stdout, _stderr, status = Open3.capture3("git", "rev-parse", "--abbrev-ref", "@{upstream}")
91
+ status.success?
92
+ end
93
+
94
+ def behind_upstream?
95
+ stdout, _stderr, status = Open3.capture3("git", "log", "..@{upstream}", "--oneline")
96
+ status.success? && !stdout.strip.empty?
97
+ end
98
+
99
+ def last_commit_date
100
+ stdout, _stderr, status = Open3.capture3("git", "log", "-1", "--format=%ci")
101
+ status.success? ? stdout.strip : nil
102
+ end
103
+
104
+ def display_status(ws, status)
105
+ @prompt.say("\n" + "=" * 60)
106
+ @prompt.say("Workstream: #{ws[:slug]}")
107
+ @prompt.say("=" * 60)
108
+ @prompt.say("Branch: #{ws[:branch]}")
109
+ @prompt.say("Created: #{ws[:created_at]}")
110
+ @prompt.say("Status: #{status[:state][:status] || "unknown"}")
111
+ @prompt.say("Iterations: #{status[:state][:iterations] || 0}")
112
+
113
+ if status[:state][:task]
114
+ @prompt.say("Task: #{status[:state][:task]}")
115
+ end
116
+
117
+ unless status[:exists]
118
+ @prompt.say("\nโš ๏ธ Worktree directory does not exist")
119
+ return
120
+ end
121
+
122
+ # Display git status
123
+ @prompt.say("\nGit Status:")
124
+ @prompt.say(" Uncommitted changes: #{status[:uncommitted_changes] ? "Yes" : "No"}")
125
+
126
+ if status[:upstream_exists]
127
+ @prompt.say(" Upstream: exists")
128
+ @prompt.say(" Unpushed commits: #{status[:unpushed_commits] ? "Yes" : "No"}")
129
+ @prompt.say(" Behind upstream: #{status[:behind_upstream] ? "Yes" : "No"}")
130
+ else
131
+ @prompt.say(" Upstream: none (local branch)")
132
+ end
133
+
134
+ if status[:last_commit_date]
135
+ @prompt.say(" Last commit: #{status[:last_commit_date]}")
136
+ end
137
+ end
138
+
139
+ def prompt_action(ws, status)
140
+ Aidp.log_debug("workstream_cleanup", "prompt_action", slug: ws[:slug])
141
+
142
+ choices = build_choices(ws, status)
143
+ @prompt.select("\nWhat would you like to do?", choices, per_page: 10)
144
+ end
145
+
146
+ def build_choices(ws, status)
147
+ choices = [
148
+ {name: "Keep (skip)", value: :keep},
149
+ {name: "Delete worktree only", value: :delete_worktree}
150
+ ]
151
+
152
+ if status[:exists]
153
+ choices << if has_risk_factors?(status)
154
+ {name: "Delete worktree and local branch (has uncommitted/unpushed work!)", value: :delete_all}
155
+ else
156
+ {name: "Delete worktree and local branch", value: :delete_all}
157
+ end
158
+
159
+ if status[:upstream_exists]
160
+ choices << {name: "Delete worktree, local branch, and remote branch", value: :delete_all_remote}
161
+ end
162
+ else
163
+ choices << {name: "Delete registration (worktree already gone)", value: :delete_worktree}
164
+ end
165
+
166
+ choices
167
+ end
168
+
169
+ def has_risk_factors?(status)
170
+ status[:uncommitted_changes] || status[:unpushed_commits]
171
+ end
172
+
173
+ def execute_action(ws, choice, status)
174
+ Aidp.log_debug("workstream_cleanup", "execute_action", slug: ws[:slug], action: choice)
175
+
176
+ case choice
177
+ when :keep
178
+ @prompt.say("Keeping workstream")
179
+ when :delete_worktree
180
+ delete_worktree(ws, delete_branch: false)
181
+ when :delete_all
182
+ if confirm_deletion(ws, status, remote: false)
183
+ delete_worktree(ws, delete_branch: true)
184
+ else
185
+ @prompt.say("Deletion cancelled")
186
+ end
187
+ when :delete_all_remote
188
+ if confirm_deletion(ws, status, remote: true)
189
+ delete_remote_branch(ws)
190
+ delete_worktree(ws, delete_branch: true)
191
+ else
192
+ @prompt.say("Deletion cancelled")
193
+ end
194
+ end
195
+ end
196
+
197
+ def confirm_deletion(ws, status, remote:)
198
+ if has_risk_factors?(status)
199
+ warning = "โš ๏ธ WARNING: This workstream has uncommitted changes or unpushed commits!"
200
+ @prompt.say("\n#{warning}")
201
+ end
202
+
203
+ message = if remote
204
+ "Delete worktree, local branch, AND remote branch for '#{ws[:slug]}'?"
205
+ else
206
+ "Delete worktree and local branch for '#{ws[:slug]}'?"
207
+ end
208
+
209
+ @prompt.yes?(message)
210
+ end
211
+
212
+ def delete_remote_branch(ws)
213
+ Aidp.log_debug("workstream_cleanup", "delete_remote_branch", slug: ws[:slug], branch: ws[:branch])
214
+
215
+ # Extract remote and branch name
216
+ # Branch format is typically "aidp/slug", we need to push to origin
217
+ Dir.chdir(@project_dir) do
218
+ _, stderr, status = Open3.capture3("git", "push", "origin", "--delete", ws[:branch])
219
+ if status.success?
220
+ @prompt.say("โœ“ Deleted remote branch: #{ws[:branch]}")
221
+ else
222
+ @prompt.say("โš ๏ธ Failed to delete remote branch: #{stderr.strip}")
223
+ Aidp.log_debug("workstream_cleanup", "delete_remote_failed", branch: ws[:branch], error: stderr.strip)
224
+ end
225
+ end
226
+ end
227
+
228
+ def delete_worktree(ws, delete_branch:)
229
+ Aidp.log_debug("workstream_cleanup", "delete_worktree", slug: ws[:slug], delete_branch: delete_branch)
230
+
231
+ begin
232
+ Aidp::Worktree.remove(
233
+ slug: ws[:slug],
234
+ project_dir: @project_dir,
235
+ delete_branch: delete_branch
236
+ )
237
+ @prompt.say("โœ“ Deleted workstream: #{ws[:slug]}")
238
+ @prompt.say(" Branch deleted") if delete_branch
239
+ rescue Aidp::Worktree::Error => e
240
+ @prompt.say("โŒ Error: #{e.message}")
241
+ Aidp.log_error("workstream_cleanup", "delete_failed", slug: ws[:slug], error: e.message)
242
+ end
243
+ end
244
+ end
245
+ end
data/lib/aidp/worktree.rb CHANGED
@@ -141,6 +141,25 @@ module Aidp
141
141
  !info(slug: slug, project_dir: project_dir).nil?
142
142
  end
143
143
 
144
+ # Find a worktree by branch name
145
+ #
146
+ # @param branch [String] Branch name to search for
147
+ # @param project_dir [String] Project root directory
148
+ # @return [Hash, nil] Worktree info or nil if not found
149
+ def find_by_branch(branch:, project_dir: Dir.pwd)
150
+ registry = load_registry(project_dir)
151
+ slug, data = registry.find { |_slug, info| info["branch"] == branch }
152
+ return nil unless data
153
+
154
+ {
155
+ slug: slug,
156
+ path: data["path"],
157
+ branch: data["branch"],
158
+ created_at: data["created_at"],
159
+ active: Dir.exist?(data["path"])
160
+ }
161
+ end
162
+
144
163
  private
145
164
 
146
165
  # Ensure we're in a git repository
@@ -239,6 +239,25 @@ providers:
239
239
  flags: ["--precise"]
240
240
  timeout: 900 # 15 minutes
241
241
 
242
+ # Thinking tier model configuration
243
+ # Maps thinking depth tiers to specific models for this provider
244
+ thinking_tiers:
245
+ mini:
246
+ models:
247
+ - cursor-fast # Fast model for simple tasks
248
+ standard:
249
+ models:
250
+ - cursor-default # Default model for standard tasks
251
+ thinking:
252
+ models:
253
+ - cursor-precise # Precise model for complex reasoning
254
+ pro:
255
+ models:
256
+ - cursor-precise # Use best model for pro tier
257
+ max:
258
+ models:
259
+ - cursor-precise # Use best model for max tier
260
+
242
261
  # Provider features
243
262
  features:
244
263
  file_upload: true
@@ -343,6 +362,25 @@ providers:
343
362
  max_tokens: 200000
344
363
  timeout: 600 # 10 minutes
345
364
 
365
+ # Thinking tier model configuration
366
+ # Maps thinking depth tiers to specific models for this provider
367
+ thinking_tiers:
368
+ mini:
369
+ models:
370
+ - claude-3-5-haiku-20241022 # Fastest, cheapest model
371
+ standard:
372
+ models:
373
+ - claude-3-5-sonnet-20241022 # Balanced performance
374
+ thinking:
375
+ models:
376
+ - claude-3-5-sonnet-20241022 # Best balance for complex tasks
377
+ pro:
378
+ models:
379
+ - claude-3-opus-20240229 # Most capable model
380
+ max:
381
+ models:
382
+ - claude-3-opus-20240229 # Maximum capability
383
+
346
384
  # Authentication configuration
347
385
  auth:
348
386
  api_key_env: "ANTHROPIC_API_KEY" # Environment variable for API key
@@ -394,6 +432,25 @@ providers:
394
432
  max_tokens: 30000
395
433
  timeout: 300 # 5 minutes
396
434
 
435
+ # Thinking tier model configuration
436
+ # Maps thinking depth tiers to specific models for this provider
437
+ thinking_tiers:
438
+ mini:
439
+ models:
440
+ - gemini-1.5-flash # Fast model for simple tasks
441
+ standard:
442
+ models:
443
+ - gemini-1.5-pro # Most capable model
444
+ thinking:
445
+ models:
446
+ - gemini-1.5-pro # Best model for complex reasoning
447
+ pro:
448
+ models:
449
+ - gemini-1.5-pro # Use best available
450
+ max:
451
+ models:
452
+ - gemini-1.5-pro # Use best available
453
+
397
454
  # Authentication configuration
398
455
  auth:
399
456
  api_key_env: "GEMINI_API_KEY" # Environment variable for API key
@@ -0,0 +1,213 @@
1
+ # Generate TDD Test Specifications
2
+
3
+ You are creating **test specifications** following Test-Driven Development (TDD) principles.
4
+
5
+ ## TDD Philosophy
6
+
7
+ ### RED โ†’ GREEN โ†’ REFACTOR
8
+
9
+ 1. **RED**: Write failing tests that specify desired behavior
10
+ 2. **GREEN**: Write minimal code to make tests pass
11
+ 3. **REFACTOR**: Improve code while keeping tests green
12
+
13
+ ## Context
14
+
15
+ Read these artifacts to understand requirements:
16
+
17
+ - `.aidp/docs/PRD.md` - Product requirements (if exists)
18
+ - `.aidp/docs/TECH_DESIGN.md` - Technical design (if exists)
19
+ - `.aidp/docs/TASK_LIST.md` - Task breakdown (if exists)
20
+ - `.aidp/docs/WBS.md` - Work breakdown structure (if exists)
21
+
22
+ ## Your Task
23
+
24
+ Generate comprehensive test specifications BEFORE implementation.
25
+
26
+ ## Test Specification Structure
27
+
28
+ Create `docs/tdd_specifications.md`:
29
+
30
+ ```markdown
31
+ # TDD Test Specifications
32
+
33
+ Generated: <timestamp>
34
+
35
+ ## Overview
36
+
37
+ This document defines tests to write BEFORE implementing features.
38
+ Follow TDD: write tests first, watch them fail, then implement.
39
+
40
+ ## Test Categories
41
+
42
+ ### Unit Tests
43
+
44
+ #### Feature: [Feature Name]
45
+
46
+ **Test Cases:**
47
+ 1. **should handle valid input**
48
+ - Given: Valid input parameters
49
+ - When: Feature is invoked
50
+ - Then: Returns expected output
51
+ - Status: โญ• Not yet written
52
+
53
+ 2. **should reject invalid input**
54
+ - Given: Invalid parameters
55
+ - When: Feature is invoked
56
+ - Then: Raises appropriate error
57
+ - Status: โญ• Not yet written
58
+
59
+ 3. **should handle edge cases**
60
+ - Given: Edge case inputs (empty, nil, boundary values)
61
+ - When: Feature is invoked
62
+ - Then: Handles gracefully
63
+ - Status: โญ• Not yet written
64
+
65
+ ### Integration Tests
66
+
67
+ #### Integration: [Component A + Component B]
68
+
69
+ **Test Cases:**
70
+ 1. **should integrate successfully**
71
+ - Given: Both components configured
72
+ - When: Integration point is called
73
+ - Then: Data flows correctly
74
+ - Status: โญ• Not yet written
75
+
76
+ ### Acceptance Tests
77
+
78
+ #### User Story: [As a user, I want to...]
79
+
80
+ **Test Cases:**
81
+ 1. **should complete user workflow**
82
+ - Given: User starts workflow
83
+ - When: User performs actions
84
+ - Then: Achieves expected outcome
85
+ - Status: โญ• Not yet written
86
+
87
+ ## Test Implementation Order
88
+
89
+ 1. **Phase 1: Critical Path**
90
+ - Write tests for core functionality first
91
+ - Focus on happy path
92
+ - Estimated: X hours
93
+
94
+ 2. **Phase 2: Edge Cases**
95
+ - Add tests for error conditions
96
+ - Boundary testing
97
+ - Estimated: Y hours
98
+
99
+ 3. **Phase 3: Integration**
100
+ - Test component interactions
101
+ - End-to-end workflows
102
+ - Estimated: Z hours
103
+
104
+ ## Coverage Goals
105
+
106
+ - **Unit Tests:** 90%+ coverage
107
+ - **Integration Tests:** All integration points
108
+ - **Acceptance Tests:** All user stories from PRD
109
+
110
+ ## Notes
111
+
112
+ - Tests should be **fast** (< 1s per test ideal)
113
+ - Tests should be **isolated** (no shared state)
114
+ - Tests should be **deterministic** (same result every time)
115
+ - Mock external dependencies (APIs, databases, file I/O)
116
+ - Test behavior, not implementation
117
+
118
+ ## Next Steps
119
+
120
+ 1. Review this specification
121
+ 2. Write tests (they should fail - RED)
122
+ 3. Implement minimal code (make tests pass - GREEN)
123
+ 4. Refactor code (keep tests green - REFACTOR)
124
+ ```
125
+
126
+ ## TDD Best Practices
127
+
128
+ ### 1. Test One Thing
129
+
130
+ Each test should verify ONE behavior.
131
+
132
+ โŒ BAD: Testing multiple behaviors in one test
133
+ โœ… GOOD: Separate tests for separate behaviors
134
+
135
+ ### 2. Use Descriptive Names
136
+
137
+ Test names should describe the behavior being tested, not implementation details.
138
+
139
+ ### 3. Follow Given-When-Then
140
+
141
+ Structure tests clearly:
142
+
143
+ - **GIVEN**: Setup test data and preconditions
144
+ - **WHEN**: Execute the behavior being tested
145
+ - **THEN**: Verify expected outcomes
146
+
147
+ ### 4. Mock External Dependencies
148
+
149
+ Don't hit real APIs, databases, or file systems in unit tests.
150
+ Use test doubles/mocks for external dependencies.
151
+
152
+ ### 5. Test Behavior, Not Implementation
153
+
154
+ โŒ BAD: Testing that internal helper methods are called
155
+ โœ… GOOD: Testing that public interface returns correct results
156
+
157
+ ## Framework-Specific Implementation
158
+
159
+ **For language/framework-specific test generation, use the appropriate skill:**
160
+
161
+ - **Ruby/RSpec**: Use `ruby_rspec_tdd` skill for RSpec-specific test files, fixtures, and syntax
162
+ - **Python/pytest**: Use `python_pytest_tdd` skill for pytest-specific implementation
163
+ - **JavaScript/Jest**: Use `javascript_jest_tdd` skill for Jest-specific implementation
164
+ - **Other frameworks**: Use ZFC skill matching to find appropriate testing skill
165
+
166
+ ## Skill Delegation
167
+
168
+ After creating the language-agnostic test specification above, delegate to the framework-specific skill to generate:
169
+
170
+ 1. **Skeleton test files** in the framework's directory structure and naming conventions
171
+ 2. **Test fixtures** or factories in the framework's format
172
+ 3. **Test execution commands** for the specific framework
173
+ 4. **Framework-specific examples** and best practices
174
+
175
+ **Example skill invocation:**
176
+
177
+ For a Ruby project using RSpec:
178
+
179
+ ```text
180
+ Use the `ruby_rspec_tdd` skill to:
181
+ 1. Generate skeleton RSpec test files in spec/ directory
182
+ 2. Create FactoryBot factories or fixtures as needed
183
+ 3. Provide RSpec-specific examples and matchers
184
+ 4. Include bundle exec rspec execution commands
185
+ ```
186
+
187
+ For a Python project using pytest:
188
+
189
+ ```text
190
+ Use the `python_pytest_tdd` skill to:
191
+ 1. Generate skeleton pytest test files in tests/ directory
192
+ 2. Create pytest fixtures as needed
193
+ 3. Provide pytest-specific examples and assertions
194
+ 4. Include pytest execution commands
195
+ ```
196
+
197
+ ## Output Files
198
+
199
+ Generate:
200
+
201
+ 1. **`docs/tdd_specifications.md`** - Framework-agnostic test specifications (as shown above)
202
+ 2. **Framework-specific test files** - Via appropriate skill delegation
203
+ 3. **Test data/fixtures** - Via appropriate skill delegation
204
+
205
+ ## Remember
206
+
207
+ - **Write tests FIRST** - before any implementation
208
+ - **Watch tests FAIL** - ensure they actually test something
209
+ - **Write minimal code** - just enough to pass tests
210
+ - **Refactor** - improve code with confidence (tests protect you)
211
+ - **Use skills for framework-specific implementation** - keep this template language-agnostic
212
+
213
+ **TDD gives you confidence, better design, and executable documentation!** ๐Ÿงช
@@ -0,0 +1,122 @@
1
+ # Iterative Implementation
2
+
3
+ You are implementing a feature or fix within the AIDP work loop using an iterative, task-based approach.
4
+
5
+ ## Your Mission
6
+
7
+ {{task_description}}
8
+
9
+ ## Important Instructions
10
+
11
+ ### 1. Break Down the Work
12
+
13
+ If this is a multi-step feature, **break it into concrete subtasks** using the persistent tasklist:
14
+
15
+ ```text
16
+ File task: "Subtask description here" priority: high|medium|low tags: tag1,tag2
17
+ ```
18
+
19
+ Examples:
20
+
21
+ ```text
22
+ File task: "Add worktree lookup logic to find existing worktrees" priority: high tags: implementation,git
23
+ File task: "Implement worktree creation for PR branches" priority: high tags: implementation,git
24
+ File task: "Add comprehensive logging using Aidp.log_debug" priority: medium tags: observability
25
+ File task: "Add tests for worktree operations" priority: high tags: testing
26
+ ```
27
+
28
+ ### 2. Implement One Subtask at a Time
29
+
30
+ **Focus on completing ONE subtask per iteration.** Keep changes minimal and focused.
31
+
32
+ - Read the pending tasks from the tasklist
33
+ - Pick the highest priority task that's ready to implement
34
+ - Implement it completely with tests
35
+ - Mark it done: `Update task: task_id_here status: done`
36
+
37
+ ### 3. Request Next Iteration
38
+
39
+ When you've completed a subtask and there's more work:
40
+
41
+ ```text
42
+ NEXT_UNIT: agentic
43
+ ```
44
+
45
+ This tells the work loop to continue with the next subtask after running tests/linters.
46
+
47
+ ### 4. Track Progress in PROMPT.md
48
+
49
+ Update this file to:
50
+
51
+ - Remove completed items
52
+ - Show current status
53
+ - List what remains
54
+
55
+ ### 5. Mark Complete When Done
56
+
57
+ When ALL work is complete (all subtasks done, tests passing):
58
+
59
+ ```text
60
+ STATUS: COMPLETE
61
+ ```
62
+
63
+ ## Completion Criteria
64
+
65
+ โœ… All subtasks filed and completed
66
+ โœ… All tests passing
67
+ โœ… All linters passing
68
+ โœ… Code follows project style guide
69
+ โœ… Comprehensive logging added
70
+ โœ… STATUS: COMPLETE added to PROMPT.md
71
+
72
+ ## Context
73
+
74
+ {{additional_context}}
75
+
76
+ ## Best Practices
77
+
78
+ - **Small iterations**: Better to do 5 small focused iterations than 1 giant one
79
+ - **Test as you go**: Write tests for each subtask before moving on
80
+ - **Use signals**: `File task:`, `Update task:`, `NEXT_UNIT:` keep the system coordinated
81
+ - **Log extensively**: Use `Aidp.log_debug()` at all important code paths
82
+ - **Fail fast**: Let bugs surface early rather than masking with rescues
83
+
84
+ ## Example Flow
85
+
86
+ Iteration 1:
87
+
88
+ ```text
89
+ File task: "Create WorktreeBranchManager class" priority: high tags: implementation
90
+ File task: "Add worktree lookup logic" priority: high tags: implementation
91
+ File task: "Add tests for WorktreeBranchManager" priority: high tags: testing
92
+
93
+ [Implement WorktreeBranchManager class with basic structure]
94
+
95
+ Update task: task_abc123 status: done
96
+ NEXT_UNIT: agentic
97
+ ```
98
+
99
+ Iteration 2:
100
+
101
+ ```text
102
+ [Implement worktree lookup logic]
103
+
104
+ Update task: task_def456 status: done
105
+ NEXT_UNIT: agentic
106
+ ```
107
+
108
+ Iteration 3:
109
+
110
+ ```text
111
+ [Add comprehensive tests]
112
+
113
+ Update task: task_ghi789 status: done
114
+ STATUS: COMPLETE
115
+ ```
116
+
117
+ ## Notes
118
+
119
+ - The work loop will automatically run tests/linters after each iteration
120
+ - If tests fail, you'll see the errors in the next iteration - fix them before continuing
121
+ - Use the persistent tasklist to coordinate work across sessions
122
+ - Each iteration should leave the codebase in a working state