@champpaba/claude-agent-kit 1.1.1 → 1.4.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.
- package/.claude/CLAUDE.md +52 -444
- package/.claude/agents/01-integration.md +47 -193
- package/.claude/agents/02-uxui-frontend.md +40 -186
- package/.claude/agents/03-test-debug.md +43 -186
- package/.claude/agents/04-frontend.md +50 -478
- package/.claude/agents/05-backend.md +49 -499
- package/.claude/agents/06-database.md +36 -188
- package/.claude/commands/cdev.md +86 -1
- package/.claude/commands/csetup.md +319 -6
- package/.claude/commands/designsetup.md +360 -29
- package/.claude/commands/pageplan.md +40 -10
- package/.claude/lib/README.md +46 -4
- package/.claude/lib/context-loading-protocol.md +462 -0
- package/.claude/lib/detailed-guides/agent-system.md +237 -0
- package/.claude/lib/detailed-guides/best-practices-system.md +150 -0
- package/.claude/lib/detailed-guides/context-optimization.md +118 -0
- package/.claude/lib/detailed-guides/design-system.md +98 -0
- package/.claude/lib/detailed-guides/page-planning.md +147 -0
- package/.claude/lib/detailed-guides/taskmaster-analysis.md +263 -0
- package/.claude/lib/document-loader.md +353 -0
- package/.claude/lib/handoff-protocol.md +665 -0
- package/.claude/lib/task-analyzer.md +694 -0
- package/.claude/lib/tdd-workflow.md +891 -0
- package/.claude/templates/design-context-template.md +220 -0
- package/README.md +191 -0
- package/package.json +1 -1
|
@@ -0,0 +1,694 @@
|
|
|
1
|
+
# Task Analyzer - TaskMaster-style Analysis
|
|
2
|
+
|
|
3
|
+
> **Enhanced task analysis for intelligent phase generation**
|
|
4
|
+
> **Version:** 1.3.0 (TaskMaster Integration)
|
|
5
|
+
> **Used by:** `/csetup` command
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🎯 Purpose
|
|
10
|
+
|
|
11
|
+
Analyze tasks.md (from OpenSpec) and generate **intelligent task metadata** including:
|
|
12
|
+
- Complexity scoring (1-10)
|
|
13
|
+
- Dependency detection
|
|
14
|
+
- Risk assessment
|
|
15
|
+
- Research requirements
|
|
16
|
+
- Subtask breakdown recommendations
|
|
17
|
+
- Priority ranking
|
|
18
|
+
|
|
19
|
+
**Inspired by:** [claude-task-master](https://github.com/eyaltoledano/claude-task-master)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 📋 Analysis Framework
|
|
24
|
+
|
|
25
|
+
### 1. Complexity Scoring (1-10)
|
|
26
|
+
|
|
27
|
+
**Factors:**
|
|
28
|
+
```typescript
|
|
29
|
+
function calculateComplexity(task: Task): number {
|
|
30
|
+
let score = 3 // Base complexity
|
|
31
|
+
|
|
32
|
+
// Factor 1: Estimated time
|
|
33
|
+
if (task.estimatedTime > 120) score += 3 // > 2 hours
|
|
34
|
+
else if (task.estimatedTime > 60) score += 2 // > 1 hour
|
|
35
|
+
else if (task.estimatedTime > 30) score += 1 // > 30 min
|
|
36
|
+
|
|
37
|
+
// Factor 2: Keywords
|
|
38
|
+
const highComplexityKeywords = [
|
|
39
|
+
'authentication', 'security', 'payment', 'real-time',
|
|
40
|
+
'websocket', 'oauth', 'encryption', 'migration',
|
|
41
|
+
'refactor', 'optimization', 'performance'
|
|
42
|
+
]
|
|
43
|
+
const matches = highComplexityKeywords.filter(kw =>
|
|
44
|
+
task.description.toLowerCase().includes(kw)
|
|
45
|
+
)
|
|
46
|
+
score += matches.length
|
|
47
|
+
|
|
48
|
+
// Factor 3: Multi-step indicator
|
|
49
|
+
if (task.description.match(/\band\b/gi)?.length > 2) score += 1
|
|
50
|
+
if (task.description.match(/\bthen\b/gi)?.length > 1) score += 1
|
|
51
|
+
|
|
52
|
+
// Factor 4: External dependencies
|
|
53
|
+
if (task.description.match(/(api|library|service|integration)/i)) score += 1
|
|
54
|
+
|
|
55
|
+
// Cap at 10
|
|
56
|
+
return Math.min(score, 10)
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Complexity Levels:**
|
|
61
|
+
- 1-3: Simple (CRUD, UI components)
|
|
62
|
+
- 4-6: Moderate (Business logic, integrations)
|
|
63
|
+
- 7-8: Complex (Auth, payments, real-time)
|
|
64
|
+
- 9-10: Critical (Security, migrations, major refactors)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### 2. Dependency Detection
|
|
69
|
+
|
|
70
|
+
**Analysis:**
|
|
71
|
+
```typescript
|
|
72
|
+
function detectDependencies(task: Task, allTasks: Task[]): Dependencies {
|
|
73
|
+
const dependencies = {
|
|
74
|
+
blocks: [], // Tasks this task blocks
|
|
75
|
+
blockedBy: [], // Tasks blocking this task
|
|
76
|
+
parallelizable: [] // Tasks that can run in parallel
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Rule 1: UI depends on backend
|
|
80
|
+
if (task.type === 'frontend-integration') {
|
|
81
|
+
const apiTasks = allTasks.filter(t =>
|
|
82
|
+
t.type === 'backend' &&
|
|
83
|
+
t.description.match(/api|endpoint/i)
|
|
84
|
+
)
|
|
85
|
+
dependencies.blockedBy.push(...apiTasks.map(t => t.id))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Rule 2: Backend depends on database
|
|
89
|
+
if (task.type === 'backend') {
|
|
90
|
+
const dbTasks = allTasks.filter(t =>
|
|
91
|
+
t.type === 'database' &&
|
|
92
|
+
task.description.includes(t.description.split(' ')[0]) // Common entity
|
|
93
|
+
)
|
|
94
|
+
dependencies.blockedBy.push(...dbTasks.map(t => t.id))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Rule 3: Tests depend on implementation
|
|
98
|
+
if (task.type === 'test') {
|
|
99
|
+
const implTasks = allTasks.filter(t =>
|
|
100
|
+
t.type !== 'test' &&
|
|
101
|
+
task.description.toLowerCase().includes(t.description.split(' ')[0].toLowerCase())
|
|
102
|
+
)
|
|
103
|
+
dependencies.blockedBy.push(...implTasks.map(t => t.id))
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Rule 4: Integration depends on both UI and API
|
|
107
|
+
if (task.description.match(/connect|integrate|link/i)) {
|
|
108
|
+
const uiTasks = allTasks.filter(t => t.type === 'uxui-frontend')
|
|
109
|
+
const apiTasks = allTasks.filter(t => t.type === 'backend')
|
|
110
|
+
dependencies.blockedBy.push(...uiTasks.map(t => t.id), ...apiTasks.map(t => t.id))
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Rule 5: Parallel work (no shared entities)
|
|
114
|
+
const parallelizable = allTasks.filter(t => {
|
|
115
|
+
if (t.id === task.id) return false
|
|
116
|
+
const taskEntities = extractEntities(task.description)
|
|
117
|
+
const otherEntities = extractEntities(t.description)
|
|
118
|
+
return taskEntities.every(e => !otherEntities.includes(e))
|
|
119
|
+
})
|
|
120
|
+
dependencies.parallelizable = parallelizable.map(t => t.id)
|
|
121
|
+
|
|
122
|
+
return dependencies
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### 3. Risk Assessment
|
|
129
|
+
|
|
130
|
+
**Risk Factors:**
|
|
131
|
+
```typescript
|
|
132
|
+
function assessRisk(task: Task, complexity: number): RiskLevel {
|
|
133
|
+
let riskScore = 0
|
|
134
|
+
|
|
135
|
+
// Factor 1: Complexity
|
|
136
|
+
if (complexity >= 9) riskScore += 3
|
|
137
|
+
else if (complexity >= 7) riskScore += 2
|
|
138
|
+
else if (complexity >= 5) riskScore += 1
|
|
139
|
+
|
|
140
|
+
// Factor 2: Security-critical
|
|
141
|
+
const securityKeywords = ['auth', 'password', 'token', 'security', 'payment', 'encryption']
|
|
142
|
+
if (securityKeywords.some(kw => task.description.toLowerCase().includes(kw))) {
|
|
143
|
+
riskScore += 3
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Factor 3: External dependencies
|
|
147
|
+
const externalKeywords = ['api', 'third-party', 'service', 'integration', 'library']
|
|
148
|
+
if (externalKeywords.some(kw => task.description.toLowerCase().includes(kw))) {
|
|
149
|
+
riskScore += 1
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Factor 4: Data migration
|
|
153
|
+
if (task.description.match(/migrat|transform|convert/i)) {
|
|
154
|
+
riskScore += 2
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Factor 5: User-facing
|
|
158
|
+
if (task.type === 'uxui-frontend' && task.description.match(/checkout|payment|profile|login/i)) {
|
|
159
|
+
riskScore += 1
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Risk levels
|
|
163
|
+
if (riskScore >= 6) return { level: 'HIGH', score: riskScore, mitigation: [] }
|
|
164
|
+
if (riskScore >= 3) return { level: 'MEDIUM', score: riskScore, mitigation: [] }
|
|
165
|
+
return { level: 'LOW', score: riskScore, mitigation: [] }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function generateMitigation(risk: RiskLevel, task: Task): string[] {
|
|
169
|
+
const mitigation = []
|
|
170
|
+
|
|
171
|
+
if (risk.level === 'HIGH' || risk.level === 'MEDIUM') {
|
|
172
|
+
mitigation.push('TDD required (write tests first)')
|
|
173
|
+
mitigation.push('Code review checkpoint')
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (task.description.match(/auth|security|payment/i)) {
|
|
177
|
+
mitigation.push('Security checklist validation')
|
|
178
|
+
mitigation.push('Use battle-tested libraries (no custom crypto)')
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (task.description.match(/migration|transform/i)) {
|
|
182
|
+
mitigation.push('Backup data before migration')
|
|
183
|
+
mitigation.push('Dry-run test on staging')
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (risk.level === 'HIGH') {
|
|
187
|
+
mitigation.push('Add 50% time buffer')
|
|
188
|
+
mitigation.push('Pair programming recommended')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return mitigation
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 4. Research Requirements Detection
|
|
198
|
+
|
|
199
|
+
> **Integration with /pageplan (v1.4.0):**
|
|
200
|
+
> - `/pageplan` handles: Component reuse analysis + Content drafting + Asset checklist
|
|
201
|
+
> - `TaskMaster` handles: Technical research (libraries, APIs, migrations)
|
|
202
|
+
> - **No overlap:** UX/accessibility research is skipped if `page-plan.md` exists
|
|
203
|
+
|
|
204
|
+
**Decision Matrix:**
|
|
205
|
+
|
|
206
|
+
| Task Type | Has page-plan.md | Research Triggered |
|
|
207
|
+
|-----------|------------------|--------------------|
|
|
208
|
+
| UI Landing | ✅ Yes | ❌ Skip UX patterns<br>❌ Skip accessibility<br>✅ Check library/migration |
|
|
209
|
+
| UI Landing | ❌ No | ✅ UX patterns research<br>✅ Accessibility research<br>✅ Check library |
|
|
210
|
+
| API Integration | ✅ Yes | ✅ Integration research (not affected) |
|
|
211
|
+
| Database Migration | ❌ No | ✅ Migration research (not affected) |
|
|
212
|
+
|
|
213
|
+
**Why this separation?**
|
|
214
|
+
- `/pageplan` = **Design-level** (which components, what content, what assets)
|
|
215
|
+
- `TaskMaster` = **Technical-level** (how to implement, which libraries, what patterns)
|
|
216
|
+
- Avoids redundant "landing page best practices" research when page structure is already planned
|
|
217
|
+
|
|
218
|
+
**Detection Logic:**
|
|
219
|
+
```typescript
|
|
220
|
+
function detectResearchNeeds(task: Task, changeContext: any): ResearchRequirement | null {
|
|
221
|
+
// Check if page-plan.md exists (skip UX/accessibility research)
|
|
222
|
+
const hasPagePlan = fileExists(`.changes/${changeContext.changeId}/page-plan.md`)
|
|
223
|
+
|
|
224
|
+
const researchIndicators = {
|
|
225
|
+
// Technical research (always check)
|
|
226
|
+
newTechnology: /new|latest|modern|upgrade|v\d+/i,
|
|
227
|
+
bestPractices: /best practice|pattern|approach|strategy|how to/i,
|
|
228
|
+
integration: /integrate|connect|setup|configure/i,
|
|
229
|
+
performance: /optimi[sz]e|performance|speed|faster/i,
|
|
230
|
+
migration: /migrat|upgrade|convert/i,
|
|
231
|
+
|
|
232
|
+
// UX research (skip if page-plan exists)
|
|
233
|
+
uxPatterns: hasPagePlan ? null : /dashboard|landing|e-commerce|checkout|wizard|onboarding/i,
|
|
234
|
+
accessibility: hasPagePlan ? null : /form|input|modal|navigation|menu|dialog|button/i,
|
|
235
|
+
|
|
236
|
+
// Design system (always check)
|
|
237
|
+
componentLibrary: /component library|ui library|design system/i,
|
|
238
|
+
designGuidelines: /brand|style|visual|aesthetic|appearance/i
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Check for multiple patterns (prioritize by order)
|
|
242
|
+
const detectedPatterns = []
|
|
243
|
+
|
|
244
|
+
for (const [category, pattern] of Object.entries(researchIndicators)) {
|
|
245
|
+
if (pattern && pattern.test(task.description)) {
|
|
246
|
+
detectedPatterns.push({
|
|
247
|
+
category,
|
|
248
|
+
reason: `Task involves ${category} - requires research phase`,
|
|
249
|
+
suggestedQueries: generateResearchQueries(task, category),
|
|
250
|
+
estimatedTime: getEstimatedResearchTime(category)
|
|
251
|
+
})
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Special case: If no design system exists and UI work detected
|
|
256
|
+
if (task.type === 'uxui-frontend' && !fileExists('design-system/STYLE_GUIDE.md')) {
|
|
257
|
+
detectedPatterns.push({
|
|
258
|
+
category: 'missingDesignSystem',
|
|
259
|
+
reason: 'No design system found - component library selection needed',
|
|
260
|
+
suggestedQueries: [
|
|
261
|
+
'shadcn/ui vs Radix UI comparison 2025',
|
|
262
|
+
'React component library recommendations',
|
|
263
|
+
'Headless UI libraries for Tailwind CSS'
|
|
264
|
+
],
|
|
265
|
+
estimatedTime: 10
|
|
266
|
+
})
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Log skipped research
|
|
270
|
+
if (hasPagePlan && detectedPatterns.length === 0) {
|
|
271
|
+
console.log(`ℹ️ UX/accessibility research skipped (page-plan.md exists)`)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Return highest priority research need
|
|
275
|
+
return detectedPatterns[0] || null
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function getEstimatedResearchTime(category: string): number {
|
|
279
|
+
const timeMap = {
|
|
280
|
+
newTechnology: 15,
|
|
281
|
+
bestPractices: 10,
|
|
282
|
+
integration: 20,
|
|
283
|
+
performance: 10,
|
|
284
|
+
migration: 15,
|
|
285
|
+
uxPatterns: 10,
|
|
286
|
+
accessibility: 5,
|
|
287
|
+
componentLibrary: 10,
|
|
288
|
+
designGuidelines: 5,
|
|
289
|
+
missingDesignSystem: 10
|
|
290
|
+
}
|
|
291
|
+
return timeMap[category] || 15
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function generateResearchQueries(task: Task, category: string): string[] {
|
|
295
|
+
const queries = []
|
|
296
|
+
|
|
297
|
+
if (category === 'newTechnology') {
|
|
298
|
+
queries.push(`Latest version and features of ${extractTechnology(task.description)}`)
|
|
299
|
+
queries.push(`Migration guide from current version`)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (category === 'bestPractices') {
|
|
303
|
+
queries.push(`Best practices for ${extractContext(task.description)}`)
|
|
304
|
+
queries.push(`Common pitfalls and how to avoid them`)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (category === 'integration') {
|
|
308
|
+
const services = extractServices(task.description)
|
|
309
|
+
queries.push(`${services[0]} integration with ${services[1]} guide`)
|
|
310
|
+
queries.push(`Authentication and security considerations`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (category === 'performance') {
|
|
314
|
+
queries.push(`Performance optimization techniques for ${extractContext(task.description)}`)
|
|
315
|
+
queries.push(`Benchmarking and profiling tools`)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (category === 'migration') {
|
|
319
|
+
const tech = extractTechnology(task.description)
|
|
320
|
+
queries.push(`${tech} migration guide 2025`)
|
|
321
|
+
queries.push(`Breaking changes and upgrade path`)
|
|
322
|
+
queries.push(`Data migration strategies and best practices`)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (category === 'uxPatterns') {
|
|
326
|
+
const pageType = extractPageType(task.description)
|
|
327
|
+
queries.push(`${pageType} best practices 2025`)
|
|
328
|
+
queries.push(`${pageType} UX patterns and examples`)
|
|
329
|
+
queries.push(`${pageType} conversion optimization techniques`)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (category === 'accessibility') {
|
|
333
|
+
const component = extractComponent(task.description)
|
|
334
|
+
queries.push(`${component} accessibility best practices`)
|
|
335
|
+
queries.push(`WCAG 2.1 guidelines for ${component}`)
|
|
336
|
+
queries.push(`Screen reader support for ${component}`)
|
|
337
|
+
queries.push(`Keyboard navigation patterns`)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (category === 'componentLibrary') {
|
|
341
|
+
queries.push('shadcn/ui vs Radix UI comparison 2025')
|
|
342
|
+
queries.push('React component library recommendations')
|
|
343
|
+
queries.push('Headless UI libraries for Tailwind CSS')
|
|
344
|
+
queries.push('Component library installation and setup')
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (category === 'designGuidelines') {
|
|
348
|
+
queries.push('Modern design trends 2025')
|
|
349
|
+
queries.push('Color palette generation tools')
|
|
350
|
+
queries.push('Typography pairing recommendations')
|
|
351
|
+
queries.push('Design system structure and organization')
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return queries
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Helper functions
|
|
358
|
+
function extractPageType(desc: string): string {
|
|
359
|
+
const pageTypes = {
|
|
360
|
+
'dashboard': 'Dashboard',
|
|
361
|
+
'landing': 'Landing page',
|
|
362
|
+
'e-commerce': 'E-commerce product page',
|
|
363
|
+
'checkout': 'Checkout flow',
|
|
364
|
+
'wizard': 'Multi-step wizard',
|
|
365
|
+
'onboarding': 'User onboarding'
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
for (const [key, value] of Object.entries(pageTypes)) {
|
|
369
|
+
if (desc.toLowerCase().includes(key)) return value
|
|
370
|
+
}
|
|
371
|
+
return 'Page'
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function extractComponent(desc: string): string {
|
|
375
|
+
const components = ['form', 'input', 'modal', 'navigation', 'menu', 'dialog', 'button', 'table', 'dropdown']
|
|
376
|
+
const found = components.find(c => desc.toLowerCase().includes(c))
|
|
377
|
+
return found ? found.charAt(0).toUpperCase() + found.slice(1) : 'Component'
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
### 5. Subtask Breakdown
|
|
384
|
+
|
|
385
|
+
**When to break down:**
|
|
386
|
+
```typescript
|
|
387
|
+
function needsSubtaskBreakdown(task: Task, complexity: number): boolean {
|
|
388
|
+
// Rule 1: High complexity
|
|
389
|
+
if (complexity >= 7) return true
|
|
390
|
+
|
|
391
|
+
// Rule 2: Multiple verbs (multi-step)
|
|
392
|
+
const verbs = task.description.match(/\b(create|build|implement|design|develop|add|update|refactor)\b/gi)
|
|
393
|
+
if (verbs && verbs.length > 2) return true
|
|
394
|
+
|
|
395
|
+
// Rule 3: Estimated time > 90 minutes
|
|
396
|
+
if (task.estimatedTime > 90) return true
|
|
397
|
+
|
|
398
|
+
// Rule 4: Explicit "and" connectors > 2
|
|
399
|
+
if (task.description.match(/\band\b/gi)?.length > 2) return true
|
|
400
|
+
|
|
401
|
+
return false
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function generateSubtasks(task: Task): Subtask[] {
|
|
405
|
+
const subtasks = []
|
|
406
|
+
|
|
407
|
+
// Pattern 1: UI + Backend pattern
|
|
408
|
+
if (task.description.match(/ui|component|page/i) && task.description.match(/api|backend|endpoint/i)) {
|
|
409
|
+
subtasks.push({
|
|
410
|
+
id: `${task.id}.1`,
|
|
411
|
+
description: `Create UI component for ${extractEntity(task.description)}`,
|
|
412
|
+
type: 'uxui-frontend',
|
|
413
|
+
estimatedTime: 45
|
|
414
|
+
})
|
|
415
|
+
subtasks.push({
|
|
416
|
+
id: `${task.id}.2`,
|
|
417
|
+
description: `Create API endpoint for ${extractEntity(task.description)}`,
|
|
418
|
+
type: 'backend',
|
|
419
|
+
estimatedTime: 30
|
|
420
|
+
})
|
|
421
|
+
subtasks.push({
|
|
422
|
+
id: `${task.id}.3`,
|
|
423
|
+
description: `Integrate UI with API`,
|
|
424
|
+
type: 'frontend',
|
|
425
|
+
estimatedTime: 20
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Pattern 2: CRUD operations
|
|
430
|
+
if (task.description.match(/crud|create.*read.*update.*delete/i)) {
|
|
431
|
+
['Create', 'Read', 'Update', 'Delete'].forEach((op, i) => {
|
|
432
|
+
subtasks.push({
|
|
433
|
+
id: `${task.id}.${i + 1}`,
|
|
434
|
+
description: `Implement ${op} operation for ${extractEntity(task.description)}`,
|
|
435
|
+
type: task.type,
|
|
436
|
+
estimatedTime: 20
|
|
437
|
+
})
|
|
438
|
+
})
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Pattern 3: Multi-entity
|
|
442
|
+
const entities = extractEntities(task.description)
|
|
443
|
+
if (entities.length > 1) {
|
|
444
|
+
entities.forEach((entity, i) => {
|
|
445
|
+
subtasks.push({
|
|
446
|
+
id: `${task.id}.${i + 1}`,
|
|
447
|
+
description: `${task.description.split(' ')[0]} ${entity}`,
|
|
448
|
+
type: task.type,
|
|
449
|
+
estimatedTime: Math.ceil(task.estimatedTime / entities.length)
|
|
450
|
+
})
|
|
451
|
+
})
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
return subtasks
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
### 6. Priority Ranking
|
|
461
|
+
|
|
462
|
+
**Priority Score:**
|
|
463
|
+
```typescript
|
|
464
|
+
function calculatePriority(task: Task, metadata: TaskMetadata): number {
|
|
465
|
+
let priority = 50 // Base priority
|
|
466
|
+
|
|
467
|
+
// Factor 1: Business value (from keywords)
|
|
468
|
+
const criticalKeywords = ['login', 'checkout', 'payment', 'core', 'critical']
|
|
469
|
+
if (criticalKeywords.some(kw => task.description.toLowerCase().includes(kw))) {
|
|
470
|
+
priority += 30
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Factor 2: Blocks other tasks
|
|
474
|
+
priority += metadata.dependencies.blocks.length * 10
|
|
475
|
+
|
|
476
|
+
// Factor 3: No blockers (can start immediately)
|
|
477
|
+
if (metadata.dependencies.blockedBy.length === 0) {
|
|
478
|
+
priority += 20
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Factor 4: Risk (high risk = higher priority to tackle early)
|
|
482
|
+
if (metadata.risk.level === 'HIGH') priority += 15
|
|
483
|
+
if (metadata.risk.level === 'MEDIUM') priority += 5
|
|
484
|
+
|
|
485
|
+
// Factor 5: Complexity (simpler = higher priority for quick wins)
|
|
486
|
+
if (metadata.complexity <= 3) priority += 10
|
|
487
|
+
|
|
488
|
+
// Factor 6: User-facing
|
|
489
|
+
if (task.type === 'uxui-frontend') priority += 10
|
|
490
|
+
|
|
491
|
+
return Math.min(priority, 100)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
function getPriorityLabel(score: number): string {
|
|
495
|
+
if (score >= 80) return 'CRITICAL'
|
|
496
|
+
if (score >= 60) return 'HIGH'
|
|
497
|
+
if (score >= 40) return 'MEDIUM'
|
|
498
|
+
return 'LOW'
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## 📊 Output Format
|
|
505
|
+
|
|
506
|
+
### Enhanced Task Metadata
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
interface TaskMetadata {
|
|
510
|
+
id: string
|
|
511
|
+
title: string
|
|
512
|
+
description: string
|
|
513
|
+
type: AgentType
|
|
514
|
+
|
|
515
|
+
// TaskMaster-style analysis
|
|
516
|
+
complexity: {
|
|
517
|
+
score: number // 1-10
|
|
518
|
+
level: 'Simple' | 'Moderate' | 'Complex' | 'Critical'
|
|
519
|
+
factors: string[] // What contributed to score
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
dependencies: {
|
|
523
|
+
blocks: string[] // Task IDs this blocks
|
|
524
|
+
blockedBy: string[] // Task IDs blocking this
|
|
525
|
+
parallelizable: string[] // Can run in parallel with
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
risk: {
|
|
529
|
+
level: 'LOW' | 'MEDIUM' | 'HIGH'
|
|
530
|
+
score: number
|
|
531
|
+
mitigation: string[] // Risk mitigation strategies
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
research: {
|
|
535
|
+
required: boolean
|
|
536
|
+
category?: string
|
|
537
|
+
queries?: string[]
|
|
538
|
+
estimatedTime?: number
|
|
539
|
+
} | null
|
|
540
|
+
|
|
541
|
+
subtasks: Subtask[] // If needs breakdown
|
|
542
|
+
|
|
543
|
+
priority: {
|
|
544
|
+
score: number // 0-100
|
|
545
|
+
label: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW'
|
|
546
|
+
reason: string
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
estimatedTime: {
|
|
550
|
+
original: number // From OpenSpec
|
|
551
|
+
adjusted: number // With buffer for complexity/risk
|
|
552
|
+
buffer: number // Percentage added
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
## 🔄 Usage in /csetup
|
|
560
|
+
|
|
561
|
+
**Integration Point: STEP 3.5 (after task detection, before template selection)**
|
|
562
|
+
|
|
563
|
+
```typescript
|
|
564
|
+
// STEP 3.5: Analyze Tasks (TaskMaster-style)
|
|
565
|
+
|
|
566
|
+
const tasks = parseTasksFromMd(tasksContent)
|
|
567
|
+
const analyzedTasks = []
|
|
568
|
+
|
|
569
|
+
for (const task of tasks) {
|
|
570
|
+
const complexity = calculateComplexity(task)
|
|
571
|
+
const dependencies = detectDependencies(task, tasks)
|
|
572
|
+
const risk = assessRisk(task, complexity)
|
|
573
|
+
const research = detectResearchNeeds(task)
|
|
574
|
+
const needsBreakdown = needsSubtaskBreakdown(task, complexity)
|
|
575
|
+
const subtasks = needsBreakdown ? generateSubtasks(task) : []
|
|
576
|
+
const priority = calculatePriority(task, { complexity, dependencies, risk })
|
|
577
|
+
|
|
578
|
+
analyzedTasks.push({
|
|
579
|
+
...task,
|
|
580
|
+
complexity: {
|
|
581
|
+
score: complexity,
|
|
582
|
+
level: getComplexityLevel(complexity),
|
|
583
|
+
factors: explainComplexity(task, complexity)
|
|
584
|
+
},
|
|
585
|
+
dependencies,
|
|
586
|
+
risk: {
|
|
587
|
+
...risk,
|
|
588
|
+
mitigation: generateMitigation(risk, task)
|
|
589
|
+
},
|
|
590
|
+
research,
|
|
591
|
+
subtasks,
|
|
592
|
+
priority: {
|
|
593
|
+
score: priority,
|
|
594
|
+
label: getPriorityLabel(priority),
|
|
595
|
+
reason: explainPriority(task, priority)
|
|
596
|
+
},
|
|
597
|
+
estimatedTime: {
|
|
598
|
+
original: task.estimatedTime,
|
|
599
|
+
adjusted: adjustTimeForComplexity(task.estimatedTime, complexity, risk),
|
|
600
|
+
buffer: calculateBuffer(complexity, risk)
|
|
601
|
+
}
|
|
602
|
+
})
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Sort by priority
|
|
606
|
+
analyzedTasks.sort((a, b) => b.priority.score - a.priority.score)
|
|
607
|
+
|
|
608
|
+
// Report analysis
|
|
609
|
+
output(`
|
|
610
|
+
📊 Task Analysis Complete
|
|
611
|
+
|
|
612
|
+
Total tasks: ${analyzedTasks.length}
|
|
613
|
+
Priority breakdown:
|
|
614
|
+
- CRITICAL: ${analyzedTasks.filter(t => t.priority.label === 'CRITICAL').length}
|
|
615
|
+
- HIGH: ${analyzedTasks.filter(t => t.priority.label === 'HIGH').length}
|
|
616
|
+
- MEDIUM: ${analyzedTasks.filter(t => t.priority.label === 'MEDIUM').length}
|
|
617
|
+
- LOW: ${analyzedTasks.filter(t => t.priority.label === 'LOW').length}
|
|
618
|
+
|
|
619
|
+
Risk assessment:
|
|
620
|
+
- HIGH risk: ${analyzedTasks.filter(t => t.risk.level === 'HIGH').length}
|
|
621
|
+
- MEDIUM risk: ${analyzedTasks.filter(t => t.risk.level === 'MEDIUM').length}
|
|
622
|
+
|
|
623
|
+
Research required: ${analyzedTasks.filter(t => t.research?.required).length} tasks
|
|
624
|
+
|
|
625
|
+
Subtask breakdown: ${analyzedTasks.filter(t => t.subtasks.length > 0).length} tasks expanded
|
|
626
|
+
`)
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## 📖 Helper Functions
|
|
632
|
+
|
|
633
|
+
```typescript
|
|
634
|
+
function extractEntity(description: string): string {
|
|
635
|
+
// Extract main entity (User, Post, Comment, etc.)
|
|
636
|
+
const match = description.match(/\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\b/)
|
|
637
|
+
return match ? match[1] : 'entity'
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function extractEntities(description: string): string[] {
|
|
641
|
+
const entities = description.match(/\b([A-Z][a-z]+)\b/g) || []
|
|
642
|
+
return [...new Set(entities)] // Remove duplicates
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function extractTechnology(description: string): string {
|
|
646
|
+
// Extract tech names (React, Next.js, Prisma, etc.)
|
|
647
|
+
const techPattern = /\b(React|Next\.js|Prisma|PostgreSQL|Redis|TypeScript|etc\.)\b/i
|
|
648
|
+
const match = description.match(techPattern)
|
|
649
|
+
return match ? match[1] : 'technology'
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function extractServices(description: string): string[] {
|
|
653
|
+
// Extract service/API names
|
|
654
|
+
const services = description.match(/\b([A-Z][a-z]+(?:\s+API)?)\b/g) || []
|
|
655
|
+
return services.slice(0, 2) // First two
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
function getComplexityLevel(score: number): string {
|
|
659
|
+
if (score <= 3) return 'Simple'
|
|
660
|
+
if (score <= 6) return 'Moderate'
|
|
661
|
+
if (score <= 8) return 'Complex'
|
|
662
|
+
return 'Critical'
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function adjustTimeForComplexity(time: number, complexity: number, risk: RiskLevel): number {
|
|
666
|
+
let adjusted = time
|
|
667
|
+
|
|
668
|
+
// Add buffer for complexity
|
|
669
|
+
if (complexity >= 7) adjusted *= 1.5
|
|
670
|
+
else if (complexity >= 5) adjusted *= 1.3
|
|
671
|
+
|
|
672
|
+
// Add buffer for risk
|
|
673
|
+
if (risk.level === 'HIGH') adjusted *= 1.5
|
|
674
|
+
else if (risk.level === 'MEDIUM') adjusted *= 1.2
|
|
675
|
+
|
|
676
|
+
return Math.ceil(adjusted)
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function calculateBuffer(complexity: number, risk: RiskLevel): number {
|
|
680
|
+
let buffer = 0
|
|
681
|
+
|
|
682
|
+
if (complexity >= 7) buffer += 50
|
|
683
|
+
else if (complexity >= 5) buffer += 30
|
|
684
|
+
|
|
685
|
+
if (risk.level === 'HIGH') buffer += 50
|
|
686
|
+
else if (risk.level === 'MEDIUM') buffer += 20
|
|
687
|
+
|
|
688
|
+
return buffer
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
**This framework transforms simple tasks.md into intelligent, analyzed workflows! 🚀**
|