aidp 0.26.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/checkpoint_command.rb +198 -0
- data/lib/aidp/cli/config_command.rb +71 -0
- data/lib/aidp/cli/enhanced_input.rb +2 -0
- data/lib/aidp/cli/first_run_wizard.rb +8 -7
- data/lib/aidp/cli/harness_command.rb +102 -0
- data/lib/aidp/cli/jobs_command.rb +3 -3
- data/lib/aidp/cli/mcp_dashboard.rb +4 -3
- data/lib/aidp/cli/models_command.rb +661 -0
- data/lib/aidp/cli/providers_command.rb +223 -0
- data/lib/aidp/cli.rb +45 -464
- data/lib/aidp/config.rb +54 -0
- data/lib/aidp/daemon/runner.rb +2 -2
- data/lib/aidp/debug_mixin.rb +25 -10
- data/lib/aidp/execute/agent_signal_parser.rb +22 -0
- data/lib/aidp/execute/async_work_loop_runner.rb +2 -1
- data/lib/aidp/execute/checkpoint_display.rb +38 -37
- data/lib/aidp/execute/interactive_repl.rb +2 -1
- data/lib/aidp/execute/prompt_manager.rb +4 -4
- 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 +238 -19
- data/lib/aidp/execute/workflow_selector.rb +4 -27
- 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 +5 -10
- data/lib/aidp/harness/config_schema.rb +8 -0
- data/lib/aidp/harness/configuration.rb +40 -2
- data/lib/aidp/harness/enhanced_runner.rb +25 -19
- data/lib/aidp/harness/error_handler.rb +23 -73
- data/lib/aidp/harness/model_cache.rb +269 -0
- data/lib/aidp/harness/model_discovery_service.rb +259 -0
- data/lib/aidp/harness/model_registry.rb +201 -0
- data/lib/aidp/harness/provider_factory.rb +11 -2
- data/lib/aidp/harness/runner.rb +5 -0
- data/lib/aidp/harness/state_manager.rb +0 -7
- data/lib/aidp/harness/thinking_depth_manager.rb +202 -7
- 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/message_display.rb +0 -46
- 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/adapter.rb +2 -4
- data/lib/aidp/providers/aider.rb +264 -0
- data/lib/aidp/providers/anthropic.rb +206 -121
- data/lib/aidp/providers/base.rb +123 -3
- data/lib/aidp/providers/capability_registry.rb +0 -1
- data/lib/aidp/providers/codex.rb +75 -70
- data/lib/aidp/providers/cursor.rb +87 -59
- data/lib/aidp/providers/gemini.rb +57 -60
- data/lib/aidp/providers/github_copilot.rb +19 -66
- data/lib/aidp/providers/kilocode.rb +35 -80
- data/lib/aidp/providers/opencode.rb +35 -80
- data/lib/aidp/setup/wizard.rb +555 -8
- 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 +95 -52
- 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 +100 -19
- 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/workflows/guided_agent.rb +3 -3
- data/lib/aidp/workstream_cleanup.rb +245 -0
- data/lib/aidp/worktree.rb +19 -0
- data/templates/aidp-development.yml.example +2 -2
- data/templates/aidp-production.yml.example +3 -3
- 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 +47 -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
|
|
@@ -137,7 +137,7 @@ providers:
|
|
|
137
137
|
file_upload: true
|
|
138
138
|
code_generation: true
|
|
139
139
|
analysis: true
|
|
140
|
-
|
|
140
|
+
supports_json_mode: true
|
|
141
141
|
|
|
142
142
|
# Monitoring configuration (enhanced for development)
|
|
143
143
|
monitoring:
|
|
@@ -243,7 +243,7 @@ providers:
|
|
|
243
243
|
code_generation: true
|
|
244
244
|
analysis: true
|
|
245
245
|
vision: true
|
|
246
|
-
|
|
246
|
+
supports_json_mode: true
|
|
247
247
|
function_calling: true
|
|
248
248
|
tool_use: true
|
|
249
249
|
|
|
@@ -149,7 +149,7 @@ providers:
|
|
|
149
149
|
code_generation: true
|
|
150
150
|
analysis: true
|
|
151
151
|
vision: true
|
|
152
|
-
|
|
152
|
+
supports_json_mode: true
|
|
153
153
|
function_calling: true
|
|
154
154
|
tool_use: true
|
|
155
155
|
|
|
@@ -254,7 +254,7 @@ providers:
|
|
|
254
254
|
file_upload: true
|
|
255
255
|
code_generation: true
|
|
256
256
|
analysis: true
|
|
257
|
-
|
|
257
|
+
supports_json_mode: true
|
|
258
258
|
|
|
259
259
|
# Monitoring configuration
|
|
260
260
|
monitoring:
|
|
@@ -365,7 +365,7 @@ providers:
|
|
|
365
365
|
code_generation: true
|
|
366
366
|
analysis: true
|
|
367
367
|
vision: true
|
|
368
|
-
|
|
368
|
+
supports_json_mode: true
|
|
369
369
|
|
|
370
370
|
# Monitoring configuration
|
|
371
371
|
monitoring:
|
data/templates/aidp.yml.example
CHANGED
|
@@ -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!** 🧪
|