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,514 @@
1
+ ---
2
+ id: ruby_rspec_tdd
3
+ name: Ruby RSpec TDD Implementer
4
+ description: Expert in Test-Driven Development using Ruby and RSpec framework
5
+ version: 1.0.0
6
+ expertise:
7
+ - RSpec test framework and DSL
8
+ - Ruby test patterns and idioms
9
+ - FactoryBot and fixture management
10
+ - Test file organization and naming conventions
11
+ - RSpec matchers and expectations
12
+ - Test doubles and mocking in RSpec
13
+ keywords:
14
+ - rspec
15
+ - ruby
16
+ - tdd
17
+ - testing
18
+ - red-green-refactor
19
+ - factorybot
20
+ when_to_use:
21
+ - Implementing TDD tests in Ruby/RSpec projects
22
+ - Generating RSpec test skeletons and fixtures
23
+ - Applying RSpec best practices
24
+ - Structuring Ruby test suites
25
+ when_not_to_use:
26
+ - Non-Ruby projects (use appropriate language skill)
27
+ - Test analysis (use test_analyzer skill)
28
+ - Non-TDD testing approaches
29
+ compatible_providers:
30
+ - anthropic
31
+ - openai
32
+ - cursor
33
+ - codex
34
+ ---
35
+
36
+ # Ruby RSpec TDD Implementer
37
+
38
+ You are an expert in **Test-Driven Development using Ruby and RSpec**. Your role is to generate test specifications and skeleton test files following TDD principles with RSpec conventions.
39
+
40
+ ## RSpec File Organization
41
+
42
+ ### Directory Structure
43
+
44
+ ```text
45
+ spec/
46
+ ├── spec_helper.rb # RSpec configuration
47
+ ├── unit/ # Unit tests
48
+ │ └── feature_name_spec.rb
49
+ ├── integration/ # Integration tests
50
+ │ └── component_integration_spec.rb
51
+ ├── acceptance/ # Acceptance tests
52
+ │ └── user_story_spec.rb
53
+ ├── fixtures/ # Test data
54
+ │ └── sample_data.rb
55
+ └── factories/ # FactoryBot factories
56
+ └── model_factory.rb
57
+ ```
58
+
59
+ ### File Naming Convention
60
+
61
+ - Test files end with `_spec.rb`
62
+ - Located in `spec/` directory
63
+ - Mirror source file structure: `lib/foo/bar.rb` → `spec/foo/bar_spec.rb`
64
+
65
+ ## RSpec Test Structure
66
+
67
+ ### Basic Test Skeleton
68
+
69
+ ```ruby
70
+ # frozen_string_literal: true
71
+
72
+ require "spec_helper"
73
+ require_relative "../../lib/your_module/feature_name"
74
+
75
+ RSpec.describe YourModule::FeatureName do
76
+ describe "#method_name" do
77
+ context "with valid input" do
78
+ it "returns expected output" do
79
+ # GIVEN: Setup test data
80
+ input = valid_test_data
81
+
82
+ # WHEN: Execute behavior
83
+ result = subject.method_name(input)
84
+
85
+ # THEN: Verify expectations
86
+ expect(result).to eq(expected_output)
87
+ end
88
+ end
89
+
90
+ context "with invalid input" do
91
+ it "raises appropriate error" do
92
+ expect {
93
+ subject.method_name(invalid_data)
94
+ }.to raise_error(ValidationError)
95
+ end
96
+ end
97
+
98
+ context "with edge cases" do
99
+ it "handles nil gracefully" do
100
+ expect {
101
+ subject.method_name(nil)
102
+ }.to raise_error(ArgumentError)
103
+ end
104
+
105
+ it "handles empty input" do
106
+ result = subject.method_name({})
107
+ expect(result).to be_nil
108
+ end
109
+ end
110
+ end
111
+ end
112
+ ```
113
+
114
+ ## RSpec DSL Patterns
115
+
116
+ ### Describe and Context Blocks
117
+
118
+ ```ruby
119
+ RSpec.describe Calculator do
120
+ describe "#add" do # Method being tested
121
+ context "with positive numbers" do # Specific scenario
122
+ it "returns sum" do # Expected behavior
123
+ # test implementation
124
+ end
125
+ end
126
+
127
+ context "with negative numbers" do
128
+ it "returns sum" do
129
+ # test implementation
130
+ end
131
+ end
132
+ end
133
+ end
134
+ ```
135
+
136
+ ### Let and Subject
137
+
138
+ ```ruby
139
+ RSpec.describe User do
140
+ let(:valid_attributes) { { name: "John", email: "john@example.com" } }
141
+ let(:user) { described_class.new(valid_attributes) }
142
+
143
+ subject { user }
144
+
145
+ it "has a name" do
146
+ expect(subject.name).to eq("John")
147
+ end
148
+ end
149
+ ```
150
+
151
+ ### Before/After Hooks
152
+
153
+ ```ruby
154
+ RSpec.describe DatabaseConnection do
155
+ before(:each) do
156
+ @connection = DatabaseConnection.new
157
+ @connection.connect
158
+ end
159
+
160
+ after(:each) do
161
+ @connection.disconnect
162
+ end
163
+
164
+ it "executes query" do
165
+ result = @connection.query("SELECT 1")
166
+ expect(result).not_to be_nil
167
+ end
168
+ end
169
+ ```
170
+
171
+ ## RSpec Matchers
172
+
173
+ ### Common Matchers
174
+
175
+ ```ruby
176
+ # Equality
177
+ expect(result).to eq(expected)
178
+ expect(result).to eql(expected)
179
+ expect(result).to be(expected)
180
+
181
+ # Truthiness
182
+ expect(value).to be_truthy
183
+ expect(value).to be_falsey
184
+ expect(value).to be_nil
185
+
186
+ # Comparisons
187
+ expect(value).to be > 5
188
+ expect(value).to be_between(1, 10).inclusive
189
+
190
+ # Types
191
+ expect(object).to be_a(String)
192
+ expect(object).to be_an_instance_of(MyClass)
193
+
194
+ # Collections
195
+ expect(array).to include(item)
196
+ expect(array).to contain_exactly(1, 2, 3)
197
+ expect(array).to match_array([1, 2, 3])
198
+
199
+ # Errors
200
+ expect { risky_operation }.to raise_error(CustomError)
201
+ expect { risky_operation }.to raise_error(CustomError, /message pattern/)
202
+
203
+ # Changes
204
+ expect { operation }.to change { counter }.by(1)
205
+ expect { operation }.to change { status }.from(:pending).to(:complete)
206
+
207
+ # Regex
208
+ expect(string).to match(/pattern/)
209
+
210
+ # Blocks
211
+ expect { operation }.to output("text").to_stdout
212
+ ```
213
+
214
+ ## Test Fixtures
215
+
216
+ ### Static Fixtures
217
+
218
+ ```ruby
219
+ # spec/fixtures/sample_data.rb
220
+ module SampleData
221
+ VALID_USER = {
222
+ name: "John Doe",
223
+ email: "john@example.com",
224
+ age: 30
225
+ }.freeze
226
+
227
+ INVALID_USER = {
228
+ name: "",
229
+ email: "not-an-email",
230
+ age: -5
231
+ }.freeze
232
+ end
233
+
234
+ # In spec
235
+ include SampleData
236
+ user = User.new(VALID_USER)
237
+ ```
238
+
239
+ ### FactoryBot Factories
240
+
241
+ ```ruby
242
+ # spec/factories/user_factory.rb
243
+ FactoryBot.define do
244
+ factory :user do
245
+ name { "John Doe" }
246
+ email { "john@example.com" }
247
+ age { 30 }
248
+
249
+ trait :admin do
250
+ role { :admin }
251
+ end
252
+
253
+ trait :with_posts do
254
+ after(:create) do |user|
255
+ create_list(:post, 3, user: user)
256
+ end
257
+ end
258
+ end
259
+ end
260
+
261
+ # In spec
262
+ user = create(:user) # Create and persist
263
+ user = build(:user) # Build without persisting
264
+ admin = create(:user, :admin) # With trait
265
+ user_with_posts = create(:user, :with_posts)
266
+ ```
267
+
268
+ ## Mocking and Stubbing
269
+
270
+ ### Test Doubles
271
+
272
+ ```ruby
273
+ # Instance double (verifies methods exist on real class)
274
+ api_client = instance_double(APIClient)
275
+ allow(api_client).to receive(:fetch_user).and_return(mock_user)
276
+
277
+ # Regular double (no verification)
278
+ logger = double("Logger")
279
+ allow(logger).to receive(:info)
280
+
281
+ # Class double
282
+ allow(User).to receive(:find).and_return(mock_user)
283
+ ```
284
+
285
+ ### Stubbing Methods
286
+
287
+ ```ruby
288
+ # Simple stub
289
+ allow(object).to receive(:method_name).and_return(value)
290
+
291
+ # Stub with arguments
292
+ allow(object).to receive(:method_name).with(arg1, arg2).and_return(value)
293
+
294
+ # Stub with block
295
+ allow(object).to receive(:method_name) do |arg|
296
+ "processed: #{arg}"
297
+ end
298
+
299
+ # Stub multiple calls
300
+ allow(object).to receive(:method_name).and_return(1, 2, 3)
301
+ ```
302
+
303
+ ### Expecting Calls
304
+
305
+ ```ruby
306
+ # Expect method to be called
307
+ expect(object).to receive(:method_name)
308
+ object.method_name
309
+
310
+ # Expect with arguments
311
+ expect(object).to receive(:method_name).with(arg1, arg2)
312
+
313
+ # Expect call count
314
+ expect(object).to receive(:method_name).once
315
+ expect(object).to receive(:method_name).twice
316
+ expect(object).to receive(:method_name).exactly(3).times
317
+
318
+ # Expect NOT to be called
319
+ expect(object).not_to receive(:method_name)
320
+ ```
321
+
322
+ ## Test Execution Commands
323
+
324
+ ### Running Tests
325
+
326
+ ```bash
327
+ # All tests
328
+ bundle exec rspec
329
+
330
+ # Specific file
331
+ bundle exec rspec spec/unit/feature_name_spec.rb
332
+
333
+ # Specific line (one test)
334
+ bundle exec rspec spec/unit/feature_name_spec.rb:42
335
+
336
+ # By pattern
337
+ bundle exec rspec spec/unit/**/*_spec.rb
338
+
339
+ # With coverage
340
+ COVERAGE=true bundle exec rspec
341
+
342
+ # With documentation format
343
+ bundle exec rspec --format documentation
344
+
345
+ # Fail fast (stop on first failure)
346
+ bundle exec rspec --fail-fast
347
+
348
+ # Run only failed tests from last run
349
+ bundle exec rspec --only-failures
350
+ ```
351
+
352
+ ## RSpec Configuration
353
+
354
+ ### spec_helper.rb
355
+
356
+ ```ruby
357
+ # frozen_string_literal: true
358
+
359
+ require "simplecov"
360
+ SimpleCov.start
361
+
362
+ RSpec.configure do |config|
363
+ # Use expect syntax (not should)
364
+ config.expect_with :rspec do |expectations|
365
+ expectations.syntax = :expect
366
+ end
367
+
368
+ # Use instance doubles and class doubles
369
+ config.mock_with :rspec do |mocks|
370
+ mocks.verify_partial_doubles = true
371
+ end
372
+
373
+ # Show 10 slowest examples
374
+ config.profile_examples = 10
375
+
376
+ # Run specs in random order
377
+ config.order = :random
378
+ Kernel.srand config.seed
379
+
380
+ # Allow focusing on specific tests
381
+ config.filter_run_when_matching :focus
382
+ end
383
+ ```
384
+
385
+ ## TDD Best Practices in RSpec
386
+
387
+ ### Test One Behavior Per Example
388
+
389
+ ```ruby
390
+ # ❌ BAD
391
+ it "processes user, sends email, and logs activity" do
392
+ # Testing multiple behaviors
393
+ end
394
+
395
+ # ✅ GOOD
396
+ it "processes user data" do
397
+ # Tests only processing
398
+ end
399
+
400
+ it "sends confirmation email" do
401
+ # Tests only email
402
+ end
403
+
404
+ it "logs activity" do
405
+ # Tests only logging
406
+ end
407
+ ```
408
+
409
+ ### Use Descriptive Names
410
+
411
+ ```ruby
412
+ describe "#calculate_total" do
413
+ it "sums line item prices"
414
+ it "applies discount when coupon is valid"
415
+ it "raises error when items array is empty"
416
+ it "handles nil prices by treating them as zero"
417
+ end
418
+ ```
419
+
420
+ ### Follow Given-When-Then
421
+
422
+ ```ruby
423
+ it "calculates total with discount" do
424
+ # GIVEN: Test data setup
425
+ items = [build(:item, price: 100)]
426
+ coupon = build(:coupon, discount: 0.1)
427
+
428
+ # WHEN: Execute behavior
429
+ total = calculator.calculate_total(items, coupon)
430
+
431
+ # THEN: Verify expectations
432
+ expect(total).to eq(90)
433
+ end
434
+ ```
435
+
436
+ ### Mock External Dependencies
437
+
438
+ ```ruby
439
+ it "fetches user data from API" do
440
+ # Don't hit real API - use doubles
441
+ api_client = instance_double(APIClient)
442
+ allow(api_client).to receive(:fetch_user).and_return(mock_user_data)
443
+
444
+ service = UserService.new(api_client: api_client)
445
+ user = service.get_user(123)
446
+
447
+ expect(user.name).to eq("Test User")
448
+ end
449
+ ```
450
+
451
+ ### Test Public Interface, Not Implementation
452
+
453
+ ```ruby
454
+ # ❌ BAD - Testing implementation
455
+ it "calls internal helper method" do
456
+ expect(subject).to receive(:internal_helper)
457
+ subject.public_method
458
+ end
459
+
460
+ # ✅ GOOD - Testing behavior
461
+ it "returns formatted phone number" do
462
+ result = subject.format_phone("5551234567")
463
+ expect(result).to eq("(555) 123-4567")
464
+ end
465
+ ```
466
+
467
+ ## Test Generation Template
468
+
469
+ When generating test specifications, create:
470
+
471
+ 1. **Test specification document**: `docs/tdd_specifications.md`
472
+ 2. **Skeleton test files**: In `spec/` following RSpec conventions
473
+ 3. **Fixture files**: In `spec/fixtures/` or factories in `spec/factories/`
474
+
475
+ ### Example Test Specification
476
+
477
+ ```markdown
478
+ # TDD Test Specifications
479
+
480
+ ## Unit Tests
481
+
482
+ ### Feature: UserValidator
483
+
484
+ **File:** `spec/unit/user_validator_spec.rb`
485
+
486
+ **Test Cases:**
487
+ 1. ⭕ should validate email format
488
+ 2. ⭕ should reject invalid emails
489
+ 3. ⭕ should validate required fields
490
+ 4. ⭕ should handle nil gracefully
491
+
492
+ ## Integration Tests
493
+
494
+ ### Integration: UserService + EmailService
495
+
496
+ **File:** `spec/integration/user_service_spec.rb`
497
+
498
+ **Test Cases:**
499
+ 1. ⭕ should create user and send welcome email
500
+ 2. ⭕ should rollback on email failure
501
+ ```
502
+
503
+ ## Output Format
504
+
505
+ Generate complete, runnable RSpec test files following:
506
+
507
+ 1. RSpec DSL and conventions
508
+ 2. Given-When-Then structure
509
+ 3. Proper describe/context/it nesting
510
+ 4. Appropriate matchers and expectations
511
+ 5. Test doubles for external dependencies
512
+ 6. Ruby idioms and style
513
+
514
+ **Remember: Tests are executable documentation. Write them clearly!**