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
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../logger"
|
|
4
|
+
|
|
5
|
+
module Aidp
|
|
6
|
+
module Planning
|
|
7
|
+
module Generators
|
|
8
|
+
# Generates marketing report with key messages and differentiators
|
|
9
|
+
# Uses AI to craft compelling narratives from technical features
|
|
10
|
+
# Follows Zero Framework Cognition (ZFC) pattern
|
|
11
|
+
class MarketingReportGenerator
|
|
12
|
+
def initialize(ai_decision_engine:, config: nil)
|
|
13
|
+
@ai_decision_engine = ai_decision_engine
|
|
14
|
+
@config = config || Aidp::Config.agile_config
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Generate marketing report from MVP scope and feedback
|
|
18
|
+
# @param mvp_scope [Hash] MVP scope definition
|
|
19
|
+
# @param feedback_analysis [Hash] User feedback analysis (optional)
|
|
20
|
+
# @return [Hash] Marketing report structure
|
|
21
|
+
def generate(mvp_scope:, feedback_analysis: nil)
|
|
22
|
+
Aidp.log_debug("marketing_report_generator", "generate",
|
|
23
|
+
feature_count: mvp_scope[:mvp_features]&.size || 0,
|
|
24
|
+
has_feedback: !feedback_analysis.nil?)
|
|
25
|
+
|
|
26
|
+
# Use AI to generate marketing materials
|
|
27
|
+
marketing_report = generate_marketing_with_ai(mvp_scope, feedback_analysis)
|
|
28
|
+
|
|
29
|
+
{
|
|
30
|
+
overview: marketing_report[:overview],
|
|
31
|
+
value_proposition: marketing_report[:value_proposition],
|
|
32
|
+
key_messages: marketing_report[:key_messages],
|
|
33
|
+
differentiators: marketing_report[:differentiators],
|
|
34
|
+
target_audience: marketing_report[:target_audience],
|
|
35
|
+
positioning: marketing_report[:positioning],
|
|
36
|
+
success_metrics: marketing_report[:success_metrics],
|
|
37
|
+
launch_checklist: marketing_report[:launch_checklist],
|
|
38
|
+
messaging_framework: marketing_report[:messaging_framework],
|
|
39
|
+
metadata: {
|
|
40
|
+
generated_at: Time.now.iso8601,
|
|
41
|
+
key_message_count: marketing_report[:key_messages]&.size || 0,
|
|
42
|
+
differentiator_count: marketing_report[:differentiators]&.size || 0
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Format marketing report as markdown
|
|
48
|
+
# @param report [Hash] Marketing report structure
|
|
49
|
+
# @return [String] Markdown formatted marketing report
|
|
50
|
+
def format_as_markdown(report)
|
|
51
|
+
Aidp.log_debug("marketing_report_generator", "format_as_markdown")
|
|
52
|
+
|
|
53
|
+
output = ["# Marketing Report", ""]
|
|
54
|
+
output << "**Generated:** #{report[:metadata][:generated_at]}"
|
|
55
|
+
output << "**Key Messages:** #{report[:metadata][:key_message_count]}"
|
|
56
|
+
output << "**Differentiators:** #{report[:metadata][:differentiator_count]}"
|
|
57
|
+
output << ""
|
|
58
|
+
|
|
59
|
+
output << "## Overview"
|
|
60
|
+
output << ""
|
|
61
|
+
output << report[:overview]
|
|
62
|
+
output << ""
|
|
63
|
+
|
|
64
|
+
output << "## Value Proposition"
|
|
65
|
+
output << ""
|
|
66
|
+
output << "### Headline"
|
|
67
|
+
output << ""
|
|
68
|
+
output << report[:value_proposition][:headline]
|
|
69
|
+
output << ""
|
|
70
|
+
output << "### Subheadline"
|
|
71
|
+
output << ""
|
|
72
|
+
output << report[:value_proposition][:subheadline]
|
|
73
|
+
output << ""
|
|
74
|
+
output << "### Core Benefits"
|
|
75
|
+
output << ""
|
|
76
|
+
report[:value_proposition][:core_benefits].each do |benefit|
|
|
77
|
+
output << "- #{benefit}"
|
|
78
|
+
end
|
|
79
|
+
output << ""
|
|
80
|
+
|
|
81
|
+
output << "## Key Messages"
|
|
82
|
+
output << ""
|
|
83
|
+
report[:key_messages].each_with_index do |message, idx|
|
|
84
|
+
output << "### #{idx + 1}. #{message[:title]}"
|
|
85
|
+
output << ""
|
|
86
|
+
output << message[:description]
|
|
87
|
+
output << ""
|
|
88
|
+
output << "**Supporting Points:**"
|
|
89
|
+
message[:supporting_points].each do |point|
|
|
90
|
+
output << "- #{point}"
|
|
91
|
+
end
|
|
92
|
+
output << ""
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
output << "## Differentiators"
|
|
96
|
+
output << ""
|
|
97
|
+
output << "What sets us apart from competitors:"
|
|
98
|
+
output << ""
|
|
99
|
+
report[:differentiators].each_with_index do |diff, idx|
|
|
100
|
+
output << "### #{idx + 1}. #{diff[:title]}"
|
|
101
|
+
output << ""
|
|
102
|
+
output << diff[:description]
|
|
103
|
+
output << ""
|
|
104
|
+
output << "**Competitive Advantage:** #{diff[:advantage]}"
|
|
105
|
+
output << ""
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
output << "## Target Audience"
|
|
109
|
+
output << ""
|
|
110
|
+
report[:target_audience].each do |segment|
|
|
111
|
+
output << "### #{segment[:name]}"
|
|
112
|
+
output << ""
|
|
113
|
+
output << "**Description:** #{segment[:description]}"
|
|
114
|
+
output << ""
|
|
115
|
+
output << "**Pain Points:**"
|
|
116
|
+
segment[:pain_points].each do |pain|
|
|
117
|
+
output << "- #{pain}"
|
|
118
|
+
end
|
|
119
|
+
output << ""
|
|
120
|
+
output << "**Our Solution:**"
|
|
121
|
+
segment[:our_solution].each do |solution|
|
|
122
|
+
output << "- #{solution}"
|
|
123
|
+
end
|
|
124
|
+
output << ""
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
output << "## Positioning"
|
|
128
|
+
output << ""
|
|
129
|
+
output << "**Category:** #{report[:positioning][:category]}"
|
|
130
|
+
output << ""
|
|
131
|
+
output << "**Statement:** #{report[:positioning][:statement]}"
|
|
132
|
+
output << ""
|
|
133
|
+
output << "**Tagline:** #{report[:positioning][:tagline]}"
|
|
134
|
+
output << ""
|
|
135
|
+
|
|
136
|
+
output << "## Success Metrics"
|
|
137
|
+
output << ""
|
|
138
|
+
report[:success_metrics].each do |metric|
|
|
139
|
+
output << "- **#{metric[:name]}:** #{metric[:target]}"
|
|
140
|
+
output << " - Measurement: #{metric[:measurement]}"
|
|
141
|
+
output << ""
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
output << "## Messaging Framework"
|
|
145
|
+
output << ""
|
|
146
|
+
output << "| Audience | Message | Channel | Call to Action |"
|
|
147
|
+
output << "|----------|---------|---------|----------------|"
|
|
148
|
+
report[:messaging_framework].each do |msg|
|
|
149
|
+
output << "| #{msg[:audience]} | #{msg[:message]} | #{msg[:channel]} | #{msg[:cta]} |"
|
|
150
|
+
end
|
|
151
|
+
output << ""
|
|
152
|
+
|
|
153
|
+
output << "## Launch Checklist"
|
|
154
|
+
output << ""
|
|
155
|
+
report[:launch_checklist].each_with_index do |item, idx|
|
|
156
|
+
output << "- [ ] **#{item[:task]}**"
|
|
157
|
+
output << " - Owner: #{item[:owner]}"
|
|
158
|
+
output << " - Timeline: #{item[:timeline]}"
|
|
159
|
+
output << ""
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
output.join("\n")
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def generate_marketing_with_ai(mvp_scope, feedback_analysis)
|
|
168
|
+
Aidp.log_debug("marketing_report_generator", "generate_marketing_with_ai")
|
|
169
|
+
|
|
170
|
+
prompt = build_marketing_prompt(mvp_scope, feedback_analysis)
|
|
171
|
+
|
|
172
|
+
schema = {
|
|
173
|
+
type: "object",
|
|
174
|
+
properties: {
|
|
175
|
+
overview: {type: "string"},
|
|
176
|
+
value_proposition: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: {
|
|
179
|
+
headline: {type: "string"},
|
|
180
|
+
subheadline: {type: "string"},
|
|
181
|
+
core_benefits: {type: "array", items: {type: "string"}}
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
key_messages: {
|
|
185
|
+
type: "array",
|
|
186
|
+
items: {
|
|
187
|
+
type: "object",
|
|
188
|
+
properties: {
|
|
189
|
+
title: {type: "string"},
|
|
190
|
+
description: {type: "string"},
|
|
191
|
+
supporting_points: {type: "array", items: {type: "string"}}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
differentiators: {
|
|
196
|
+
type: "array",
|
|
197
|
+
items: {
|
|
198
|
+
type: "object",
|
|
199
|
+
properties: {
|
|
200
|
+
title: {type: "string"},
|
|
201
|
+
description: {type: "string"},
|
|
202
|
+
advantage: {type: "string"}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
target_audience: {
|
|
207
|
+
type: "array",
|
|
208
|
+
items: {
|
|
209
|
+
type: "object",
|
|
210
|
+
properties: {
|
|
211
|
+
name: {type: "string"},
|
|
212
|
+
description: {type: "string"},
|
|
213
|
+
pain_points: {type: "array", items: {type: "string"}},
|
|
214
|
+
our_solution: {type: "array", items: {type: "string"}}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
positioning: {
|
|
219
|
+
type: "object",
|
|
220
|
+
properties: {
|
|
221
|
+
category: {type: "string"},
|
|
222
|
+
statement: {type: "string"},
|
|
223
|
+
tagline: {type: "string"}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
success_metrics: {
|
|
227
|
+
type: "array",
|
|
228
|
+
items: {
|
|
229
|
+
type: "object",
|
|
230
|
+
properties: {
|
|
231
|
+
name: {type: "string"},
|
|
232
|
+
target: {type: "string"},
|
|
233
|
+
measurement: {type: "string"}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
messaging_framework: {
|
|
238
|
+
type: "array",
|
|
239
|
+
items: {
|
|
240
|
+
type: "object",
|
|
241
|
+
properties: {
|
|
242
|
+
audience: {type: "string"},
|
|
243
|
+
message: {type: "string"},
|
|
244
|
+
channel: {type: "string"},
|
|
245
|
+
cta: {type: "string"}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
launch_checklist: {
|
|
250
|
+
type: "array",
|
|
251
|
+
items: {
|
|
252
|
+
type: "object",
|
|
253
|
+
properties: {
|
|
254
|
+
task: {type: "string"},
|
|
255
|
+
owner: {type: "string"},
|
|
256
|
+
timeline: {type: "string"}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
required: ["overview", "value_proposition", "key_messages", "differentiators"]
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
decision = @ai_decision_engine.decide(
|
|
265
|
+
context: "marketing_report_generation",
|
|
266
|
+
prompt: prompt,
|
|
267
|
+
data: {
|
|
268
|
+
mvp_scope: mvp_scope,
|
|
269
|
+
feedback_analysis: feedback_analysis
|
|
270
|
+
},
|
|
271
|
+
schema: schema
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
Aidp.log_debug("marketing_report_generator", "ai_report_generated",
|
|
275
|
+
messages: decision[:key_messages]&.size || 0)
|
|
276
|
+
|
|
277
|
+
decision
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def build_marketing_prompt(mvp_scope, feedback_analysis)
|
|
281
|
+
feedback_insights = if feedback_analysis
|
|
282
|
+
<<~INSIGHTS
|
|
283
|
+
USER FEEDBACK INSIGHTS:
|
|
284
|
+
#{feedback_analysis[:findings]&.map { |f| "- #{f}" }&.join("\n") || "No insights"}
|
|
285
|
+
INSIGHTS
|
|
286
|
+
else
|
|
287
|
+
""
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
<<~PROMPT
|
|
291
|
+
Generate a comprehensive marketing report for the following MVP.
|
|
292
|
+
|
|
293
|
+
MVP FEATURES:
|
|
294
|
+
#{mvp_scope[:mvp_features]&.map { |f| "- #{f[:name]}: #{f[:description]}" }&.join("\n") || "No features"}
|
|
295
|
+
|
|
296
|
+
SUCCESS CRITERIA:
|
|
297
|
+
#{mvp_scope[:success_criteria]&.map { |c| "- #{c}" }&.join("\n") || "No criteria"}
|
|
298
|
+
|
|
299
|
+
#{feedback_insights}
|
|
300
|
+
|
|
301
|
+
TASK:
|
|
302
|
+
Create marketing materials that translate technical features into compelling value propositions:
|
|
303
|
+
|
|
304
|
+
1. OVERVIEW
|
|
305
|
+
- Brief summary of the marketing strategy
|
|
306
|
+
|
|
307
|
+
2. VALUE PROPOSITION
|
|
308
|
+
- Compelling headline (10-15 words)
|
|
309
|
+
- Supporting subheadline (15-25 words)
|
|
310
|
+
- 3-5 core benefits
|
|
311
|
+
|
|
312
|
+
3. KEY MESSAGES (3-5 messages)
|
|
313
|
+
- For each: title, description, 3-5 supporting points
|
|
314
|
+
- Focus on customer value, not technical features
|
|
315
|
+
|
|
316
|
+
4. DIFFERENTIATORS (2-4 items)
|
|
317
|
+
- What makes this unique?
|
|
318
|
+
- Competitive advantages
|
|
319
|
+
- Why choose us over alternatives?
|
|
320
|
+
|
|
321
|
+
5. TARGET AUDIENCE (2-3 segments)
|
|
322
|
+
- Name and description
|
|
323
|
+
- Pain points they experience
|
|
324
|
+
- How our solution addresses their needs
|
|
325
|
+
|
|
326
|
+
6. POSITIONING
|
|
327
|
+
- Category (what market/space are we in?)
|
|
328
|
+
- Positioning statement (who, what, value, differentiation)
|
|
329
|
+
- Tagline (memorable 3-7 words)
|
|
330
|
+
|
|
331
|
+
7. SUCCESS METRICS
|
|
332
|
+
- 4-6 measurable metrics for launch success
|
|
333
|
+
- Targets and how to measure
|
|
334
|
+
|
|
335
|
+
8. MESSAGING FRAMEWORK
|
|
336
|
+
- For each audience: specific message, channel, call to action
|
|
337
|
+
|
|
338
|
+
9. LAUNCH CHECKLIST
|
|
339
|
+
- 8-12 pre-launch tasks
|
|
340
|
+
- Owner and timeline for each
|
|
341
|
+
|
|
342
|
+
Make it compelling, customer-focused, and actionable. Avoid jargon.
|
|
343
|
+
PROMPT
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../logger"
|
|
4
|
+
|
|
5
|
+
module Aidp
|
|
6
|
+
module Planning
|
|
7
|
+
module Generators
|
|
8
|
+
# Generates MVP scope definition using AI to analyze features
|
|
9
|
+
# Determines must-have vs nice-to-have features for MVP
|
|
10
|
+
# Uses Zero Framework Cognition (ZFC) - NO heuristics, pure AI decisions
|
|
11
|
+
class MVPScopeGenerator
|
|
12
|
+
def initialize(ai_decision_engine:, prompt: nil, config: nil)
|
|
13
|
+
@ai_decision_engine = ai_decision_engine
|
|
14
|
+
@prompt = prompt || TTY::Prompt.new
|
|
15
|
+
@config = config || Aidp::Config.agile_config
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Generate MVP scope from PRD and user priorities
|
|
19
|
+
# @param prd [Hash] Parsed PRD document
|
|
20
|
+
# @param user_priorities [Array<String>] User-specified priorities (optional)
|
|
21
|
+
# @return [Hash] MVP scope with must-have and nice-to-have features
|
|
22
|
+
def generate(prd:, user_priorities: nil)
|
|
23
|
+
Aidp.log_debug("mvp_scope_generator", "generate", has_prd: !prd.nil?)
|
|
24
|
+
|
|
25
|
+
# Collect user priorities if not provided
|
|
26
|
+
priorities = user_priorities || collect_user_priorities(prd)
|
|
27
|
+
|
|
28
|
+
Aidp.log_debug("mvp_scope_generator", "analyzing_features", priority_count: priorities.size)
|
|
29
|
+
|
|
30
|
+
# Use AI to analyze features and determine MVP viability
|
|
31
|
+
mvp_analysis = analyze_features_with_ai(prd, priorities)
|
|
32
|
+
|
|
33
|
+
{
|
|
34
|
+
mvp_features: mvp_analysis[:must_have],
|
|
35
|
+
deferred_features: mvp_analysis[:nice_to_have],
|
|
36
|
+
out_of_scope: mvp_analysis[:out_of_scope],
|
|
37
|
+
success_criteria: mvp_analysis[:success_criteria],
|
|
38
|
+
assumptions: mvp_analysis[:assumptions],
|
|
39
|
+
risks: mvp_analysis[:risks],
|
|
40
|
+
metadata: {
|
|
41
|
+
generated_at: Time.now.iso8601,
|
|
42
|
+
mvp_feature_count: mvp_analysis[:must_have].size,
|
|
43
|
+
deferred_feature_count: mvp_analysis[:nice_to_have].size,
|
|
44
|
+
out_of_scope_count: mvp_analysis[:out_of_scope].size,
|
|
45
|
+
user_priorities: priorities
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Format MVP scope as markdown
|
|
51
|
+
# @param mvp_scope [Hash] MVP scope structure
|
|
52
|
+
# @return [String] Markdown formatted MVP scope
|
|
53
|
+
def format_as_markdown(mvp_scope)
|
|
54
|
+
Aidp.log_debug("mvp_scope_generator", "format_as_markdown")
|
|
55
|
+
|
|
56
|
+
output = ["# MVP Scope Definition", ""]
|
|
57
|
+
output << "**Generated:** #{mvp_scope[:metadata][:generated_at]}"
|
|
58
|
+
output << "**MVP Features:** #{mvp_scope[:metadata][:mvp_feature_count]}"
|
|
59
|
+
output << "**Deferred Features:** #{mvp_scope[:metadata][:deferred_feature_count]}"
|
|
60
|
+
output << ""
|
|
61
|
+
|
|
62
|
+
output << "## Overview"
|
|
63
|
+
output << ""
|
|
64
|
+
output << "This document defines the Minimum Viable Product (MVP) scope, distinguishing between must-have features for initial release and nice-to-have features that can be deferred to later iterations."
|
|
65
|
+
output << ""
|
|
66
|
+
|
|
67
|
+
output << "## User Priorities"
|
|
68
|
+
output << ""
|
|
69
|
+
mvp_scope[:metadata][:user_priorities].each_with_index do |priority, idx|
|
|
70
|
+
output << "#{idx + 1}. #{priority}"
|
|
71
|
+
end
|
|
72
|
+
output << ""
|
|
73
|
+
|
|
74
|
+
output << "## MVP Features (Must-Have)"
|
|
75
|
+
output << ""
|
|
76
|
+
output << "These features are essential for the MVP and must be included in the first release:"
|
|
77
|
+
output << ""
|
|
78
|
+
mvp_scope[:mvp_features].each_with_index do |feature, idx|
|
|
79
|
+
output << "### #{idx + 1}. #{feature[:name]}"
|
|
80
|
+
output << ""
|
|
81
|
+
output << feature[:description] if feature[:description]
|
|
82
|
+
output << ""
|
|
83
|
+
output << "**Rationale:** #{feature[:rationale]}" if feature[:rationale]
|
|
84
|
+
output << ""
|
|
85
|
+
output << "**Acceptance Criteria:**"
|
|
86
|
+
(feature[:acceptance_criteria] || []).each do |criterion|
|
|
87
|
+
output << "- #{criterion}"
|
|
88
|
+
end
|
|
89
|
+
output << ""
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
output << "## Deferred Features (Nice-to-Have)"
|
|
93
|
+
output << ""
|
|
94
|
+
output << "These features can be implemented in future iterations:"
|
|
95
|
+
output << ""
|
|
96
|
+
mvp_scope[:deferred_features].each_with_index do |feature, idx|
|
|
97
|
+
output << "### #{idx + 1}. #{feature[:name]}"
|
|
98
|
+
output << ""
|
|
99
|
+
output << feature[:description] if feature[:description]
|
|
100
|
+
output << ""
|
|
101
|
+
output << "**Deferral Reason:** #{feature[:deferral_reason]}" if feature[:deferral_reason]
|
|
102
|
+
output << ""
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
output << "## Out of Scope"
|
|
106
|
+
output << ""
|
|
107
|
+
output << "These items are explicitly out of scope for the MVP:"
|
|
108
|
+
output << ""
|
|
109
|
+
mvp_scope[:out_of_scope].each do |item|
|
|
110
|
+
output << "- #{item}"
|
|
111
|
+
end
|
|
112
|
+
output << ""
|
|
113
|
+
|
|
114
|
+
output << "## Success Criteria"
|
|
115
|
+
output << ""
|
|
116
|
+
output << "The MVP will be considered successful if:"
|
|
117
|
+
output << ""
|
|
118
|
+
mvp_scope[:success_criteria].each do |criterion|
|
|
119
|
+
output << "- #{criterion}"
|
|
120
|
+
end
|
|
121
|
+
output << ""
|
|
122
|
+
|
|
123
|
+
output << "## Assumptions"
|
|
124
|
+
output << ""
|
|
125
|
+
mvp_scope[:assumptions].each do |assumption|
|
|
126
|
+
output << "- #{assumption}"
|
|
127
|
+
end
|
|
128
|
+
output << ""
|
|
129
|
+
|
|
130
|
+
output << "## Risks"
|
|
131
|
+
output << ""
|
|
132
|
+
mvp_scope[:risks].each_with_index do |risk, idx|
|
|
133
|
+
output << "#{idx + 1}. **#{risk[:title]}**"
|
|
134
|
+
output << " - **Impact:** #{risk[:impact]}"
|
|
135
|
+
output << " - **Mitigation:** #{risk[:mitigation]}"
|
|
136
|
+
output << ""
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
output.join("\n")
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
private
|
|
143
|
+
|
|
144
|
+
# Collect user priorities interactively
|
|
145
|
+
def collect_user_priorities(prd)
|
|
146
|
+
Aidp.log_debug("mvp_scope_generator", "collect_user_priorities")
|
|
147
|
+
|
|
148
|
+
@prompt.say("Let's define your MVP priorities.")
|
|
149
|
+
@prompt.say("")
|
|
150
|
+
|
|
151
|
+
priorities = []
|
|
152
|
+
|
|
153
|
+
# Ask about key priorities
|
|
154
|
+
priorities << @prompt.ask("What is the primary goal of this MVP?", required: true)
|
|
155
|
+
priorities << @prompt.ask("What is the main problem you're solving?", required: true)
|
|
156
|
+
|
|
157
|
+
# Ask about target users
|
|
158
|
+
target_users = @prompt.ask("Who are your target users?", required: true)
|
|
159
|
+
priorities << "Target users: #{target_users}"
|
|
160
|
+
|
|
161
|
+
# Ask about timeline
|
|
162
|
+
timeline = @prompt.ask("What is your target timeline for MVP launch? (e.g., 3 months)", required: true)
|
|
163
|
+
priorities << "Timeline: #{timeline}"
|
|
164
|
+
|
|
165
|
+
# Ask about constraints
|
|
166
|
+
if @prompt.yes?("Do you have any resource or technical constraints?")
|
|
167
|
+
constraints = @prompt.ask("What constraints should we consider?")
|
|
168
|
+
priorities << "Constraints: #{constraints}"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
Aidp.log_debug("mvp_scope_generator", "priorities_collected", count: priorities.size)
|
|
172
|
+
priorities
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Use AI Decision Engine to analyze features and determine MVP scope
|
|
176
|
+
# This is ZFC - semantic analysis goes to AI, not code
|
|
177
|
+
def analyze_features_with_ai(prd, priorities)
|
|
178
|
+
Aidp.log_debug("mvp_scope_generator", "analyze_features_with_ai")
|
|
179
|
+
|
|
180
|
+
# Build prompt for AI analysis
|
|
181
|
+
prompt = build_mvp_analysis_prompt(prd, priorities)
|
|
182
|
+
|
|
183
|
+
# Define schema for structured output
|
|
184
|
+
schema = {
|
|
185
|
+
type: "object",
|
|
186
|
+
properties: {
|
|
187
|
+
must_have: {
|
|
188
|
+
type: "array",
|
|
189
|
+
items: {
|
|
190
|
+
type: "object",
|
|
191
|
+
properties: {
|
|
192
|
+
name: {type: "string"},
|
|
193
|
+
description: {type: "string"},
|
|
194
|
+
rationale: {type: "string"},
|
|
195
|
+
acceptance_criteria: {type: "array", items: {type: "string"}}
|
|
196
|
+
},
|
|
197
|
+
required: ["name", "description", "rationale"]
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
nice_to_have: {
|
|
201
|
+
type: "array",
|
|
202
|
+
items: {
|
|
203
|
+
type: "object",
|
|
204
|
+
properties: {
|
|
205
|
+
name: {type: "string"},
|
|
206
|
+
description: {type: "string"},
|
|
207
|
+
deferral_reason: {type: "string"}
|
|
208
|
+
},
|
|
209
|
+
required: ["name", "description", "deferral_reason"]
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
out_of_scope: {
|
|
213
|
+
type: "array",
|
|
214
|
+
items: {type: "string"}
|
|
215
|
+
},
|
|
216
|
+
success_criteria: {
|
|
217
|
+
type: "array",
|
|
218
|
+
items: {type: "string"}
|
|
219
|
+
},
|
|
220
|
+
assumptions: {
|
|
221
|
+
type: "array",
|
|
222
|
+
items: {type: "string"}
|
|
223
|
+
},
|
|
224
|
+
risks: {
|
|
225
|
+
type: "array",
|
|
226
|
+
items: {
|
|
227
|
+
type: "object",
|
|
228
|
+
properties: {
|
|
229
|
+
title: {type: "string"},
|
|
230
|
+
impact: {type: "string"},
|
|
231
|
+
mitigation: {type: "string"}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
required: ["must_have", "nice_to_have", "success_criteria"]
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
# Call AI Decision Engine
|
|
240
|
+
decision = @ai_decision_engine.decide(
|
|
241
|
+
context: "mvp_scope_analysis",
|
|
242
|
+
prompt: prompt,
|
|
243
|
+
data: {
|
|
244
|
+
prd: prd,
|
|
245
|
+
priorities: priorities
|
|
246
|
+
},
|
|
247
|
+
schema: schema
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
Aidp.log_debug("mvp_scope_generator", "ai_analysis_complete",
|
|
251
|
+
must_have: decision[:must_have].size,
|
|
252
|
+
nice_to_have: decision[:nice_to_have].size)
|
|
253
|
+
|
|
254
|
+
decision
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def build_mvp_analysis_prompt(prd, priorities)
|
|
258
|
+
<<~PROMPT
|
|
259
|
+
Analyze the following Product Requirements Document (PRD) and user priorities to determine the Minimum Viable Product (MVP) scope.
|
|
260
|
+
|
|
261
|
+
USER PRIORITIES:
|
|
262
|
+
#{priorities.map.with_index { |p, i| "#{i + 1}. #{p}" }.join("\n")}
|
|
263
|
+
|
|
264
|
+
PRD SUMMARY:
|
|
265
|
+
#{prd[:content] || prd.inspect}
|
|
266
|
+
|
|
267
|
+
TASK:
|
|
268
|
+
1. Identify MUST-HAVE features that are absolutely essential for the MVP
|
|
269
|
+
- These should address the primary goal and solve the main problem
|
|
270
|
+
- Consider the target users and timeline
|
|
271
|
+
- Focus on core functionality that delivers value
|
|
272
|
+
|
|
273
|
+
2. Identify NICE-TO-HAVE features that can be deferred to future iterations
|
|
274
|
+
- These are valuable but not critical for initial release
|
|
275
|
+
- Explain why each can be deferred
|
|
276
|
+
|
|
277
|
+
3. Identify items that are OUT OF SCOPE for the MVP
|
|
278
|
+
- Features that don't align with MVP goals
|
|
279
|
+
- Advanced features that can wait
|
|
280
|
+
|
|
281
|
+
4. Define SUCCESS CRITERIA for the MVP
|
|
282
|
+
- Measurable outcomes
|
|
283
|
+
- User satisfaction metrics
|
|
284
|
+
- Technical performance targets
|
|
285
|
+
|
|
286
|
+
5. List ASSUMPTIONS
|
|
287
|
+
- What are we assuming about users, technology, or resources?
|
|
288
|
+
|
|
289
|
+
6. Identify RISKS
|
|
290
|
+
- What could prevent MVP success?
|
|
291
|
+
- What's the impact and mitigation strategy?
|
|
292
|
+
|
|
293
|
+
For each must-have feature, provide:
|
|
294
|
+
- Clear name
|
|
295
|
+
- Description
|
|
296
|
+
- Rationale (why it's essential for MVP)
|
|
297
|
+
- Acceptance criteria (how we know it's done)
|
|
298
|
+
|
|
299
|
+
For each nice-to-have feature, provide:
|
|
300
|
+
- Clear name
|
|
301
|
+
- Description
|
|
302
|
+
- Deferral reason (why it can wait)
|
|
303
|
+
|
|
304
|
+
Be pragmatic and focus on delivering value quickly while managing scope.
|
|
305
|
+
PROMPT
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|