@hyperdrive.bot/bmad-workflow 1.0.2

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1017 -0
  3. package/bin/dev +5 -0
  4. package/bin/dev.cmd +3 -0
  5. package/bin/dev.js +5 -0
  6. package/bin/run +5 -0
  7. package/bin/run.cmd +3 -0
  8. package/bin/run.js +5 -0
  9. package/dist/commands/config/show.d.ts +34 -0
  10. package/dist/commands/config/show.js +108 -0
  11. package/dist/commands/config/validate.d.ts +29 -0
  12. package/dist/commands/config/validate.js +131 -0
  13. package/dist/commands/decompose.d.ts +79 -0
  14. package/dist/commands/decompose.js +327 -0
  15. package/dist/commands/demo.d.ts +18 -0
  16. package/dist/commands/demo.js +107 -0
  17. package/dist/commands/epics/create.d.ts +123 -0
  18. package/dist/commands/epics/create.js +459 -0
  19. package/dist/commands/epics/list.d.ts +120 -0
  20. package/dist/commands/epics/list.js +280 -0
  21. package/dist/commands/hello/index.d.ts +12 -0
  22. package/dist/commands/hello/index.js +34 -0
  23. package/dist/commands/hello/world.d.ts +8 -0
  24. package/dist/commands/hello/world.js +24 -0
  25. package/dist/commands/prd/fix.d.ts +39 -0
  26. package/dist/commands/prd/fix.js +140 -0
  27. package/dist/commands/prd/validate.d.ts +112 -0
  28. package/dist/commands/prd/validate.js +302 -0
  29. package/dist/commands/stories/create.d.ts +95 -0
  30. package/dist/commands/stories/create.js +431 -0
  31. package/dist/commands/stories/develop.d.ts +91 -0
  32. package/dist/commands/stories/develop.js +460 -0
  33. package/dist/commands/stories/list.d.ts +84 -0
  34. package/dist/commands/stories/list.js +291 -0
  35. package/dist/commands/stories/move.d.ts +66 -0
  36. package/dist/commands/stories/move.js +273 -0
  37. package/dist/commands/stories/qa.d.ts +99 -0
  38. package/dist/commands/stories/qa.js +530 -0
  39. package/dist/commands/workflow.d.ts +97 -0
  40. package/dist/commands/workflow.js +390 -0
  41. package/dist/index.d.ts +1 -0
  42. package/dist/index.js +1 -0
  43. package/dist/models/agent-options.d.ts +50 -0
  44. package/dist/models/agent-options.js +1 -0
  45. package/dist/models/agent-result.d.ts +29 -0
  46. package/dist/models/agent-result.js +1 -0
  47. package/dist/models/index.d.ts +10 -0
  48. package/dist/models/index.js +10 -0
  49. package/dist/models/phase-result.d.ts +65 -0
  50. package/dist/models/phase-result.js +7 -0
  51. package/dist/models/provider.d.ts +28 -0
  52. package/dist/models/provider.js +18 -0
  53. package/dist/models/story.d.ts +154 -0
  54. package/dist/models/story.js +18 -0
  55. package/dist/models/workflow-config.d.ts +148 -0
  56. package/dist/models/workflow-config.js +1 -0
  57. package/dist/models/workflow-result.d.ts +164 -0
  58. package/dist/models/workflow-result.js +7 -0
  59. package/dist/services/agents/agent-runner-factory.d.ts +31 -0
  60. package/dist/services/agents/agent-runner-factory.js +44 -0
  61. package/dist/services/agents/agent-runner.d.ts +46 -0
  62. package/dist/services/agents/agent-runner.js +29 -0
  63. package/dist/services/agents/claude-agent-runner.d.ts +81 -0
  64. package/dist/services/agents/claude-agent-runner.js +332 -0
  65. package/dist/services/agents/gemini-agent-runner.d.ts +82 -0
  66. package/dist/services/agents/gemini-agent-runner.js +350 -0
  67. package/dist/services/agents/index.d.ts +7 -0
  68. package/dist/services/agents/index.js +7 -0
  69. package/dist/services/file-system/file-manager.d.ts +110 -0
  70. package/dist/services/file-system/file-manager.js +223 -0
  71. package/dist/services/file-system/glob-matcher.d.ts +75 -0
  72. package/dist/services/file-system/glob-matcher.js +126 -0
  73. package/dist/services/file-system/path-resolver.d.ts +183 -0
  74. package/dist/services/file-system/path-resolver.js +400 -0
  75. package/dist/services/logging/workflow-logger.d.ts +232 -0
  76. package/dist/services/logging/workflow-logger.js +552 -0
  77. package/dist/services/orchestration/batch-processor.d.ts +113 -0
  78. package/dist/services/orchestration/batch-processor.js +187 -0
  79. package/dist/services/orchestration/dependency-graph-executor.d.ts +60 -0
  80. package/dist/services/orchestration/dependency-graph-executor.js +447 -0
  81. package/dist/services/orchestration/index.d.ts +10 -0
  82. package/dist/services/orchestration/index.js +8 -0
  83. package/dist/services/orchestration/input-detector.d.ts +125 -0
  84. package/dist/services/orchestration/input-detector.js +381 -0
  85. package/dist/services/orchestration/story-queue.d.ts +94 -0
  86. package/dist/services/orchestration/story-queue.js +170 -0
  87. package/dist/services/orchestration/story-type-detector.d.ts +80 -0
  88. package/dist/services/orchestration/story-type-detector.js +258 -0
  89. package/dist/services/orchestration/task-decomposition-service.d.ts +67 -0
  90. package/dist/services/orchestration/task-decomposition-service.js +607 -0
  91. package/dist/services/orchestration/workflow-orchestrator.d.ts +659 -0
  92. package/dist/services/orchestration/workflow-orchestrator.js +2201 -0
  93. package/dist/services/parsers/epic-parser.d.ts +117 -0
  94. package/dist/services/parsers/epic-parser.js +264 -0
  95. package/dist/services/parsers/prd-fixer.d.ts +86 -0
  96. package/dist/services/parsers/prd-fixer.js +194 -0
  97. package/dist/services/parsers/prd-parser.d.ts +123 -0
  98. package/dist/services/parsers/prd-parser.js +286 -0
  99. package/dist/services/parsers/standalone-story-parser.d.ts +114 -0
  100. package/dist/services/parsers/standalone-story-parser.js +255 -0
  101. package/dist/services/parsers/story-parser-factory.d.ts +81 -0
  102. package/dist/services/parsers/story-parser-factory.js +108 -0
  103. package/dist/services/parsers/story-parser.d.ts +122 -0
  104. package/dist/services/parsers/story-parser.js +262 -0
  105. package/dist/services/scaffolding/decompose-session-scaffolder.d.ts +74 -0
  106. package/dist/services/scaffolding/decompose-session-scaffolder.js +315 -0
  107. package/dist/services/scaffolding/file-scaffolder.d.ts +94 -0
  108. package/dist/services/scaffolding/file-scaffolder.js +314 -0
  109. package/dist/services/validation/config-validator.d.ts +88 -0
  110. package/dist/services/validation/config-validator.js +167 -0
  111. package/dist/types/task-graph.d.ts +142 -0
  112. package/dist/types/task-graph.js +5 -0
  113. package/dist/utils/colors.d.ts +49 -0
  114. package/dist/utils/colors.js +50 -0
  115. package/dist/utils/error-formatter.d.ts +64 -0
  116. package/dist/utils/error-formatter.js +279 -0
  117. package/dist/utils/errors.d.ts +170 -0
  118. package/dist/utils/errors.js +233 -0
  119. package/dist/utils/formatters.d.ts +84 -0
  120. package/dist/utils/formatters.js +162 -0
  121. package/dist/utils/logger.d.ts +63 -0
  122. package/dist/utils/logger.js +78 -0
  123. package/dist/utils/progress.d.ts +104 -0
  124. package/dist/utils/progress.js +161 -0
  125. package/dist/utils/retry.d.ts +114 -0
  126. package/dist/utils/retry.js +160 -0
  127. package/dist/utils/shared-flags.d.ts +28 -0
  128. package/dist/utils/shared-flags.js +43 -0
  129. package/package.json +119 -0
@@ -0,0 +1,170 @@
1
+ /**
2
+ * Story Queue
3
+ *
4
+ * Thread-safe queue mechanism for capturing completed stories during the story creation phase
5
+ * and making them available to the development phase. Supports concurrent consumers with
6
+ * async waiting when queue is empty.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import pino from 'pino'
11
+ * import { StoryQueue } from './story-queue.js'
12
+ *
13
+ * const logger = pino()
14
+ * const queue = new StoryQueue(logger)
15
+ *
16
+ * // Producer: enqueue completed stories
17
+ * queue.enqueue(story1)
18
+ * queue.enqueue(story2)
19
+ *
20
+ * // Consumer: dequeue stories for processing
21
+ * const story = await queue.dequeue() // Waits if queue is empty
22
+ * if (story === null) {
23
+ * // Queue is closed and empty
24
+ * return
25
+ * }
26
+ *
27
+ * // When all stories are created, close the queue
28
+ * queue.close()
29
+ * ```
30
+ */
31
+ /**
32
+ * Thread-safe queue for story pipeline coordination.
33
+ *
34
+ * Provides FIFO queueing with async waiting for consumers. Safe for concurrent
35
+ * access in Node.js event loop (no mutex needed due to single-threaded execution).
36
+ */
37
+ export class StoryQueue {
38
+ /**
39
+ * Flag indicating no more stories will be added
40
+ */
41
+ closed = false;
42
+ /**
43
+ * Structured logger instance
44
+ */
45
+ logger;
46
+ /**
47
+ * Internal FIFO queue of stories
48
+ */
49
+ queue = [];
50
+ /**
51
+ * Array of waiting dequeue promises
52
+ */
53
+ waiters = [];
54
+ /**
55
+ * Creates a new StoryQueue instance
56
+ *
57
+ * @param logger - Pino logger for structured logging
58
+ */
59
+ constructor(logger) {
60
+ this.logger = logger;
61
+ this.logger.debug('StoryQueue initialized');
62
+ }
63
+ /**
64
+ * Signals that no more stories will be added to the queue.
65
+ * All waiting dequeue calls will be resolved with null.
66
+ */
67
+ close() {
68
+ if (this.closed) {
69
+ this.logger.warn('Close called on already closed queue');
70
+ return;
71
+ }
72
+ this.closed = true;
73
+ this.logger.info({
74
+ remainingQueueSize: this.queue.length,
75
+ waitersToNotify: this.waiters.length,
76
+ }, 'Queue closed');
77
+ // Wake up all waiting dequeue calls with null
78
+ while (this.waiters.length > 0) {
79
+ const waiter = this.waiters.shift();
80
+ if (waiter) {
81
+ waiter(null);
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Removes and returns the next story from the queue.
87
+ * If queue is empty and not closed, waits asynchronously for a story to be enqueued.
88
+ * If queue is closed and empty, returns null.
89
+ *
90
+ * @returns Promise that resolves to the next story, or null if queue is closed and empty
91
+ */
92
+ async dequeue() {
93
+ // If queue has items, return immediately
94
+ if (this.queue.length > 0) {
95
+ const story = this.queue.shift() ?? null;
96
+ this.logger.info({
97
+ remainingQueueSize: this.queue.length,
98
+ storyNumber: story?.fullNumber,
99
+ storyTitle: story?.title,
100
+ }, 'Story dequeued');
101
+ return story;
102
+ }
103
+ // If closed and empty, return null
104
+ if (this.closed) {
105
+ this.logger.debug({
106
+ closed: this.closed,
107
+ isEmpty: true,
108
+ }, 'Dequeue returning null: queue closed and empty');
109
+ return null;
110
+ }
111
+ // Wait for item or close
112
+ this.logger.debug({
113
+ closed: this.closed,
114
+ isEmpty: this.isEmpty(),
115
+ waiters: this.waiters.length,
116
+ }, 'Dequeue waiting for story');
117
+ return new Promise((resolve) => {
118
+ this.waiters.push(resolve);
119
+ });
120
+ }
121
+ /**
122
+ * Adds a story to the queue
123
+ *
124
+ * @param story - The story to enqueue
125
+ * @throws Error if queue is already closed
126
+ */
127
+ enqueue(story) {
128
+ if (this.closed) {
129
+ const error = new Error('Cannot enqueue to closed queue');
130
+ this.logger.error({
131
+ closed: this.closed,
132
+ storyNumber: story.fullNumber,
133
+ }, 'Enqueue failed: queue closed');
134
+ throw error;
135
+ }
136
+ this.queue.push(story);
137
+ this.logger.info({
138
+ queueSize: this.queue.length,
139
+ storyNumber: story.fullNumber,
140
+ storyTitle: story.title,
141
+ waiters: this.waiters.length,
142
+ }, 'Story enqueued');
143
+ // Wake up a waiting dequeue call if any
144
+ const waiter = this.waiters.shift();
145
+ if (waiter) {
146
+ const dequeuedStory = this.queue.shift() ?? null;
147
+ this.logger.debug({
148
+ remainingQueueSize: this.queue.length,
149
+ storyNumber: dequeuedStory?.fullNumber,
150
+ }, 'Woke up waiting dequeue consumer');
151
+ waiter(dequeuedStory);
152
+ }
153
+ }
154
+ /**
155
+ * Gets the number of pending stories in the queue
156
+ *
157
+ * @returns Number of stories waiting to be dequeued
158
+ */
159
+ getPendingCount() {
160
+ return this.queue.length;
161
+ }
162
+ /**
163
+ * Checks if the queue is empty
164
+ *
165
+ * @returns true if queue has no items, false otherwise
166
+ */
167
+ isEmpty() {
168
+ return this.queue.length === 0;
169
+ }
170
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * StoryTypeDetector Service
3
+ *
4
+ * Analyzes story content to determine if it's frontend, backend, or full-stack work.
5
+ * Used to automatically include relevant documentation references for dev agents.
6
+ */
7
+ import type pino from 'pino';
8
+ /**
9
+ * Story type classification
10
+ */
11
+ export type StoryType = 'backend' | 'frontend' | 'fullstack' | 'unknown';
12
+ /**
13
+ * Detection result with confidence score
14
+ */
15
+ export interface StoryTypeDetection {
16
+ /**
17
+ * Confidence score (0-1)
18
+ */
19
+ confidence: number;
20
+ /**
21
+ * Matched keywords that led to detection
22
+ */
23
+ matchedKeywords: string[];
24
+ /**
25
+ * Detected story type
26
+ */
27
+ type: StoryType;
28
+ }
29
+ /**
30
+ * Configuration for documentation references by story type
31
+ */
32
+ export interface DocumentationReferences {
33
+ backend: string[];
34
+ frontend: string[];
35
+ }
36
+ /**
37
+ * StoryTypeDetector service for analyzing story content
38
+ *
39
+ * Detects whether a story is frontend, backend, or full-stack work
40
+ * by analyzing keywords, file paths, and acceptance criteria.
41
+ */
42
+ export declare class StoryTypeDetector {
43
+ private readonly logger;
44
+ /**
45
+ * Create a new StoryTypeDetector instance
46
+ *
47
+ * @param logger - Logger instance for structured logging
48
+ */
49
+ constructor(logger: pino.Logger);
50
+ /**
51
+ * Detect story type from content
52
+ *
53
+ * Analyzes the story content (title, description, tasks, acceptance criteria)
54
+ * to determine if it's frontend, backend, or full-stack work.
55
+ *
56
+ * @param storyContent - Full story markdown content
57
+ * @returns Detection result with type, confidence, and matched keywords
58
+ */
59
+ detectStoryType(storyContent: string): StoryTypeDetection;
60
+ /**
61
+ * Get documentation references for a story type
62
+ *
63
+ * Returns the appropriate documentation file paths based on the detected story type.
64
+ * Saves tokens by only including relevant documentation.
65
+ *
66
+ * @param storyType - Detected story type
67
+ * @returns Array of documentation file paths to include
68
+ */
69
+ getDocumentationReferences(storyType: StoryType): string[];
70
+ /**
71
+ * Count keyword matches in content
72
+ * @private
73
+ */
74
+ private countKeywordMatches;
75
+ /**
76
+ * Count file path pattern matches
77
+ * @private
78
+ */
79
+ private countPathPatternMatches;
80
+ }
@@ -0,0 +1,258 @@
1
+ /**
2
+ * StoryTypeDetector Service
3
+ *
4
+ * Analyzes story content to determine if it's frontend, backend, or full-stack work.
5
+ * Used to automatically include relevant documentation references for dev agents.
6
+ */
7
+ /**
8
+ * Keywords that indicate frontend work
9
+ */
10
+ const FRONTEND_KEYWORDS = [
11
+ 'frontend',
12
+ 'ui',
13
+ 'component',
14
+ 'react',
15
+ 'amplify',
16
+ 'interface',
17
+ 'page',
18
+ 'view',
19
+ 'form',
20
+ 'button',
21
+ 'modal',
22
+ 'navigation',
23
+ 'routing',
24
+ 'css',
25
+ 'style',
26
+ 'theme',
27
+ 'layout',
28
+ 'responsive',
29
+ 'client-side',
30
+ 'browser',
31
+ 'web app',
32
+ 'user interface',
33
+ 'vite',
34
+ 'typescript react',
35
+ 'tsx',
36
+ 'jsx',
37
+ 'cognito',
38
+ 'authentication ui',
39
+ 'sign-in',
40
+ 'sign-up',
41
+ ];
42
+ /**
43
+ * Keywords that indicate backend work
44
+ */
45
+ const BACKEND_KEYWORDS = [
46
+ 'backend',
47
+ 'api',
48
+ 'endpoint',
49
+ 'handler',
50
+ 'service',
51
+ 'dynamodb',
52
+ 'database',
53
+ 'lambda',
54
+ 'serverless',
55
+ 'middleware',
56
+ 'authentication',
57
+ 'authorization',
58
+ 'rest api',
59
+ 'graphql',
60
+ 's3',
61
+ 'eventbridge',
62
+ 'sqs',
63
+ 'sns',
64
+ 'cognito user pool',
65
+ 'aws sdk',
66
+ 'marshall',
67
+ 'unmarshall',
68
+ 'query command',
69
+ 'put item',
70
+ 'get item',
71
+ 'update item',
72
+ 'delete item',
73
+ 'gsi',
74
+ 'partition key',
75
+ 'sort key',
76
+ 'http status',
77
+ 'error handling',
78
+ 'validation',
79
+ 'business logic',
80
+ ];
81
+ /**
82
+ * File path patterns that indicate frontend work
83
+ */
84
+ const FRONTEND_PATH_PATTERNS = [
85
+ /packages\/web-apps\//i,
86
+ /packages\/entities\/clients\/.*\/repos\//i,
87
+ /src\/components\//i,
88
+ /src\/pages\//i,
89
+ /src\/lib\//i,
90
+ /\.tsx$/i,
91
+ /\.jsx$/i,
92
+ /frontend/i,
93
+ ];
94
+ /**
95
+ * File path patterns that indicate backend work
96
+ */
97
+ const BACKEND_PATH_PATTERNS = [
98
+ /packages\/serverless\/api/i,
99
+ /src\/handlers\//i,
100
+ /src\/services\//i,
101
+ /src\/middleware/i,
102
+ /serverless\.yml$/i,
103
+ /\.handler\.ts$/i,
104
+ /\.service\.ts$/i,
105
+ /backend/i,
106
+ /api/i,
107
+ ];
108
+ /**
109
+ * StoryTypeDetector service for analyzing story content
110
+ *
111
+ * Detects whether a story is frontend, backend, or full-stack work
112
+ * by analyzing keywords, file paths, and acceptance criteria.
113
+ */
114
+ export class StoryTypeDetector {
115
+ logger;
116
+ /**
117
+ * Create a new StoryTypeDetector instance
118
+ *
119
+ * @param logger - Logger instance for structured logging
120
+ */
121
+ constructor(logger) {
122
+ this.logger = logger;
123
+ }
124
+ /**
125
+ * Detect story type from content
126
+ *
127
+ * Analyzes the story content (title, description, tasks, acceptance criteria)
128
+ * to determine if it's frontend, backend, or full-stack work.
129
+ *
130
+ * @param storyContent - Full story markdown content
131
+ * @returns Detection result with type, confidence, and matched keywords
132
+ */
133
+ detectStoryType(storyContent) {
134
+ this.logger.debug('Detecting story type from content');
135
+ // Convert to lowercase for case-insensitive matching
136
+ const contentLower = storyContent.toLowerCase();
137
+ // Count keyword matches
138
+ const frontendMatches = this.countKeywordMatches(contentLower, FRONTEND_KEYWORDS);
139
+ const backendMatches = this.countKeywordMatches(contentLower, BACKEND_KEYWORDS);
140
+ // Check file path patterns
141
+ const frontendPathMatches = this.countPathPatternMatches(storyContent, FRONTEND_PATH_PATTERNS);
142
+ const backendPathMatches = this.countPathPatternMatches(storyContent, BACKEND_PATH_PATTERNS);
143
+ // Calculate weighted scores (keywords count more than paths)
144
+ const frontendScore = frontendMatches.count * 2 + frontendPathMatches.count;
145
+ const backendScore = backendMatches.count * 2 + backendPathMatches.count;
146
+ this.logger.debug({
147
+ backendScore,
148
+ frontendScore,
149
+ }, 'Story type detection scores');
150
+ // Determine type based on scores
151
+ let type;
152
+ let confidence;
153
+ let matchedKeywords;
154
+ if (frontendScore === 0 && backendScore === 0) {
155
+ // No clear indicators
156
+ type = 'unknown';
157
+ confidence = 0;
158
+ matchedKeywords = [];
159
+ }
160
+ else if (frontendScore > backendScore * 2) {
161
+ // Clearly frontend
162
+ type = 'frontend';
163
+ confidence = Math.min(frontendScore / 10, 1);
164
+ matchedKeywords = [...frontendMatches.keywords, ...frontendPathMatches.patterns];
165
+ }
166
+ else if (backendScore > frontendScore * 2) {
167
+ // Clearly backend
168
+ type = 'backend';
169
+ confidence = Math.min(backendScore / 10, 1);
170
+ matchedKeywords = [...backendMatches.keywords, ...backendPathMatches.patterns];
171
+ }
172
+ else {
173
+ // Mixed signals - likely full-stack
174
+ type = 'fullstack';
175
+ confidence = Math.min((frontendScore + backendScore) / 15, 1);
176
+ matchedKeywords = [
177
+ ...frontendMatches.keywords,
178
+ ...backendMatches.keywords,
179
+ ...frontendPathMatches.patterns,
180
+ ...backendPathMatches.patterns,
181
+ ];
182
+ }
183
+ this.logger.info({
184
+ confidence,
185
+ matchedCount: matchedKeywords.length,
186
+ type,
187
+ }, 'Story type detected');
188
+ return {
189
+ confidence,
190
+ matchedKeywords,
191
+ type,
192
+ };
193
+ }
194
+ /**
195
+ * Get documentation references for a story type
196
+ *
197
+ * Returns the appropriate documentation file paths based on the detected story type.
198
+ * Saves tokens by only including relevant documentation.
199
+ *
200
+ * @param storyType - Detected story type
201
+ * @returns Array of documentation file paths to include
202
+ */
203
+ getDocumentationReferences(storyType) {
204
+ const docs = {
205
+ backend: [
206
+ 'docs/api/src/services/service-style-typescript.md',
207
+ 'docs/api/src/handlers/handlers-guide-typescript.md',
208
+ 'docs/api/dynamodb-tables.md',
209
+ 'docs/api/multitenancy-guide.md',
210
+ ],
211
+ frontend: ['docs/frontend-tenant-and-amplify-guide.md', 'docs/api/multitenancy-guide.md'],
212
+ };
213
+ switch (storyType) {
214
+ case 'backend': {
215
+ this.logger.debug('Returning backend documentation references');
216
+ return docs.backend;
217
+ }
218
+ case 'frontend': {
219
+ this.logger.debug('Returning frontend documentation references');
220
+ return docs.frontend;
221
+ }
222
+ case 'fullstack': {
223
+ this.logger.debug('Returning full-stack documentation references (frontend + backend)');
224
+ return [...docs.frontend, ...docs.backend];
225
+ }
226
+ default: {
227
+ this.logger.debug('No documentation references for unknown story type');
228
+ return [];
229
+ }
230
+ }
231
+ }
232
+ /**
233
+ * Count keyword matches in content
234
+ * @private
235
+ */
236
+ countKeywordMatches(content, keywords) {
237
+ const matched = [];
238
+ for (const keyword of keywords) {
239
+ if (content.includes(keyword)) {
240
+ matched.push(keyword);
241
+ }
242
+ }
243
+ return { count: matched.length, keywords: matched };
244
+ }
245
+ /**
246
+ * Count file path pattern matches
247
+ * @private
248
+ */
249
+ countPathPatternMatches(content, patterns) {
250
+ const matched = [];
251
+ for (const pattern of patterns) {
252
+ if (pattern.test(content)) {
253
+ matched.push(pattern.source);
254
+ }
255
+ }
256
+ return { count: matched.length, patterns: matched };
257
+ }
258
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * TaskDecompositionService
3
+ *
4
+ * Decomposes large goals into executable task graphs with dependency management.
5
+ * Leverages Claude AI to intelligently break down complex objectives into
6
+ * small, actionable tasks with proper sequencing and parallelization.
7
+ */
8
+ import type pino from 'pino';
9
+ import type { DecomposeOptions, TaskGraph } from '../../types/task-graph.js';
10
+ import type { AIProviderRunner } from '../agents/agent-runner.js';
11
+ import type { FileManager } from '../file-system/file-manager.js';
12
+ import type { GlobMatcher } from '../file-system/glob-matcher.js';
13
+ /**
14
+ * Service for decomposing goals into task graphs
15
+ */
16
+ export declare class TaskDecompositionService {
17
+ private readonly agentRunner;
18
+ private readonly fileManager;
19
+ private readonly globMatcher;
20
+ private readonly logger;
21
+ constructor(agentRunner: AIProviderRunner, fileManager: FileManager, globMatcher: GlobMatcher, logger: pino.Logger);
22
+ /**
23
+ * Decompose a goal into an executable task graph
24
+ *
25
+ * @param options - Decomposition options including goal, context, and mode
26
+ * @param sessionDir - Directory where session outputs will be stored
27
+ * @returns Complete task graph with dependencies
28
+ */
29
+ decomposeGoal(options: DecomposeOptions, sessionDir: string): Promise<TaskGraph>;
30
+ /**
31
+ * Build the decomposition prompt for Claude
32
+ */
33
+ private buildDecompositionPrompt;
34
+ /**
35
+ * Build execution layers using topological sort (Kahn's algorithm)
36
+ * Each layer contains tasks that can run in parallel
37
+ */
38
+ private buildExecutionLayers;
39
+ /**
40
+ * Detect circular dependencies using DFS
41
+ */
42
+ private detectCircularDependencies;
43
+ /**
44
+ * Extract YAML content from output (handles markdown code fences)
45
+ */
46
+ private extractYaml;
47
+ /**
48
+ * Gather target files using glob pattern
49
+ */
50
+ private gatherTargetFiles;
51
+ /**
52
+ * Generate unique session ID
53
+ */
54
+ private generateSessionId;
55
+ /**
56
+ * Parse Claude's YAML output into a structured TaskGraph
57
+ */
58
+ private parseTaskGraph;
59
+ /**
60
+ * Validate YAML and ask Claude to fix it if invalid
61
+ */
62
+ private validateAndFixYaml;
63
+ /**
64
+ * Validate task graph for common errors
65
+ */
66
+ private validateTaskGraph;
67
+ }